From db202fd5b8d38da7abcf29db80a82565ae6137a2 Mon Sep 17 00:00:00 2001 From: Alexandre MUNSCH Date: Sun, 10 Mar 2024 18:20:36 +0100 Subject: [PATCH] feat: upgrade to 2.0.0 Initial commit --- .clang-format | 19 ++--- .clang-tidy | 17 ++-- .cppcheck.suppress | 1 - .github/scripts/check_version.sh | 23 ++++++ .github/scripts/patch_doxyfile.sh | 13 +++ .github/scripts/prepare_doxygen.sh | 41 ++++++++++ .github/workflows/build-and-test.yml | 50 ++++++++++++ .github/workflows/publish-doc-release.yml | 2 +- .github/workflows/publish-to-keypop-doc.yml | 2 +- CMakeLists.txt | 28 ++++--- CPPLINT.cfg | 2 +- README.md | 4 +- include/CMakeLists.txt | 33 +++++--- include/keypop/card/AbstractApduException.hpp | 55 ++++++++----- include/keypop/card/ApduResponseApi.hpp | 69 ++++++++++++---- include/keypop/card/CMakeLists.txt | 24 ------ include/keypop/card/CardApiProperties.hpp | 17 ++-- .../card/CardBrokenCommunicationException.hpp | 37 +++++---- include/keypop/card/CardResponseApi.hpp | 67 +++++++++------- ...ponse.hpp => CardSelectionResponseApi.hpp} | 80 ++++++++++++------- include/keypop/card/ChannelControl.hpp | 21 ++--- include/keypop/card/ParseException.hpp | 46 +++++++---- include/keypop/card/ProxyReaderApi.hpp | 65 +++++++++------ .../ReaderBrokenCommunicationException.hpp | 37 +++++---- .../card/UnexpectedStatusWordException.hpp | 37 +++++---- include/keypop/card/spi/ApduRequestSpi.hpp | 64 ++++++++++----- include/keypop/card/spi/CardRequestSpi.hpp | 32 ++++---- .../card/spi/CardSelectionExtensionSpi.hpp | 35 ++++---- .../card/spi/CardSelectionRequestSpi.hpp | 54 +++++++++---- include/keypop/card/spi/SmartCardSpi.hpp | 17 ++-- include/keypop/mainpage.dox | 2 +- src/CMakeLists.txt | 17 ++-- src/test/CMakeLists.txt | 31 ++++--- src/test/CMakeLists.txt.googletest | 45 +++++++---- src/test/CardApiPropertiesTest.cpp | 17 ++-- src/test/MainTest.cpp | 17 ++-- 36 files changed, 731 insertions(+), 390 deletions(-) create mode 100644 .github/scripts/check_version.sh create mode 100644 .github/scripts/patch_doxyfile.sh create mode 100644 .github/scripts/prepare_doxygen.sh create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 include/keypop/card/CMakeLists.txt rename include/keypop/card/{CardSelectionResponse.hpp => CardSelectionResponseApi.hpp} (62%) rename include/keypop/card/{spi => }/ReaderBrokenCommunicationException.hpp (70%) diff --git a/.clang-format b/.clang-format index 54e9f9d..fe5ea28 100644 --- a/.clang-format +++ b/.clang-format @@ -1,11 +1,12 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ #http://clang.llvm.org/docs/ClangFormatStyleOptions.html @@ -114,7 +115,7 @@ BreakConstructorInitializersBeforeComma: true # A column limit of 0 means that there is no column limit. In this case, # clang-format will respect the input’s line breaking decisions within # statements unless they contradict other rules. -ColumnLimit: 100 +ColumnLimit: 80 # A regular expression that describes comments with special meaning, which # should not be split into lines or otherwise changed. diff --git a/.clang-tidy b/.clang-tidy index bc69f17..7adfeed 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,11 +1,12 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ Checks: '-checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*' WarningsAsErrors: true diff --git a/.cppcheck.suppress b/.cppcheck.suppress index b2fe9e2..f35ba3b 100644 --- a/.cppcheck.suppress +++ b/.cppcheck.suppress @@ -1,3 +1,2 @@ cstyleCast -missingIncludeSystem missingInclude diff --git a/.github/scripts/check_version.sh b/.github/scripts/check_version.sh new file mode 100644 index 0000000..5989d39 --- /dev/null +++ b/.github/scripts/check_version.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +tag=$1 +echo "Input tag: '$tag'" + +version="$(sed -rn 's/.*MAJOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*MINOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*PATCH.*\"(.*)\".*/\1/p' CMakeLists.txt)" + +echo "Version in 'CMakeLists.txt' file: '$version'" + +if [ "$tag" != "" ]; then + echo "Release mode: check version consistency..." + if [ "$tag" != "$version" ]; then + echo "ERROR: the tag '$tag' is different from the version '$version' in the 'CMakeLists.txt' file" + exit 1 + fi +else + echo "Snapshot mode: fetch existing tags..." + git fetch --tags + if [ $(git tag -l "$version") ]; then + echo "ERROR: version '$version' has already been released" + exit 1 + fi +fi diff --git a/.github/scripts/patch_doxyfile.sh b/.github/scripts/patch_doxyfile.sh new file mode 100644 index 0000000..8676210 --- /dev/null +++ b/.github/scripts/patch_doxyfile.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo "Compute the current API version..." +version=$1 + +if [ "$version" = "" ]; then + # SNAPSHOT version + version="$(sed -rn 's/.*MAJOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*MINOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*PATCH.*\"(.*)\".*/\1/p' CMakeLists.txt)-SNAPSHOT" +fi + +echo "Computed current API version: $version" + +sed -i "s/%PROJECT_VERSION%/$version/g" ./.github/doxygen/Doxyfile diff --git a/.github/scripts/prepare_doxygen.sh b/.github/scripts/prepare_doxygen.sh new file mode 100644 index 0000000..f805496 --- /dev/null +++ b/.github/scripts/prepare_doxygen.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +echo "Compute the current API version..." +version=$1 + +if [ "$version" = "" ]; then + # SNAPSHOT version + version="$(sed -rn 's/.*MAJOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*MINOR.*\"(.*)\".*/\1/p' CMakeLists.txt).$(sed -rn 's/.*PATCH.*\"(.*)\".*/\1/p' CMakeLists.txt)-SNAPSHOT" +fi + +echo "Computed current API version: $version" + +repository_name=$(git rev-parse --show-toplevel | xargs basename) + +echo "Clone $repository_name..." +git clone --branch gh-pages https://github.com/eclipse-keypop/"$repository_name".git + +cd "$repository_name" || exit + +echo "Delete existing SNAPSHOT directory..." +rm -rf ./*-SNAPSHOT + +echo "Create target directory $version..." +mkdir "$version" + +echo "Copy Doxygen doc..." +cp -rf ../.github/doxygen/out/html/* "$version"/ + +echo "Update versions list..." +echo "| Version | Documents |" >list_versions.md +echo "|:---:|---|" >>list_versions.md +for directory in $(ls -rd [0-9]*/ | cut -f1 -d'/'); do + echo "| $directory | [API documentation]($directory) |" >>list_versions.md +done + +echo "Computed all versions:" +cat list_versions.md + +cd .. + +echo "Local docs update finished." diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..51bf07d --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,50 @@ +name: Build and test code + +on: + push: + branches: + - main + pull_request: + +jobs: + build: + + strategy: + matrix: + env: + - toolchain: "toolchain/gcc-linux.cmake" + runner: ubuntu-latest + generator: "" + - toolchain: "toolchain/clang-macos.cmake" + runner: macos-latest + generator: "" + - toolchain: "\"toolchain/clang-windows.cmake\"" + runner: windows-latest + generator: "-G \"Visual Studio 17 2022\"" + + runs-on: ${{ matrix.env.runner }} + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Install Linux reqs + if: ${{ matrix.env.runner == 'ubuntu-latest' }} + run: | + sudo apt-get update + sudo apt-get install -y clang cmake cppcheck clang-format clang-tidy gcc pre-commit + + - name: Install macOS reqs + if: ${{ matrix.env.runner == 'macos-latest' }} + run: | + brew install llvm cppcheck clang-format gcc pre-commit + + - name: Build + run: | + cmake ${{ matrix.env.generator }} -B build -S . -DCMAKE_TOOLCHAIN_FILE=${{ matrix.env.toolchain }} + cmake --build build -j8 + + - name: Run Linux/macOS tests + if: ${{ matrix.env.runner == 'ubuntu-latest' || matrix.env.runner == 'macos-latest' }} + run: | + ./build/bin/keypopcard_ut diff --git a/.github/workflows/publish-doc-release.yml b/.github/workflows/publish-doc-release.yml index 70fdd5a..f77e305 100644 --- a/.github/workflows/publish-doc-release.yml +++ b/.github/workflows/publish-doc-release.yml @@ -35,4 +35,4 @@ jobs: git commit -m "docs: update ${{ github.event.inputs.version || github.ref_name }} documentation" git push origin doc --force env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish-to-keypop-doc.yml b/.github/workflows/publish-to-keypop-doc.yml index f819512..708c341 100644 --- a/.github/workflows/publish-to-keypop-doc.yml +++ b/.github/workflows/publish-to-keypop-doc.yml @@ -35,4 +35,4 @@ jobs: with: token: ${{ secrets.ORG_GITHUB_BOT_TOKEN }} repository: eclipse-keypop/keypop-api-docs - event-type: update-submodules \ No newline at end of file + event-type: update-submodules diff --git a/CMakeLists.txt b/CMakeLists.txt index 3489730..e87769d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,25 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ CMAKE_MINIMUM_REQUIRED(VERSION 3.5) - PROJECT(KeypopCardCppApi VERSION 2.0.0 - C CXX) + LANGUAGES C CXX) + +SET(CMAKE_PROJECT_VERSION_MAJOR "2") +SET(CMAKE_PROJECT_VERSION_MINOR "0") +SET(CMAKE_PROJECT_VERSION_PATCH "0") + +SET(CMAKE_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_MAJOR}. + ${CMAKE_PROJECT_VERSION_MINOR}. + ${CMAKE_PROJECT_VERSION_PATCH}") SET(PACKAGE_NAME "keypop-card-cpp-api") SET(PACKAGE_VERSION ${CMAKE_PROJECT_VERSION}) diff --git a/CPPLINT.cfg b/CPPLINT.cfg index 3f61f42..0a3c6f1 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -1,3 +1,3 @@ set noparent filter=-whitespace/indent,-build/c++11 -linelength=120 +linelength=80 diff --git a/README.md b/README.md index 5348042..52611f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keypop Card C++ API ## Overview -This repository contains C++ source files that define component interfaces aligned with the +This repository contains C++ source files that define component interfaces aligned with the [**Terminal Card**](https://terminal-api.calypsonet.org/specifications/reader-layer/card-api/) specifications proposed by the [Calypso Networks Association](https://www.calypsonet.org/). This C++ interface is a port of the [Keypop Card Java API](https://github.com/eclipse-keypop/keypop-card-java-api), which remains @@ -37,4 +37,4 @@ Please adhere to the [Code of Conduct](CODE_OF_CONDUCT.md) when participating in ## License This project is licensed under the [MIT License](LICENSE). For more details, please refer to the [LICENSE](LICENSE) -file. \ No newline at end of file +file. diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index eabb738..24aeecd 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,24 +1,37 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ SET(LIBRARY_NAME keypopcard) # Declare this library as header only. ADD_LIBRARY( + ${LIBRARY_NAME} + INTERFACE ) TARGET_INCLUDE_DIRECTORIES( + ${LIBRARY_NAME} + INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/keypop/card + + ${CMAKE_CURRENT_SOURCE_DIR} ) -ADD_LIBRARY(Keypop::Card ALIAS ${LIBRARY_NAME}) +ADD_LIBRARY( + + Keypop::Card + + ALIAS + + ${LIBRARY_NAME} +) diff --git a/include/keypop/card/AbstractApduException.hpp b/include/keypop/card/AbstractApduException.hpp index 13d7252..6f37c75 100644 --- a/include/keypop/card/AbstractApduException.hpp +++ b/include/keypop/card/AbstractApduException.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -19,8 +20,8 @@ namespace keypop { namespace card { /** - * Generic exception carrying response data received from the card until a communication failure - * occurs or an unexpected APDU status code is received. + * Generic exception carrying response data received from the card until a + * communication failure occurs or an unexpected APDU status code is received. * * @since 1.0.0 */ @@ -30,8 +31,9 @@ class AbstractApduException : public std::exception { * Builds a new exception embedding card response data. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message The message to identify the exception context. * @since 1.0.0 */ @@ -39,17 +41,20 @@ class AbstractApduException : public std::exception { const std::shared_ptr cardResponseApi, const bool isCardResponseComplete, const std::string& message) - : std::exception(message) + : std::exception() + , mMessage(message) , mCardResponseApi(cardResponseApi) , mIsCardResponseComplete(isCardResponseComplete) { } /** - * Builds a new exception embedding card response data with the originating exception. + * Builds a new exception embedding card response data with the originating + * exception. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @param cause The cause * @since 1.0.0 @@ -59,7 +64,8 @@ class AbstractApduException : public std::exception { const bool isCardResponseComplete, const std::string& message, const std::shared_ptr cause) - : std::exception(message, cause) + : std::exception(*cause) + , mMessage(message) , mCardResponseApi(cardResponseApi) , mIsCardResponseComplete(isCardResponseComplete) { } @@ -71,7 +77,7 @@ class AbstractApduException : public std::exception { * @since 1.0.0 */ const std::shared_ptr - getCardResponse() { + getCardResponse() const { return mCardResponseApi; } @@ -87,7 +93,20 @@ class AbstractApduException : public std::exception { return mIsCardResponseComplete; } + /** + * + */ + const std::string& + getMessage() const { + return mMessage; + } + private: + /** + * + */ + const std::string mMessage; + /** * */ diff --git a/include/keypop/card/ApduResponseApi.hpp b/include/keypop/card/ApduResponseApi.hpp index 53354cf..36d5f17 100644 --- a/include/keypop/card/ApduResponseApi.hpp +++ b/include/keypop/card/ApduResponseApi.hpp @@ -1,17 +1,21 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once #include +#include #include #include +#include +#include #include namespace keypop { @@ -36,7 +40,8 @@ class ApduResponseApi { virtual const std::vector& getApdu() const = 0; /** - * Gets the data part of the response received from the card (excluding the status word). + * Gets the data part of the response received from the card (excluding the + * status word). * * @return A not null byte array. * @since 1.0.0 @@ -55,11 +60,26 @@ class ApduResponseApi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::shared_ptr ara) { + operator<<(std::ostream& os, const ApduResponseApi& ara) { + const std::vector apdu = ara.getApdu(); + const std::vector dataOut = ara.getDataOut(); + + std::stringstream ssApdu; + for (const auto val : apdu) { + ssApdu << std::uppercase << std::hex << std::setfill('0') + << std::setw(2) << static_cast(val); + } + + std::stringstream ssDataOut; + for (const auto val : dataOut) { + ssDataOut << std::uppercase << std::hex << std::setfill('0') + << std::setw(2) << static_cast(val); + } + os << "APDU_RESPONSE_API: {" - << "APDU = " << ara->getApdu() << ", " - << "DATA_OUT = " << ara->getDataOut() << ", " - << "STATUS_WORD = " << ara->getStatusWord() << "}"; + << "APDU: " << ssApdu.str() << ", " + << "DATA_OUT: " << ssDataOut.str() << ", " + << "STATUS_WORD: " << ara.getStatusWord() << "}"; return os; } @@ -68,13 +88,28 @@ class ApduResponseApi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::vector>& aras) { + operator<<(std::ostream& os, const std::shared_ptr ara) { + os << *ara.get(); + + return os; + } + + /** + * + */ + friend std::ostream& + operator<<( + std::ostream& os, + const std::vector>& aras) { os << "APDU_RESPONSE_APIS: {"; - for (auto it = aras.begin(); it != aras.end(); ++it) { - if (it != aras.begin()) - os << ", "; + + for (auto it = std::begin(aras); it != std::end(aras); ++it) { os << *it; + if (it != aras.end() - 1) { + os << ", "; + } } + os << "}"; return os; diff --git a/include/keypop/card/CMakeLists.txt b/include/keypop/card/CMakeLists.txt deleted file mode 100644 index eabb738..0000000 --- a/include/keypop/card/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ - -SET(LIBRARY_NAME keypopcard) - -# Declare this library as header only. -ADD_LIBRARY( - ${LIBRARY_NAME} - INTERFACE -) - -TARGET_INCLUDE_DIRECTORIES( - ${LIBRARY_NAME} - INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR}/keypop/card -) - -ADD_LIBRARY(Keypop::Card ALIAS ${LIBRARY_NAME}) diff --git a/include/keypop/card/CardApiProperties.hpp b/include/keypop/card/CardApiProperties.hpp index c95dc0b..21cfd74 100644 --- a/include/keypop/card/CardApiProperties.hpp +++ b/include/keypop/card/CardApiProperties.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once diff --git a/include/keypop/card/CardBrokenCommunicationException.hpp b/include/keypop/card/CardBrokenCommunicationException.hpp index 43255f9..cc8e11d 100644 --- a/include/keypop/card/CardBrokenCommunicationException.hpp +++ b/include/keypop/card/CardBrokenCommunicationException.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -20,8 +21,8 @@ namespace keypop { namespace card { /** - * Exception carrying response data received from the card until a communication failure with the - * card occurs. + * Exception carrying response data received from the card until a communication + * failure with the card occurs. * * @since 1.0.0 */ @@ -31,8 +32,9 @@ class CardBrokenCommunicationException final : public AbstractApduException { * Builds a new exception embedding card response data. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original keypop::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * keypop::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @since 1.0.0 */ @@ -44,11 +46,13 @@ class CardBrokenCommunicationException final : public AbstractApduException { } /** - * Builds a new exception embedding card response data with the originating exception. + * Builds a new exception embedding card response data with the originating + * exception. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original keypop::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * keypop::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @param cause The cause * @since 1.0.0 @@ -58,7 +62,8 @@ class CardBrokenCommunicationException final : public AbstractApduException { const bool isCardResponseComplete, const std::string& message, const std::shared_ptr cause) - : AbstractApduException(cardResponseApi, isCardResponseComplete, message, cause) { + : AbstractApduException( + cardResponseApi, isCardResponseComplete, message, cause) { } }; diff --git a/include/keypop/card/CardResponseApi.hpp b/include/keypop/card/CardResponseApi.hpp index aaeb71a..b979742 100644 --- a/include/keypop/card/CardResponseApi.hpp +++ b/include/keypop/card/CardResponseApi.hpp @@ -1,16 +1,18 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once #include #include +#include #include #include "keypop/card/ApduResponseApi.hpp" @@ -21,17 +23,19 @@ namespace card { /** * Group of multiple APDU responses. * - *

