Keyple Card Calypso C++ Library 2.1.0
Reference Terminal Reader API for C++
CmdCardSearchRecordMultiple.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
14
15#include <sstream>
16
17/* Keyple Core Util */
18#include "ApduUtil.h"
19#include "Arrays.h"
20#include "ByteArrayUtil.h"
21#include "System.h"
22
23/* Keyple Card Calypso */
29
30namespace keyple {
31namespace card {
32namespace calypso {
33
34using namespace keyple::core::util;
35using namespace keyple::core::util::cpp;
36
37const std::map<const int, const std::shared_ptr<StatusProperties>>
38 CmdCardSearchRecordMultiple::STATUS_TABLE = initStatusTable();
39
41 const CalypsoCardClass calypsoCardClass,
42 const std::shared_ptr<SearchCommandDataAdapter> data)
43: AbstractCardCommand(CalypsoCardCommand::SEARCH_RECORD_MULTIPLE),
44 mData(data)
45{
46 const int searchDataLength = static_cast<int>(data->getSearchData().size());
47 const uint8_t p2 = data->getSfi() * 8 + 7;
48
49 std::vector<uint8_t> dataIn(3 + (2 * searchDataLength));
50 if (data->isEnableRepeatedOffset()) {
51 dataIn[0] = 0x80;
52 }
53
54 if (data->isFetchFirstMatchingResult()) {
55 dataIn[0] |= 1;
56 }
57
58 dataIn[1] = static_cast<uint8_t>(data->getOffset());
59 dataIn[2] = static_cast<uint8_t>(searchDataLength);
60
61 System::arraycopy(data->getSearchData(), 0, dataIn, 3, searchDataLength);
62
63 if (data->getMask().empty()) {
64 /* CL-CMD-SEARCH.1 */
65 Arrays::fill(dataIn,
66 dataIn.size() - searchDataLength,
67 dataIn.size(),
68 static_cast<uint8_t>(0xFF));
69 } else {
70 System::arraycopy(data->getMask(),
71 0,
72 dataIn,
73 dataIn.size() - searchDataLength,
74 data->getMask().size());
75 if (static_cast<int>(data->getMask().size()) != searchDataLength) {
76 /* CL-CMD-SEARCH.1 */
77 Arrays::fill(dataIn,
78 dataIn.size() - searchDataLength + data->getMask().size(),
79 dataIn.size(),
80 static_cast<uint8_t>(0xFF));
81 }
82 }
83
85 std::make_shared<ApduRequestAdapter>(
86 ApduUtil::build(calypsoCardClass.getValue(),
87 getCommandRef().getInstructionByte(),
88 data->getRecordNumber(),
89 p2,
90 dataIn,
91 0)));
92
93 std::stringstream extraInfo;
94 extraInfo << "SFI:" << data->getSfi() << "h, "
95 << "RECORD_NUMBER:" << data->getRecordNumber() << ", "
96 << "OFFSET:" << data->getOffset() << ", "
97 << "REPEATED_OFFSET:" << data->isEnableRepeatedOffset() << ", "
98 << "FETCH_FIRST_RESULT:" << data->isFetchFirstMatchingResult() << ", "
99 << "SEARCH_DATA:" << ByteArrayUtil::toHex(data->getSearchData()) << "h, "
100 << "MASK:" << ByteArrayUtil::toHex(data->getMask()) << "h";
101
102 addSubName(extraInfo.str());
103}
104
106{
107 return false;
108}
109
110const std::map<const int, const std::shared_ptr<StatusProperties>>
111 CmdCardSearchRecordMultiple::initStatusTable()
112{
113 std::map<const int, const std::shared_ptr<StatusProperties>> m =
115
116 m.insert({0x6400,
117 std::make_shared<StatusProperties>("Data Out overflow (outgoing data would be too" \
118 " long).",
120 m.insert({0x6700,
121 std::make_shared<StatusProperties>("Lc value not supported (<4).",
122 typeid(CardIllegalParameterException))});
123 m.insert({0x6981,
124 std::make_shared<StatusProperties>("Incorrect EF type: Binary EF.",
125 typeid(CardDataAccessException))});
126 m.insert({0x6982,
127 std::make_shared<StatusProperties>("Security conditions not fulfilled (PIN code " \
128 "not presented, encryption required).",
129 typeid(CardSecurityContextException))});
130 m.insert({0x6985,
131 std::make_shared<StatusProperties>("Access forbidden (Never access mode, Stored " \
132 "Value log file and a Stored Value operation was" \
133 "done during the current secure session).",
134 typeid(CardAccessForbiddenException))});
135 m.insert({0x6986,
136 std::make_shared<StatusProperties>("Incorrect file type: the Current File is not " \
137 "an EF. Supersedes 6981h.",
138 typeid(CardDataAccessException))});
139 m.insert({0x6A80,
140 std::make_shared<StatusProperties>("Incorrect command data (S. Length incompatible " \
141 "with Lc, S. Length > RecSize, S. Offset + S. " \
142 "Length > RecSize, S. Mask bigger than S. Data).",
143 typeid(CardIllegalParameterException))});
144 m.insert({0x6A82,
145 std::make_shared<StatusProperties>("File not found.",
146 typeid(CardDataAccessException))});
147 m.insert({0x6A83,
148 std::make_shared<StatusProperties>("Record not found (record index is 0, or above " \
149 "NumRec).",
150 typeid(CardDataAccessException))});
151 m.insert({0x6B00,
152 std::make_shared<StatusProperties>("P1 or P2 value not supported.",
153 typeid(CardIllegalParameterException))});
154
155 return m;
156}
157
158const std::map<const int, const std::shared_ptr<StatusProperties>>&
160{
161 return STATUS_TABLE;
162}
163
165 const std::shared_ptr<ApduResponseApi> apduResponse)
166{
168
169 if (apduResponse->getDataOut().size() > 0) {
170 const std::vector<uint8_t> dataOut = apduResponse->getDataOut();
171
172 const int nbRecords = dataOut[0];
173 for (int i = 1; i <= nbRecords; i++) {
174 mData->getMatchingRecordNumbers().push_back(dataOut[i]);
175 }
176
177 if (mData->isFetchFirstMatchingResult() && nbRecords > 0) {
178 mFirstMatchingRecordContent =
179 Arrays::copyOfRange(dataOut, nbRecords + 1, dataOut.size());
180 }
181 }
182
183 return *this;
184}
185
186const std::shared_ptr<SearchCommandDataAdapter> CmdCardSearchRecordMultiple::getSearchCommandData()
187 const
188{
189 return mData;
190}
191
193{
194 return !mFirstMatchingRecordContent.empty() ?
195 mFirstMatchingRecordContent : std::vector<uint8_t>();
196}
197
198}
199}
200}
static const std::map< const int, const std::shared_ptr< StatusProperties > > STATUS_TABLE
virtual void addSubName(const std::string &subName) final
virtual void setApduRequest(const std::shared_ptr< ApduRequestAdapter > apduRequest) final
const CalypsoCardCommand & getCommandRef() const override
AbstractCardCommand & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
const std::vector< uint8_t > getFirstMatchingRecordContent() const
CmdCardSearchRecordMultiple(const CalypsoCardClass calypsoCardClass, const std::shared_ptr< SearchCommandDataAdapter > data)
const std::shared_ptr< SearchCommandDataAdapter > getSearchCommandData() const
CmdCardSearchRecordMultiple & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
const std::map< const int, const std::shared_ptr< StatusProperties > > & getStatusTable() const override