16#include "ParseException.h"
19#include "InconsistentDataException.h"
20#include "SelectFileException.h"
21#include "UnexpectedCommandStatusException.h"
36#include "UnsupportedOperationException.h"
42#include "ByteArrayUtil.h"
44#include "IllegalArgumentException.h"
45#include "KeypleAssert.h"
47#include "PatternSyntaxException.h"
53using namespace calypsonet::terminal::card::spi;
54using namespace calypsonet::terminal::calypso::transaction;
55using namespace keyple::core::util;
56using namespace keyple::core::util::cpp;
57using namespace keyple::core::util::cpp::exception;
59const int CalypsoCardSelectionAdapter::AID_MIN_LENGTH = 5;
60const int CalypsoCardSelectionAdapter::AID_MAX_LENGTH = 16;
61const int CalypsoCardSelectionAdapter::SW_CARD_INVALIDATED = 0x6283;
62const std::string CalypsoCardSelectionAdapter::MSG_CARD_COMMAND_ERROR =
63 "A card command error occurred ";
69 const std::string& cardProtocol)
71 Assert::getInstance().notEmpty(cardProtocol,
"cardProtocol");
73 mCardSelector->filterByCardProtocol(cardProtocol);
79 const std::string& powerOnDataRegex)
81 Assert::getInstance().notEmpty(powerOnDataRegex,
"powerOnDataRegex");
84 Pattern::compile(powerOnDataRegex);
85 }
catch (
const PatternSyntaxException& exception) {
87 throw IllegalArgumentException(
"Invalid regular expression: '" +
92 mCardSelector->filterByPowerOnData(powerOnDataRegex);
99 Assert::getInstance().notEmpty(aid,
"aid")
100 .isInRange(aid.size(), AID_MIN_LENGTH, AID_MAX_LENGTH,
"aid");
102 mCardSelector->filterByDfName(aid);
109 Assert::getInstance().isHexString(aid,
"aid format");
119 switch (fileOccurrence) {
120 case FileOccurrence::FIRST:
121 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::FIRST);
123 case FileOccurrence::LAST:
124 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::LAST);
126 case FileOccurrence::NEXT:
127 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::NEXT);
129 case FileOccurrence::PREVIOUS:
130 mCardSelector->setFileOccurrence(CardSelectorSpi::FileOccurrence::PREVIOUS);
140 if (fileControlInformation == FileControlInformation::FCI) {
141 mCardSelector->setFileControlInformation(CardSelectorSpi::FileControlInformation::FCI);
142 }
else if (fileControlInformation == FileControlInformation::NO_RESPONSE) {
143 mCardSelector->setFileControlInformation(
144 CardSelectorSpi::FileControlInformation::NO_RESPONSE);
152 Assert::getInstance().isInRange(statusWord, 0, 0xFFFF,
"statusWord");
154 mCardSelector->addSuccessfulStatusWord(statusWord);
161 mCardSelector->addSuccessfulStatusWord(SW_CARD_INVALIDATED);
167 const uint8_t sfi,
const uint8_t recordNumber)
173 const uint8_t recordNumber)
175 Assert::getInstance().isInRange(sfi,
179 .isInRange(recordNumber,
189 static_cast<uint8_t
>(0)));
198 case GetDataTag::FCI_FOR_CURRENT_DF:
201 case GetDataTag::FCP_FOR_CURRENT_FILE:
204 case GetDataTag::EF_LIST:
207 case GetDataTag::TRACEABILITY_INFORMATION:
212 throw UnsupportedOperationException(
"Unsupported Get Data tag: ");
219 const std::vector<uint8_t>& lid)
221 Assert::getInstance().isEqual(lid.size(), 2,
"lid length");
223 return prepareSelectFile(
static_cast<uint16_t
>(ByteArrayUtil::extractInt(lid, 0, 2,
false)));
230 CalypsoCard::ProductType::PRIME_REVISION_3, lid));
236 const SelectFileControl selectControl)
243const std::shared_ptr<CardSelectionRequestSpi>
246 std::vector<std::shared_ptr<ApduRequestSpi>> cardSelectionApduRequests;
248 if (!mCommands.empty()) {
250 for (
const auto& command : mCommands) {
252 cardSelectionApduRequests.push_back(command->getApduRequest());
255 return std::make_shared<CardSelectionRequestAdapter>(
257 std::make_shared<CardRequestAdapter>(cardSelectionApduRequests,
false));
261 return std::make_shared<CardSelectionRequestAdapter>(mCardSelector,
nullptr);
266 const std::shared_ptr<CardSelectionResponseApi> cardSelectionResponse)
268 const std::shared_ptr<CardResponseApi> cardResponse = cardSelectionResponse->getCardResponse();
270 std::vector<std::shared_ptr<ApduResponseApi>> apduResponses =
271 cardResponse !=
nullptr ?
272 cardResponse->getApduResponses() : std::vector<std::shared_ptr<ApduResponseApi>>();
274 if (mCommands.size() != apduResponses.size()) {
276 throw ParseException(
"Mismatch in the number of requests/responses.");
279 std::shared_ptr<CalypsoCardAdapter> calypsoCard;
283 calypsoCard = std::make_shared<CalypsoCardAdapter>();
284 calypsoCard->initialize(cardSelectionResponse);
286 if (!mCommands.empty()) {
288 parseApduResponses(calypsoCard, mCommands, apduResponses);
291 }
catch (
const Exception& e) {
293 throw ParseException(
"Invalid card response: " + e.getMessage(),
294 std::make_shared<Exception>(e));
297 if (calypsoCard->getProductType() == CalypsoCard::ProductType::UNKNOWN &&
298 cardSelectionResponse->getSelectApplicationResponse() ==
nullptr &&
299 cardSelectionResponse->getPowerOnData() ==
"") {
301 throw ParseException(
"Unable to create a CalypsoCard: no power-on data and no FCI " \
308void CalypsoCardSelectionAdapter::parseApduResponses(
309 const std::shared_ptr<CalypsoCardAdapter> calypsoCard,
310 const std::vector<std::shared_ptr<AbstractApduCommand>>& commands,
311 const std::vector<std::shared_ptr<ApduResponseApi>>& apduResponses)
318 if (apduResponses.size() > commands.size()) {
320 throw InconsistentDataException(
"The number of commands/responses does not match: nb " \
322 std::to_string(commands.size()) +
323 ", nb responses = " +
324 std::to_string(apduResponses.size()));
332 for (
int i = 0; i < static_cast<int>(apduResponses.size()); i++) {
334 auto command = std::dynamic_pointer_cast<AbstractCardCommand>(commands[i]);
338 command->parseApduResponse(apduResponses[i], calypsoCard);
340 }
catch (
const CardCommandException& e) {
342 const CalypsoCardCommand& commandRef =
343 std::dynamic_pointer_cast<AbstractCardCommand>(command)->getCommandRef();
347 (void)
dynamic_cast<const CardDataAccessException&
>(e);
355 if (command->getApduResponse()->getStatusWord() != 0x6A82 &&
356 command->getApduResponse()->getStatusWord() != 0x6A83) {
363 throw SelectFileException(
"File not found",
364 std::make_shared<CardCommandException>(e));
368 throw UnexpectedCommandStatusException(
369 std::string(MSG_CARD_COMMAND_ERROR) +
370 "while processing responses to card commands: " +
371 e.getCommand().getName(),
372 std::make_shared<CardCommandException>(e));
375 }
catch (
const std::bad_cast& ex) {
377 throw UnexpectedCommandStatusException(
378 std::string(MSG_CARD_COMMAND_ERROR) +
379 "while processing responses to card commands: " +
380 e.getCommand().getName(),
381 std::make_shared<CardCommandException>(e));
390 if (apduResponses.size() < commands.size()) {
391 throw InconsistentDataException(
"The number of commands/responses does not match: nb " \
393 std::to_string(commands.size()) +
394 ", nb responses = " +
395 std::to_string(apduResponses.size()));
static const CalypsoCardClass ISO
static const CalypsoCardCommand SELECT_FILE
static const CalypsoCardCommand READ_RECORDS
static const int NB_REC_MAX
static const int NB_REC_MIN
CalypsoCardSelection & filterByPowerOnData(const std::string &powerOnDataRegex) override
CalypsoCardSelection & addSuccessfulStatusWord(const int statusWord) override
CalypsoCardSelection & prepareGetData(const GetDataTag tag) override
CalypsoCardSelection & prepareReadRecordFile(const uint8_t sfi, const uint8_t recordNumber) override
CalypsoCardSelection & setFileOccurrence(const FileOccurrence fileOccurrence) override
CalypsoCardSelectionAdapter()
CalypsoCardSelection & acceptInvalidatedCard() override
CalypsoCardSelection & setFileControlInformation(const FileControlInformation fileControlInformation) override
const std::shared_ptr< SmartCardSpi > parse(const std::shared_ptr< CardSelectionResponseApi > cardSelectionResponse) override
const std::shared_ptr< CardSelectionRequestSpi > getCardSelectionRequest() override
CalypsoCardSelection & prepareReadRecord(const uint8_t sfi, const uint8_t recordNumber) override
CalypsoCardSelection & filterByDfName(const std::vector< uint8_t > &aid) override
CalypsoCardSelection & filterByCardProtocol(const std::string &cardProtocol) override
CalypsoCardSelection & prepareSelectFile(const std::vector< uint8_t > &lid) override
CardSelectorSpi::FileOccurrence FileOccurrence
CardSelectorSpi::FileControlInformation FileControlInformation