Contains a list of keypop::card::ApduResponseApi received from the card in response to a - * keypop::card::spi::CardRequestSpi and the associated execution status. + *

Contains a list of keypop::card::ApduResponseApi received from the card in + * response to a keypop::card::spi::CardRequestSpi and the associated execution + * status. * - *

The execution status includes the state of the logical channel after the operation and the - * information saying whether a response is present for all APDUs in the - * keypop::card::spi::CardRequestSpi. + *

The execution status includes the state of the logical channel after the + * operation and the information saying whether a response is present for all + * APDUs in the keypop::card::spi::CardRequestSpi. * *

Responses may be missing when this object is embedded in an - * keypop::card::AbstractApduException, for example, if the card is removed durin processing or if - * an unsuccessful status word was received and processing was requested to be stopped in this case - * (see keypop::card::spi::CardRequestSpi::stopOnUnsuccessfulStatusWord()). + * keypop::card::AbstractApduException, for example, if the card is removed + * durin processing or if an unsuccessful status word was received and + * processing was requested to be stopped in this case (see + * keypop::card::spi::CardRequestSpi::stopOnUnsuccessfulStatusWord()). * * @see keypop::card::spi::CardRequestSpi * @since 1.0.0 @@ -49,10 +53,13 @@ class CardResponseApi { * @return A not null list, empty if there is no response. * @since 1.0.0 */ - virtual const std::vector>& getApduResponses() const = 0; + virtual const std::vector>& + getApduResponses() const + = 0; /** - * Gets the state of the logical channel following the execution of the request. + * Gets the state of the logical channel following the execution of the + * request. * * @return True if the logical channel is open. * @since 1.0.0 @@ -63,19 +70,25 @@ class CardResponseApi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::shared_ptr cra) { - os << "CARD_RESPONSE_API: {"; + operator<<(std::ostream& os, const CardResponseApi& cra) { + os << "CARD_RESPONSE_API: {" + << "APDU_RESPONSES: " << cra.getApduResponses() << ", " + << "IS_LOGICAL_CHANNEL_OPEN: " << cra.isLogicalChannelOpen() << "}"; - if (cra == nullptr) { - os << "null"; + return os; + } + + /** + * + */ + friend std::ostream& + operator<<(std::ostream& os, const std::shared_ptr cra) { + if (cra) { + os << *cra.get(); } else { - os << "CARD_RESPONSE_API: {" - << "IS_LOGICAL_CHANNEL_OPEN = " << cra->isLogicalChannelOpen() << ", " - << "APDU_RESPONSES = {" << cra->getApduResponses() << "}"; + os << "CARD_RESPONSE_API: null"; } - os << "}"; - return os; } }; diff --git a/include/keypop/card/CardSelectionResponse.hpp b/include/keypop/card/CardSelectionResponseApi.hpp similarity index 62% rename from include/keypop/card/CardSelectionResponse.hpp rename to include/keypop/card/CardSelectionResponseApi.hpp index 1424e4b..d2528f3 100644 --- a/include/keypop/card/CardSelectionResponse.hpp +++ b/include/keypop/card/CardSelectionResponseApi.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -14,7 +15,6 @@ #include #include -/* Calypsonet Terminal Card */ #include "keypop/card/ApduResponseApi.hpp" #include "keypop/card/CardResponseApi.hpp" @@ -22,12 +22,13 @@ namespace keypop { namespace card { /** - * Data from the start-up phase with the card: selection data and any additional responses. + * Data from the start-up phase with the card: selection data and any additional + * responses. * - *

