Keyple Card Calypso C++ Library 2.1.0
Reference Terminal Reader API for C++
CmdCardReadRecords.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2022 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
13#include "CmdCardReadRecords.h"
14
15#include <sstream>
16
17/* Keyple Card Calypso */
22
23/* Keyple Core Util */
24#include "ApduUtil.h"
25#include "Arrays.h"
26
27namespace keyple {
28namespace card {
29namespace calypso {
30
31using namespace keyple::core::util;
32using namespace keyple::core::util::cpp;
33
34const CalypsoCardCommand CmdCardReadRecords::mCommand = CalypsoCardCommand::READ_RECORDS;
35const std::map<const int, const std::shared_ptr<StatusProperties>>
36 CmdCardReadRecords::STATUS_TABLE = initStatusTable();
37
39 const uint8_t sfi,
40 const uint8_t firstRecordNumber,
41 const ReadMode readMode,
42 const uint8_t expectedLength)
43: AbstractCardCommand(mCommand),
44 mSfi(sfi),
45 mFirstRecordNumber(firstRecordNumber),
46 mReadMode(readMode)
47{
48 const uint8_t p1 = static_cast<uint8_t>(firstRecordNumber);
49 uint8_t p2 = sfi == 0x00 ? 0x05 : static_cast<uint8_t>((sfi * 8) + 5);
50 if (readMode == ReadMode::ONE_RECORD) {
51 p2 -= 0x01;
52 }
53 const uint8_t le = expectedLength;
54
56 std::make_shared<ApduRequestAdapter>(
57 ApduUtil::build(
58 calypsoCardClass.getValue(), mCommand.getInstructionByte(), p1, p2, le)));
59
60
61 std::stringstream extraInfo;
62 extraInfo << "SFI: " << sfi << "h, "
63 << "REC: " << firstRecordNumber << ", "
64 << "READMODE: " << readMode << ", "
65 << "EXPECTEDLENGTH: " << expectedLength;
66 addSubName(extraInfo.str());
67}
68
70{
71 return false;
72}
73
74const std::map<const int, const std::shared_ptr<StatusProperties>>
75 CmdCardReadRecords::initStatusTable()
76{
77 std::map<const int, const std::shared_ptr<StatusProperties>> m =
79
80 m.insert({0x6981,
81 std::make_shared<StatusProperties>("Command forbidden on binary files",
82 typeid(CardDataAccessException))});
83 m.insert({0x6982,
84 std::make_shared<StatusProperties>("Security conditions not fulfilled (PIN code " \
85 "not presented, encryption required).",
86 typeid(CardSecurityContextException))});
87 m.insert({0x6985,
88 std::make_shared<StatusProperties>("Access forbidden (Never access mode, stored " \
89 "value log file and a stored value operation was" \
90 " done during the current session).",
91 typeid(CardAccessForbiddenException))});
92 m.insert({0x6986,
93 std::make_shared<StatusProperties>("Command not allowed (no current EF)",
94 typeid(CardDataAccessException))});
95 m.insert({0x6A82,
96 std::make_shared<StatusProperties>("File not found",
97 typeid(CardDataAccessException))});
98 m.insert({0x6A83,
99 std::make_shared<StatusProperties>("Record not found (record index is 0, or above " \
100 "NumRec",
101 typeid(CardDataAccessException))});
102 m.insert({0x6B00,
103 std::make_shared<StatusProperties>("P2 value not supported",
104 typeid(CardIllegalParameterException))});
105
106 return m;
107}
108
109const std::map<const int, const std::shared_ptr<StatusProperties>>&
111{
112 return STATUS_TABLE;
113}
114
116 const std::shared_ptr<ApduResponseApi> apduResponse)
117{
119
120 if (apduResponse->getDataOut().size() > 0) {
122 mRecords.insert({mFirstRecordNumber, apduResponse->getDataOut()});
123 } else {
124 const std::vector<uint8_t> mApdu = apduResponse->getDataOut();
125 uint8_t apduLen = static_cast<uint8_t>(mApdu.size());
126 uint8_t index = 0;
127 while (apduLen > 0) {
128 const uint8_t recordNb = mApdu[index++];
129 const uint8_t len = mApdu[index++];
130 mRecords.insert({recordNb, Arrays::copyOfRange(mApdu, index, index + len)});
131 index = index + len;
132 apduLen -= (2 + len);
133 }
134 }
135 }
136
137 return *this;
138}
139
141{
142 return mSfi;
143}
144
146{
147 return mFirstRecordNumber;
148}
149
151{
152 return mReadMode;
153}
154
155const std::map<const uint8_t, const std::vector<uint8_t>>& CmdCardReadRecords::getRecords() const
156{
157 return mRecords;
158}
159
160std::ostream& operator<<(std::ostream& os, const CmdCardReadRecords::ReadMode rm)
161{
162 os << "READ_MODE: ";
163
164 switch (rm) {
166 os << "MULTIPLE_RECORD";
167 break;
169 os << "ONE_RECORD";
170 break;
171 default:
172 os << "UNKNOWN";
173 break;
174 }
175
176 return os;
177}
178
179}
180}
181}
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
AbstractCardCommand & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
static const CalypsoCardCommand READ_RECORDS
CmdCardReadRecords(const CalypsoCardClass calypsoCardClass, const uint8_t sfi, const uint8_t firstRecordNumber, const ReadMode readMode, const uint8_t expectedLength)
const std::map< const uint8_t, const std::vector< uint8_t > > & getRecords() const
const std::map< const int, const std::shared_ptr< StatusProperties > > & getStatusTable() const override
CmdCardReadRecords & setApduResponse(const std::shared_ptr< ApduResponseApi > apduResponse) override
std::ostream & operator<<(std::ostream &os, const std::shared_ptr< ApduRequestAdapter > ara)