14#include "keyple/card/calypso/CommandSearchRecordMultiple.hpp"
21#include "keyple/card/calypso/CalypsoCardAdapter.hpp"
22#include "keyple/card/calypso/CardAccessForbiddenException.hpp"
23#include "keyple/card/calypso/CardDataAccessException.hpp"
24#include "keyple/card/calypso/CardIllegalParameterException.hpp"
25#include "keyple/card/calypso/CardSecurityContextException.hpp"
26#include "keyple/card/calypso/CardSessionBufferOverflowException.hpp"
27#include "keyple/core/util/ApduUtil.hpp"
28#include "keyple/core/util/HexUtil.hpp"
29#include "keyple/core/util/cpp/Arrays.hpp"
30#include "keyple/core/util/cpp/System.hpp"
36using keyple::core::util::ApduUtil;
37using keyple::core::util::HexUtil;
38using keyple::core::util::cpp::Arrays;
39using keyple::core::util::cpp::System;
41const std::map<int, const std::shared_ptr<Command::StatusProperties>>
42 CommandSearchRecordMultiple::STATUS_TABLE = [] {
43 std::map<int, const std::shared_ptr<Command::StatusProperties>> m(
44 Command::STATUS_TABLE);
48 std::make_shared<Command::StatusProperties>(
49 "Data Out overflow (outgoing data would be too long)",
50 typeid(CardSessionBufferOverflowException))},
52 std::make_shared<Command::StatusProperties>(
53 "Lc value not supported (<4)",
54 typeid(CardIllegalParameterException))},
56 std::make_shared<Command::StatusProperties>(
57 "Incorrect EF type: Binary EF",
58 typeid(CardDataAccessException))},
60 std::make_shared<Command::StatusProperties>(
61 "Security conditions not fulfilled (PIN code not presented, "
62 "encryption required)",
63 typeid(CardSecurityContextException))},
65 std::make_shared<Command::StatusProperties>(
66 "Access forbidden (Never access mode, Stored Value log file "
67 "and a Stored Value operation was done during the current "
69 typeid(CardAccessForbiddenException))},
71 std::make_shared<Command::StatusProperties>(
72 "Incorrect file type: the Current File is not an EF. "
74 typeid(CardDataAccessException))},
76 std::make_shared<Command::StatusProperties>(
77 "Incorrect command data (S. Length incompatible with Lc, S. "
78 "Length > RecSize, S. Offset + S. Length > RecSize, S. Mask "
79 "bigger than S. Data)",
80 typeid(CardIllegalParameterException))},
82 std::make_shared<Command::StatusProperties>(
83 "File not found",
typeid(CardDataAccessException))},
85 std::make_shared<Command::StatusProperties>(
86 "Record not found (record index is 0, or above NumRec",
87 typeid(CardDataAccessException))},
89 std::make_shared<Command::StatusProperties>(
90 "P2 value not supported",
91 typeid(CardIllegalParameterException))}});
96CommandSearchRecordMultiple::CommandSearchRecordMultiple(
97 const std::shared_ptr<DtoAdapters::TransactionContextDto>&
99 const std::shared_ptr<DtoAdapters::CommandContextDto>& commandContext,
100 const std::shared_ptr<DtoAdapters::SearchCommandDataAdapter> data)
102 CardCommandRef::SEARCH_RECORD_MULTIPLE,
108 const int searchDataLength =
static_cast<int>(data->getSearchData().size());
109 const uint8_t p2 = data->getSfi() * 8 + 7;
111 std::vector<uint8_t> dataIn(3 + (2 * searchDataLength));
112 if (data->isEnableRepeatedOffset()) {
116 if (data->isFetchFirstMatchingResult()) {
120 dataIn[1] =
static_cast<uint8_t
>(data->getOffset());
121 dataIn[2] =
static_cast<uint8_t
>(searchDataLength);
123 System::arraycopy(data->getSearchData(), 0, dataIn, 3, searchDataLength);
125 if (data->getMask().empty()) {
129 dataIn.size() - searchDataLength,
131 static_cast<uint8_t
>(0xFF));
138 dataIn.size() - searchDataLength,
139 data->getMask().size());
141 if (
static_cast<int>(data->getMask().size()) != searchDataLength) {
145 dataIn.size() - searchDataLength + data->getMask().size(),
147 static_cast<uint8_t
>(0xFF));
152 setApduRequestInBestEffortMode(
153 std::make_shared<DtoAdapters::ApduRequestAdapter>(ApduUtil::build(
154 transactionContext->getCard()->getCardClass().getValue(),
155 getCommandRef().getInstructionByte(),
156 static_cast<uint8_t
>(data->getRecordNumber()),
161 const std::string extraInfo
162 =
"SFI: " + HexUtil::toHex(data->getSfi())
163 +
"h, Rec: " + std::to_string(data->getRecordNumber()) +
", Offset: "
164 + std::to_string(data->getOffset()) +
", Repeated offset: "
165 + std::to_string(data->isEnableRepeatedOffset())
166 +
", Fetch first result: "
167 + std::to_string(data->isFetchFirstMatchingResult())
168 +
", Search data: " + HexUtil::toHex(data->getSearchData()) +
"h,"
169 +
" Mask: " + HexUtil::toHex(data->getMask()) +
"h";
171 addSubName(extraInfo);
175CommandSearchRecordMultiple::finalizeRequest()
181CommandSearchRecordMultiple::isCryptoServiceRequiredToFinalizeRequest()
const
187CommandSearchRecordMultiple::synchronizeCryptoServiceBeforeCardProcessing()
192const std::map<int, const std::shared_ptr<Command::StatusProperties>>&
193CommandSearchRecordMultiple::getStatusTable()
const
199CommandSearchRecordMultiple::parseResponse(
200 const std::shared_ptr<ApduResponseApi> apduResponse)
202 if (!setApduResponseAndCheckStatusInBestEffortMode(apduResponse)) {
206 const std::vector<uint8_t> dataOut = apduResponse->getDataOut();
207 const int nbRecords = dataOut[0];
209 for (
int i = 1; i <= nbRecords; i++) {
210 mData->getMatchingRecordNumbers().push_back(dataOut[i]);
213 if (mData->isFetchFirstMatchingResult() && nbRecords > 0) {
214 getTransactionContext()->getCard()->setContent(
216 static_cast<uint8_t
>(mData->getMatchingRecordNumbers()[0]),
217 Arrays::copyOfRange(dataOut, nbRecords + 1, dataOut.size()));