Keyple Plugin Stub C++ Library - 2.2.2
Component of the Keyple C++ middleware
StubSmartCard.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * This program and the accompanying materials are made available under the *
5 * terms of the MIT License which is available at *
6 * https://opensource.org/licenses/MIT. *
7 * *
8 * SPDX-License-Identifier: MIT *
9 ******************************************************************************/
10
11#include "keyple/plugin/stub/StubSmartCard.hpp"
12
13#include "keyple/core/plugin/CardIOException.hpp"
14#include "keyple/core/util/HexUtil.hpp"
15#include "keyple/core/util/cpp/KeypleStd.hpp"
16#include "keyple/core/util/cpp/Pattern.hpp"
17
18namespace keyple {
19namespace plugin {
20namespace stub {
21
22using keyple::core::plugin::CardIOException;
23using keyple::core::util::HexUtil;
24using keyple::core::util::cpp::Pattern;
25
26/* BUILDER ------------------------------------------------------------------ */
27
29{
30}
31
32StubSmartCard::SimulatedCommandStep&
33StubSmartCard::Builder::withSimulatedCommand(
34 const std::string& command, const std::string& response)
35{
36 /* Add commands without space */
37 std::string cmd = command;
38 std::string resp = response;
39
40 mHexCommands.insert({std::trim(cmd), std::trim(resp)});
41
42 return *this;
43}
44
45std::shared_ptr<StubSmartCard>
46StubSmartCard::Builder::build()
47{
48 return std::shared_ptr<StubSmartCard>(new StubSmartCard(
49 mPowerOnData, mCardProtocol, mHexCommands, mApduResponseProvider));
50}
51
52StubSmartCard::ProtocolStep&
53StubSmartCard::Builder::withPowerOnData(const std::vector<uint8_t>& powerOnData)
54{
55 mPowerOnData = powerOnData;
56
57 return *this;
58}
59
60StubSmartCard::CommandStep&
61StubSmartCard::Builder::withProtocol(const std::string& protocol)
62{
63 mCardProtocol = protocol;
64
65 return *this;
66}
67
68StubSmartCard::BuildStep&
69StubSmartCard::Builder::withApduResponseProvider(
70 const std::shared_ptr<ApduResponseProviderSpi> apduResponseProvider)
71{
72 mApduResponseProvider = apduResponseProvider;
73
74 return *this;
75}
76
77/* STUB SMARTCARD ----------------------------------------------------------- */
78
79const std::string&
80StubSmartCard::getCardProtocol() const
81{
82 return mCardProtocol;
83}
84
85const std::vector<uint8_t>&
86StubSmartCard::getPowerOnData() const
87{
88 return mPowerOnData;
89}
90
91bool
92StubSmartCard::isPhysicalChannelOpen() const
93{
94 return mIsPhysicalChannelOpen;
95}
96
97void
98StubSmartCard::openPhysicalChannel()
99{
100 mIsPhysicalChannelOpen = true;
101}
102
103void
104StubSmartCard::closePhysicalChannel()
105{
106 mIsPhysicalChannelOpen = false;
107}
108
109const std::vector<uint8_t>
110StubSmartCard::processApdu(const std::vector<uint8_t>& apduIn)
111{
112 if (apduIn.size() == 0) {
113 return std::vector<uint8_t>();
114 }
115
116 /* Convert apduIn to hex */
117 const std::string hexApdu = HexUtil::toHex(apduIn);
118
119 if (mApduResponseProvider != nullptr) {
120 const std::string responseFromRequest
121 = mApduResponseProvider->getResponseFromRequest(hexApdu);
122 if (responseFromRequest != "") {
123 return HexUtil::toByteArray(responseFromRequest);
124 }
125
126 } else if (!mHexCommands.empty()) {
127 /* Return matching hex response if the provided APDU matches the regex
128 */
129 for (const auto& hexCommand : mHexCommands) {
130 std::shared_ptr<Pattern> p = Pattern::compile(hexCommand.first);
131 if (p->matcher(hexApdu)->matches()) {
132 return HexUtil::toByteArray(hexCommand.second);
133 }
134 }
135 }
136
137 /* Throw a CardIOException if not found */
138 throw CardIOException("No response is available for request: " + hexApdu);
139}
140
141std::ostream&
142operator<<(std::ostream& os, const std::shared_ptr<StubSmartCard> ssc)
143{
144 os << "STUB_SMART_CARD: {"
145 << "POWER_ON_DATA = " << HexUtil::toHex(ssc->mPowerOnData) << ", "
146 << "CARD_PROTOCOL = " << ssc->mCardProtocol << ", "
147 << "IS_PHYSICAL_CHANNEL_OPEN = " << ssc->mIsPhysicalChannelOpen << ", "
148 << "HEX_COMMANDS(#) = " << ssc->mHexCommands.size() << "}";
149
150 return os;
151}
152
153std::unique_ptr<StubSmartCard::PowerOnDataStep>
154StubSmartCard::builder()
155{
156 return std::unique_ptr<Builder>(new Builder());
157}
158
159StubSmartCard::StubSmartCard(
160 const std::vector<uint8_t>& powerOnData,
161 const std::string& cardProtocol,
162 const std::map<std::string, std::string>& hexCommands,
163 const std::shared_ptr<ApduResponseProviderSpi> apduResponseProvider)
164: mPowerOnData(powerOnData)
165, mCardProtocol(cardProtocol)
166, mIsPhysicalChannelOpen(false)
167, mHexCommands(hexCommands)
168, mApduResponseProvider(apduResponseProvider)
169{
170}
171
172} /* namespace stub */
173} /* namespace plugin */
174} /* namespace keyple */
std::ostream & operator<<(std::ostream &os, const std::shared_ptr< StubSmartCard > ssc)
StubPluginFactoryBuilder::Builder Builder