Includes the status of the selection itself and the responses to any commands that may have - * been executed afterwards. + *

Includes the status of the selection itself and the responses to any + * commands that may have been executed afterwards. * - * @see org::calypsonet.terminal.card.spi.CardSelectionRequestSpi + * @see CardSelectionRequestSpi * @since 1.0.0 */ class CardSelectionResponseApi { @@ -35,20 +36,22 @@ class CardSelectionResponseApi { /** * Gets the card's power-on data. * - *

The power-on data is defined as the data retrieved by the reader when the card is - * inserted. + *

The power-on data is defined as the data retrieved by the reader when + * the card is inserted. * - *

In the case of a contact reader, this is the Answer To Reset data (ATR) defined by - * ISO7816. + *

In the case of a contact reader, this is the Answer To Reset data + * (ATR) defined by ISO7816. * - *

In the case of a contactless reader, the reader decides what this data is.
+ *

In the case of a contactless reader, the reader decides what this data + * is.
* Some contactless readers provide a virtual ATR (partially standardized by the PC/SC - * standard), but other devices can have their own definition, including for example elements - * from the anti-collision stage of the ISO14443 protocol (ATQA, ATQB, ATS, SAK, etc) or any - * proprietary definitions. + * standard), but other devices can have their own definition, including for + * example elements from the anti-collision stage of the ISO14443 protocol + * (ATQA, ATQB, ATS, SAK, etc) or any proprietary definitions. * - *

These data being variable from one reader to another, they are defined here in string - * format which can be either a hexadecimal string or any other relevant information. + *

These data being variable from one reader to another, they are defined + * here in string format which can be either a hexadecimal string or any + * other relevant information. * * @return Null if no power-on data is available. * @since 1.0.0 @@ -56,13 +59,15 @@ class CardSelectionResponseApi { virtual const std::string& getPowerOnData() const = 0; /** - * Gets the calypsonet::terminal::card::ApduResponseApi received from the card in response to + * Gets the calypsonet::terminal::card::ApduResponseApi received from the + * card in response to * the Select Application command. * * @return Null if no Select Application command was performed. * @since 1.0.0 */ - virtual const std::shared_ptr getSelectApplicationResponse() const = 0; + virtual const std::shared_ptr + getSelectApplicationResponse() const = 0; /** * Gives the selection process status. @@ -86,10 +91,11 @@ class CardSelectionResponseApi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::shared_ptr csr) { + operator<<(std::ostream& os, const CardSelectionResponseApi& csr) { os << "CARD_SELECTION_RESPONSE_API: {" - << "HAS_MATCHED: " << csr->hasMatched() << "" - << "}"; + << "HAS_MATCHED: " << csr.hasMatched() << ", " + << "POWER_ON_DATA: " << csr.getPowerOnData() << ", " + << "CARD_RESPONSE: " << csr.getCardResponse() << "}"; return os; } @@ -99,7 +105,23 @@ class CardSelectionResponseApi { */ friend std::ostream& operator<<( - std::ostream& os, const std::vector>& csrs) { + std::ostream& os, const std::shared_ptr csr) { + if (csr) { + os << *csr.get(); + } else { + os << "CARD_SELECTION_RESPONSE_API: null"; + } + + return os; + } + + /** + * + */ + friend std::ostream& + operator<<( + std::ostream& os, + const std::vector>& csrs) { os << "CARD_SELECTION_RESPONSE_APIS: {"; for (auto it = std::begin(csrs); it != std::end(csrs); ++it) { diff --git a/include/keypop/card/ChannelControl.hpp b/include/keypop/card/ChannelControl.hpp index 69cdf2c..1496e63 100644 --- a/include/keypop/card/ChannelControl.hpp +++ b/include/keypop/card/ChannelControl.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -27,8 +28,8 @@ enum class ChannelControl { /** * Terminates communication with the card.
- * The physical channel closes instantly or a card removal sequence is initiated depending on - * the observation mode. + * The physical channel closes instantly or a card removal sequence is + * initiated depending on the observation mode. * * @since 1.0.0 */ diff --git a/include/keypop/card/ParseException.hpp b/include/keypop/card/ParseException.hpp index 87bd74d..e0065aa 100644 --- a/include/keypop/card/ParseException.hpp +++ b/include/keypop/card/ParseException.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -19,8 +20,8 @@ namespace card { /** * Indicates that the parsing of the card selection response has failed. * - *

The most likely reason is that the select application command returned an invalid FCI - * structure. + *

The most likely reason is that the select application command returned an + * invalid FCI structure. * * @since 2.0.0 */ @@ -31,8 +32,8 @@ class ParseException : public std::exception { * @since 1.0.0 */ explicit ParseException(const std::string& message) - : std::exception() { - (void)message; + : std::exception() + , mMessage(message) { } /** @@ -40,10 +41,25 @@ class ParseException : public std::exception { * @param cause The cause. * @since 1.0.0 */ - ParseException(const std::string& message, const std::shared_ptr cause) - : std::exception(*cause) { - (void)message; + ParseException( + const std::string& message, const std::shared_ptr cause) + : std::exception(*cause) + , mMessage(message) { } + + /** + * + */ + const std::string& + getMessage() const { + return mMessage; + } + +private: + /** + * + */ + const std::string mMessage; }; } /* namespace card */ diff --git a/include/keypop/card/ProxyReaderApi.hpp b/include/keypop/card/ProxyReaderApi.hpp index 9d4ee04..89a40b8 100644 --- a/include/keypop/card/ProxyReaderApi.hpp +++ b/include/keypop/card/ProxyReaderApi.hpp @@ -1,25 +1,29 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once #include -#include "keypop/card/CardRequestSpi.hpp" #include "keypop/card/CardResponseApi.hpp" #include "keypop/card/ChannelControl.hpp" +#include "keypop/card/spi/CardRequestSpi.hpp" namespace keypop { namespace card { +using keypop::card::spi::CardRequestSpi; + /** - * Reader able to transmit card requests and having control over the physical channel. + * Reader able to transmit card requests and having control over the physical + * channel. * *

Backside of the keypop::reader::CardReader interface present in the * Terminal Reader API. @@ -38,39 +42,48 @@ class ProxyReaderApi { virtual ~ProxyReaderApi() = default; /** - * Transmits a keypop::card::CardRequestSpi, applies the provided keypop::card::ChannelControl - * policy and returns a keypop::card::CardResponseApi. + * Transmits a keypop::card::CardRequestSpi, applies the provided + * keypop::card::ChannelControl policy and returns a + * keypop::card::CardResponseApi. * *

The APDUs (keypop::card::spi::ApduRequestSpi) contained in the * keypop::card::CardRequestSpi are sent to the card, their responses - * (keypop::card::ApduResponseApi) are added to a new list (keypop::card::CardResponseApi). + * (keypop::card::ApduResponseApi) are added to a new list + * (keypop::card::CardResponseApi). * *

Note: in case of an error when sending an APDU (communication error, unexpected - * status word), an keypop::card::AbstractApduException exception is thrown. Any responses from - * previously transmitted APDU commands are attached to this exception.
- This allows the calling application to be tolerant to card tearing and to retrieve the - partial - * response to the keypop::card::CardRequestSpi or to have strict control over the - * APDUs sent to the card (see keypop::card::CardRequestSpi::stopOnUnsuccessfulStatusWord()). + * status word), an keypop::card::AbstractApduException exception is thrown. + * Any responses from previously transmitted APDU commands are attached to + * this exception.
This allows the calling application to be tolerant to + * card tearing and to retrieve the partial response to the + * keypop::card::CardRequestSpi or to have strict control over the APDUs + * sent to the card (see + * keypop::card::CardRequestSpi::stopOnUnsuccessfulStatusWord()). * * @param cardRequest The card request. * @param channelControl The channel control policy to apply. * @return A not null reference. - * @throw IllegalArgumentException If one of the provided parameters is null. - * @throw ReaderBrokenCommunicationException If the communication with the reader has failed. - * @throw CardBrokenCommunicationException If the communication with the card has failed. - * @throw UnexpectedStatusWordException If any of the APDUs returned an unexpected status word - * and the card request specified the need to check them. + * @throw IllegalArgumentException If one of the provided parameters is + * null. + * @throw ReaderBrokenCommunicationException If the communication with the + * reader has failed. + * @throw CardBrokenCommunicationException If the communication with the + * card has failed. + * @throw UnexpectedStatusWordException If any of the APDUs returned an + * unexpected status word and the card request specified the need to check + * them. * @since 1.0.0 */ virtual const std::shared_ptr transmitCardRequest( - const std::shared_ptr cardRequest, const ChannelControl channelControl) + const std::shared_ptr cardRequest, + const ChannelControl channelControl) = 0; /** * Releases the communication channel previously established with the card. * - * @throw ReaderBrokenCommunicationException If the communication with the reader has failed. + * @throw ReaderBrokenCommunicationException If the communication with the + * reader has failed. * @since 1.0.0 */ virtual void releaseChannel() = 0; diff --git a/include/keypop/card/spi/ReaderBrokenCommunicationException.hpp b/include/keypop/card/ReaderBrokenCommunicationException.hpp similarity index 70% rename from include/keypop/card/spi/ReaderBrokenCommunicationException.hpp rename to include/keypop/card/ReaderBrokenCommunicationException.hpp index 6e603ec..1ecb3ab 100644 --- a/include/keypop/card/spi/ReaderBrokenCommunicationException.hpp +++ b/include/keypop/card/ReaderBrokenCommunicationException.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -20,8 +21,8 @@ namespace keypop { namespace card { /** - * Exception carrying response data received from the card until a communication failure with the - * reader occurs. + * Exception carrying response data received from the card until a communication + * failure with the reader occurs. * * @since 1.0.0 */ @@ -31,8 +32,9 @@ class ReaderBrokenCommunicationException final : public AbstractApduException { * Builds a new exception embedding card response data. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @since 1.0.0 */ @@ -44,11 +46,13 @@ class ReaderBrokenCommunicationException final : public AbstractApduException { } /** - * Builds a new exception embedding card response data with the originating exception. + * Builds a new exception embedding card response data with the originating + * exception. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @param cause The cause * @since 1.0.0 @@ -58,7 +62,8 @@ class ReaderBrokenCommunicationException final : public AbstractApduException { const bool isCardResponseComplete, const std::string& message, const std::shared_ptr cause) - : AbstractApduException(cardResponseApi, isCardResponseComplete, message, cause) { + : AbstractApduException( + cardResponseApi, isCardResponseComplete, message, cause) { } }; diff --git a/include/keypop/card/UnexpectedStatusWordException.hpp b/include/keypop/card/UnexpectedStatusWordException.hpp index 33ad0e0..cc64c1d 100644 --- a/include/keypop/card/UnexpectedStatusWordException.hpp +++ b/include/keypop/card/UnexpectedStatusWordException.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -20,8 +21,8 @@ namespace keypop { namespace card { /** - * Exception carrying response data received from the card until an unexpected APDU status word is - * received. + * Exception carrying response data received from the card until an unexpected + * APDU status word is received. * * @since 1.0.0 */ @@ -31,8 +32,9 @@ class UnexpectedStatusWordException final : public AbstractApduException { * Builds a new exception embedding card response data. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @since 1.0.0 */ @@ -44,11 +46,13 @@ class UnexpectedStatusWordException final : public AbstractApduException { } /** - * Builds a new exception embedding card response data with the originating exception. + * Builds a new exception embedding card response data with the originating + * exception. * * @param cardResponseApi The card responses received so far. - * @param isCardResponseComplete True if the number responses equals the number of requests - * present in the original calypsonet::terminal::card::spi::CardRequestSpi. + * @param isCardResponseComplete True if the number responses equals the + * number of requests present in the original + * calypsonet::terminal::card::spi::CardRequestSpi. * @param message Message to identify the exception context. * @param cause The cause * @since 1.0.0 @@ -58,7 +62,8 @@ class UnexpectedStatusWordException final : public AbstractApduException { const bool isCardResponseComplete, const std::string& message, const std::shared_ptr cause) - : AbstractApduException(cardResponseApi, isCardResponseComplete, message, cause) { + : AbstractApduException( + cardResponseApi, isCardResponseComplete, message, cause) { } }; diff --git a/include/keypop/card/spi/ApduRequestSpi.hpp b/include/keypop/card/spi/ApduRequestSpi.hpp index 7694df1..a9d8896 100644 --- a/include/keypop/card/spi/ApduRequestSpi.hpp +++ b/include/keypop/card/spi/ApduRequestSpi.hpp @@ -1,17 +1,20 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once #include +#include #include #include +#include #include #include @@ -38,10 +41,11 @@ class ApduRequestSpi { * @return A array of at least 4 bytes. * @since 1.0.0 */ - virtual std::vector& getApdu() = 0; + virtual std::vector getApdu() const = 0; /** - * Gets the list of status words that must be considered successful for the APDU. + * Gets the list of status words that must be considered successful for the + * APDU. * * @return A set of integer values containing at least 9000h. * @since 1.0.0 @@ -62,10 +66,28 @@ class ApduRequestSpi { * */ friend std::ostream& - operator<<(std::ostream& os, ApduRequestSpi& ars) { + operator<<(std::ostream& os, const ApduRequestSpi& ars) { + const std::vector apdu = ars.getApdu(); + const std::vector sw = ars.getSuccessfulStatusWords(); + + std::stringstream ssApdu; + for (const auto val : apdu) { + ssApdu << std::uppercase << std::hex << std::setfill('0') + << std::setw(2) << static_cast(val); + } + + std::stringstream ssSw; + for (auto it = std::begin(sw); it != std::end(sw); ++it) { + ssSw << std::uppercase << std::hex << std::setfill('0') + << std::setw(4) << static_cast(*it); + if (it != sw.end() - 1) { + ssSw << ", "; + } + } + os << "APDU_REQUEST_SPI: {" - << "APDU: " << ars.getApdu() << ", " - << "SUCCESSFUL_STATUS_WORDS: " << ars.getSuccessfulStatusWords() << ", " + << "APDU: " << ssApdu.str() << ", " + << "SUCCESSFUL_STATUS_WORD: " << ssSw.str() << ", " << "INFO: " << ars.getInfo() << "}"; return os; @@ -76,11 +98,7 @@ class ApduRequestSpi { */ friend std::ostream& operator<<(std::ostream& os, const std::shared_ptr ars) { - if (ars == nullptr) { - os << "APDU_REQUEST_SPI: null"; - } else { - os << *ars.get(); - } + os << *ars.get(); return os; } @@ -89,14 +107,16 @@ class ApduRequestSpi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::vector>& ars) { + operator<<( + std::ostream& os, + const std::vector>& arss) { os << "APDU_REQUEST_SPIS: {"; - for (auto it = ars.begin(); it != ars.end(); it++) { - if (it != ars.begin()) { + for (auto it = std::begin(arss); it != std::end(arss); ++it) { + os << *it; + if (it != arss.end() - 1) { os << ", "; } - os << *it; } os << "}"; diff --git a/include/keypop/card/spi/CardRequestSpi.hpp b/include/keypop/card/spi/CardRequestSpi.hpp index 530288e..d89f6fc 100644 --- a/include/keypop/card/spi/CardRequestSpi.hpp +++ b/include/keypop/card/spi/CardRequestSpi.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -21,8 +22,9 @@ namespace spi { /** * Request grouping multiple APDUs to be executed consecutively. * - *

Contains a list of {@link ApduRequestSpi} to be sent to a card and a flag indicating whether - * to stop processing in case of an unexpected status word in response to one of the APDUs. + *

Contains a list of {@link ApduRequestSpi} to be sent to a card and a flag + * indicating whether to stop processing in case of an unexpected status word in + * response to one of the APDUs. * * @see calypsonet::terminal::card::ApduResponseApi * @since 1.0.0 @@ -40,13 +42,15 @@ class CardRequestSpi { * @return A not empty list. * @since 1.0.0 */ - virtual const std::vector>& getApduRequests() const = 0; + virtual const std::vector>& + getApduRequests() const = 0; /** - * Indicates if the processing of the requests must stop when an unexpected status word is - * received. + * Indicates if the processing of the requests must stop when an unexpected + * status word is received. * - * @return True if the process must stop at the first unsuccessful status word received. + * @return True if the process must stop at the first unsuccessful status + * word received. * @since 1.0.0 */ virtual bool stopOnUnsuccessfulStatusWord() const = 0; diff --git a/include/keypop/card/spi/CardSelectionExtensionSpi.hpp b/include/keypop/card/spi/CardSelectionExtensionSpi.hpp index 68b491d..2bc9997 100644 --- a/include/keypop/card/spi/CardSelectionExtensionSpi.hpp +++ b/include/keypop/card/spi/CardSelectionExtensionSpi.hpp @@ -1,17 +1,20 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once #include +#include "keypop/card/CardSelectionResponseApi.hpp" #include "keypop/card/spi/CardSelectionRequestSpi.hpp" +#include "keypop/card/spi/SmartCardSpi.hpp" namespace keypop { namespace card { @@ -20,7 +23,8 @@ namespace spi { /** * Extension of the card selection for a specific card extension. * - *

Provides the CardSelectionRequestSpi and interprets the result to provide a SmartCardSpi. + *

Provides the CardSelectionRequestSpi and interprets the result to provide + * a SmartCardSpi. * *

Backside of the org.eclipse.keypop.reader.selection.spi.CardSelectionExtension * interface present in the Keypop Reader API. @@ -37,16 +41,18 @@ class CardSelectionExtensionSpi { virtual ~CardSelectionExtensionSpi() = default; /** - * Gets the card selection request containing the selection data prepared for this selection. + * Gets the card selection request containing the selection data prepared + * for this selection. * * @return A non-null reference. * @since 1.0.0 */ - virtual const std::shared_ptr getCardSelectionRequest() const = 0; + virtual std::shared_ptr + getCardSelectionRequest() const = 0; /** - * Analyzes the response received from the card during the selection process and creates a - * SmartCardSpi. + * Analyzes the response received from the card during the selection process + * and creates a SmartCardSpi. * * @param cardSelectionResponseApi The card selection response. * @return A non-null reference. @@ -54,7 +60,8 @@ class CardSelectionExtensionSpi { * @since 1.0.0 */ virtual std::shared_ptr - parse(const std::shared_ptr cardSelectionResponseApi) const = 0; + parse(const std::shared_ptr + cardSelectionResponseApi) const = 0; }; } /* namespace spi */ diff --git a/include/keypop/card/spi/CardSelectionRequestSpi.hpp b/include/keypop/card/spi/CardSelectionRequestSpi.hpp index f258e22..f7e8a08 100644 --- a/include/keypop/card/spi/CardSelectionRequestSpi.hpp +++ b/include/keypop/card/spi/CardSelectionRequestSpi.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once @@ -13,6 +14,7 @@ #include #include +#include "keyple/core/util/cpp/KeypleStd.hpp" #include "keypop/card/spi/CardRequestSpi.hpp" namespace keypop { @@ -22,8 +24,8 @@ namespace spi { /** * Data provided as input to the selection process. * - *

Embeds a card selector defining the target card profile and an optional card request to be - * executed after the card selection when successful. + *

Embeds a card selector defining the target card profile and an optional + * card request to be executed after the card selection when successful. * * @see calypsonet::terminal::card::CardSelectionResponseApi * @since 1.0.0 @@ -35,6 +37,15 @@ class CardSelectionRequestSpi { */ virtual ~CardSelectionRequestSpi() = default; + /** + * Gets the list of successful selection status words. + * + * @return A set of integer values containing at least 9000h. + * @since 2.0.0 + */ + virtual const std::vector& getSuccessfulSelectionStatusWords() const + = 0; + /** * Gets the card request. * @@ -47,12 +58,22 @@ class CardSelectionRequestSpi { * */ friend std::ostream& - operator<<(std::ostream& os, const std::shared_ptr csr) { - (void)csr; - + operator<<(std::ostream& os, const CardSelectionRequestSpi& csr) { os << "CARD_SELECTION_REQUEST_SPI: {" - << "" - << "}"; + << "SUCCESSFUL_SELECTON_STATUS_WORDS: " + << csr.getSuccessfulSelectionStatusWords() << ", " + << "CARD_REQUEST: " << csr.getCardRequest() << "}"; + + return os; + } + + /** + * + */ + friend std::ostream& + operator<<( + std::ostream& os, const std::shared_ptr csr) { + os << *csr.get(); return os; } @@ -62,7 +83,8 @@ class CardSelectionRequestSpi { */ friend std::ostream& operator<<( - std::ostream& os, const std::vector>& csrs) { + std::ostream& os, + const std::vector>& csrs) { os << "CARD_SELECTION_REQUEST_SPIS: {"; for (auto it = std::begin(csrs); it != std::end(csrs); ++it) { diff --git a/include/keypop/card/spi/SmartCardSpi.hpp b/include/keypop/card/spi/SmartCardSpi.hpp index 799f5cc..76b9606 100644 --- a/include/keypop/card/spi/SmartCardSpi.hpp +++ b/include/keypop/card/spi/SmartCardSpi.hpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #pragma once diff --git a/include/keypop/mainpage.dox b/include/keypop/mainpage.dox index 4875e1b..b8cf9ea 100644 --- a/include/keypop/mainpage.dox +++ b/include/keypop/mainpage.dox @@ -64,4 +64,4 @@ * * - keypop::card::ParseException * Card selection response parsing failure handling - */ \ No newline at end of file + */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7597614..ff19073 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,12 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ # Add projects ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/test) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 1d2c9e2..a5af0a5 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,20 +1,22 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ SET(EXECTUABLE_NAME keypopcard_ut) INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/../../include ) ADD_EXECUTABLE( + ${EXECTUABLE_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/MainTest.cpp @@ -25,4 +27,13 @@ ADD_EXECUTABLE( SET(GOOGLETEST_DIRECTORY ${CMAKE_BINARY_DIR}/bin) INCLUDE(CMakeLists.txt.googletest) -TARGET_LINK_LIBRARIES(${EXECTUABLE_NAME} gtest gmock) +TARGET_LINK_LIBRARIES( + + ${EXECTUABLE_NAME} + + PRIVATE + + gtest + gmock + Keypop::Card +) diff --git a/src/test/CMakeLists.txt.googletest b/src/test/CMakeLists.txt.googletest index 72ff596..57b541d 100644 --- a/src/test/CMakeLists.txt.googletest +++ b/src/test/CMakeLists.txt.googletest @@ -1,28 +1,41 @@ -# ************************************************************************************************* -# Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * -# * -# This program and the accompanying materials are made available under the * -# terms of the MIT License which is available at https://opensource.org/licenses/MIT. * -# * -# SPDX-License-Identifier: MIT * -# *************************************************************************************************/ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ -IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/googletest-build") +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) - MESSAGE("fetching GTest from keypop card") +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/googletest-src") - # FetchContent added in CMake 3.11, downloads during the configure step - # FetchContent_MakeAvailable was added in CMake 3.14; simpler usage - INCLUDE(FetchContent) + MESSAGE("-- > Fetching GTest from keypop card") FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.14.0 ) - # For Windows: Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - FetchContent_MakeAvailable(googletest) +ELSE() + + FetchContent_Declare( + + googletest + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/googletest-src + ) ENDIF() + +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(googletest) diff --git a/src/test/CardApiPropertiesTest.cpp b/src/test/CardApiPropertiesTest.cpp index 2e8422e..27a18e5 100644 --- a/src/test/CardApiPropertiesTest.cpp +++ b/src/test/CardApiPropertiesTest.cpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #include diff --git a/src/test/MainTest.cpp b/src/test/MainTest.cpp index 8773b54..c3bc772 100644 --- a/src/test/MainTest.cpp +++ b/src/test/MainTest.cpp @@ -1,11 +1,12 @@ -/************************************************************************************************** - * Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * - * * - * This program and the accompanying materials are made available under the * - * terms of the MIT License which is available at https://opensource.org/licenses/MIT. * - * * - * SPDX-License-Identifier: MIT * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * This program and the accompanying materials are made available under the * + * terms of the MIT License which is available at * + * https://opensource.org/licenses/MIT. * + * * + * SPDX-License-Identifier: MIT * + ******************************************************************************/ #include "gtest/gtest.h"