diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..2d01d71c9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/CI_build.yml b/.github/workflows/CI_build.yml new file mode 100644 index 000000000..c5201b0c9 --- /dev/null +++ b/.github/workflows/CI_build.yml @@ -0,0 +1,118 @@ +name: CI_build + +on: [push, pull_request] + +jobs: + + build_windows: + + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Ninja"] + + steps: + + - name: Install openssl dev + run: | + choco install openssl --version=3.3.2 + choco install ninja + + - name: Add nmake + uses: ilammy/msvc-dev-cmd@v1 + + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.*' + modules: 'qtscxml qtwebsockets qtshadertools qtconnectivity qtimageformats' + setup-python: 'false' + + - name: generate cmake + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B _build + + - name: build cmake + run: | + cmake --build _build --config ${{ matrix.build_configuration }} --target package + cmake --install _build + + - name: run ctest + run: | + ctest --test-dir _build --output-on-failure -C "${{ matrix.build_configuration }}" + + build_linux: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Unix Makefiles"] + + steps: + - uses: actions/checkout@v4 + + - name: Install packages via apt + run: | + sudo apt update -qq && sudo apt install -y cmake pkg-config libssl-dev libudev-dev libhttp-parser-dev libpcsclite-dev libgl1-mesa-dev qt6-l10n-tools + + # ubuntu 22.04 comes just with QT 6.2.4 and Qt >= 6.4 is required + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.2' + modules: 'qtscxml qtwebsockets qtshadertools qtconnectivity' + setup-python: 'false' + + - name: generate cmake + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B _build + + - name: build cmake + run: | + cmake --build _build --config ${{ matrix.build_configuration }} --target package + sudo cmake --install _build + + - name: run ctest + run: | + ctest --test-dir _build --output-on-failure -C "${{ matrix.build_configuration }}" + + build_macos: + + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Unix Makefiles"] + + steps: + - uses: actions/checkout@v4 + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.2' + modules: 'qtscxml qtwebsockets qtshadertools qtconnectivity qtimageformats' + + - name: generate cmake + run: | + export OPENSSL_ROOT=/usr/local/opt/openssl/bin + export LDFLAGS=-L/usr/local/opt/openssl/lib + export CPPFLAGS=-I/usr/local/opt/openssl/include + export PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig/ + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B _build + + - name: build cmake + run: | + cmake --build _build --config ${{ matrix.build_configuration }} + + - name: run ctest + run: | + ctest --test-dir _build --output-on-failure -C "${{ matrix.build_configuration }}" diff --git a/.github/workflows/CI_build_combined.yml b/.github/workflows/CI_build_combined.yml new file mode 100644 index 000000000..4eeba15c0 --- /dev/null +++ b/.github/workflows/CI_build_combined.yml @@ -0,0 +1,171 @@ +name: CI_build_combined + +on: [push, pull_request] + +env: + BUILD_DIR_LIBS_WIN: "c:/_build_libs" + BUILD_DIR_APP_WIN: "c:/_build" + BUILD_DIR_LIBS: "_build_libs" + BUILD_DIR_APP: "_build" + + +jobs: + build_windows: + + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Ninja"] + + steps: + + - name: Install nmake replacement jom, ninja + run: | + choco install jom ninja + + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Add nmake + uses: ilammy/msvc-dev-cmd@v1 + + - name: generate cmake libs + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B "${{ env.BUILD_DIR_LIBS_WIN }}" D:\a\AusweisApp\AusweisApp\libs + + - name: build cmake libs + run: | + cmake --build "${{ env.BUILD_DIR_LIBS_WIN }}" --config ${{ matrix.build_configuration }} + + - name: generate cmake + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B "${{ env.BUILD_DIR_APP_WIN }}" -DCMAKE_PREFIX_PATH=c:\_build_libs\dist D:\a\AusweisApp\AusweisApp + + - name: build cmake + run: | + cmake --build "${{ env.BUILD_DIR_APP_WIN }}" --config ${{ matrix.build_configuration }} --target package + cmake --install "${{ env.BUILD_DIR_APP_WIN }}" + + - name: run ctest + run: | + ctest --test-dir "${{ env.BUILD_DIR_APP_WIN }}" --output-on-failure -C "${{ matrix.build_configuration }}" + + + + build_linux: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Ninja"] + + steps: + - uses: actions/checkout@v4 + + - name: Install packages via apt + run: | + sudo apt-get update -qq && sudo apt install -y cmake pkg-config libssl-dev libudev-dev libhttp-parser-dev libpcsclite-dev libgl1-mesa-dev libdbus-1-dev libclang-15-dev libclang-14-dev libclang-13-dev ninja-build + + - name: generate cmake libs + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B ${{ env.BUILD_DIR_LIBS }} ./libs + + - name: build cmake libs + run: | + cmake --build ${{ env.BUILD_DIR_LIBS }} --config ${{ matrix.build_configuration }} + + - name: generate cmake + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B ${{ env.BUILD_DIR_APP }} -DCMAKE_PREFIX_PATH=./_build_libs/dist + + - name: build cmake + run: | + cmake --build ${{ env.BUILD_DIR_APP }} --config ${{ matrix.build_configuration }} + sudo cmake --install ${{ env.BUILD_DIR_APP }} + + - name: run ctest + run: | + ctest --test-dir ${{ env.BUILD_DIR_APP }} --output-on-failure -C "${{ matrix.build_configuration }}" + + + build_linux_android: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Unix Makefiles"] + + steps: + - uses: actions/checkout@v4 + + - name: Install packages via apt + run: | + sudo apt-get update -qq && sudo apt install -y cmake pkg-config libssl-dev libudev-dev libhttp-parser-dev libpcsclite-dev libgl1-mesa-dev libdbus-1-dev libclang-15-dev libclang-14-dev libclang-13-dev ninja-build + sudo apt -y remove firefox microsoft-edge-stable google-chrome-stable kotlin libmono* mono-runtime + + - name: generate cmake libs + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -DCMAKE_TOOLCHAIN_FILE=../cmake/android.toolchain.cmake -B ${{ env.BUILD_DIR_LIBS }} ./libs + + - name: build cmake libs + run: | + cmake --build ${{ env.BUILD_DIR_LIBS }} --config ${{ matrix.build_configuration }} + cmake --install ${{ env.BUILD_DIR_LIBS }} + + build_macos: + + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Ninja"] + + steps: + - uses: actions/checkout@v4 + + - name: install ninja + run: | + brew install ninja + + - name: generate cmake libs + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -B ${{ env.BUILD_DIR_LIBS }} ./libs + + - name: build cmake libs + run: | + cmake --build ${{ env.BUILD_DIR_LIBS }} --config ${{ matrix.build_configuration }} + + - name: generate cmake + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -DCMAKE_PREFIX_PATH=./_build_libs/dist -B ${{ env.BUILD_DIR_APP }} + + build_ios: + + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + build_configuration: [Release] + build_platform: ["Unix Makefiles"] + + steps: + - uses: actions/checkout@v4 + + - name: install ninja + run: | + brew install ninja + + - name: generate cmake libs + run: | + cmake -G "${{ matrix.build_platform }}" -DCMAKE_BUILD_TYPE="${{ matrix.build_configuration }}" -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.toolchain.cmake -B ${{ env.BUILD_DIR_LIBS }} ./libs + + - name: build cmake libs + run: | + cmake --build ${{ env.BUILD_DIR_LIBS }} --config ${{ matrix.build_configuration }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c1de2b2a0..3eb6b5491 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,10 +24,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} queries: +security-and-quality @@ -35,10 +35,18 @@ jobs: - name: Install dependencies run: sudo apt update -qq && sudo apt install -y cmake pkg-config libssl-dev libudev-dev libhttp-parser-dev libpcsclite-dev libqt6svg6-dev libqt6websockets6-dev qt6-base-dev qt6-base-private-dev qt6-declarative-dev qt6-connectivity-dev qt6-scxml-dev qt6-tools-dev qt6-tools-dev-tools libqt6opengl6-dev libqt6shadertools6-dev libgl1-mesa-dev qt6-l10n-tools + #QT > 6.4 is required but ubuntu 22.04 just has 6.2.4, so additional installation is needed + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.2' + modules: 'qtscxml qtwebsockets qtshadertools qtconnectivity' + setup-python: 'false' + - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{ matrix.language }}" diff --git a/.qmlformat.ini b/.qmlformat.ini new file mode 100644 index 000000000..3144a533e --- /dev/null +++ b/.qmlformat.ini @@ -0,0 +1,5 @@ +[General] +UseTabs=true +IndentWidth=4 +NewlineType=unix +NormalizeOrder=true diff --git a/.qmllint.ini b/.qmllint.ini new file mode 100644 index 000000000..b50baf511 --- /dev/null +++ b/.qmllint.ini @@ -0,0 +1,47 @@ +[General] +DisableDefaultImports=false + +[Warnings] +AccessSingletonViaObject=warning +BadSignalHandlerParameters=warning +CompilerWarnings=disable +Deprecated=warning +DuplicatePropertyBinding=warning +DuplicatedName=warning +ImportFailure=warning +IncompatibleType=info +InheritanceCycle=warning +InvalidLintDirective=warning +LintPluginWarnings=warning +MissingProperty=info +MissingType=warning +MultilineStrings=warning +NonListProperty=warning +PrefixedImportType=warning +PropertyAliasCycles=warning +ReadOnlyProperty=warning +RequiredProperty=info +RestrictedType=warning +TopLevelComponent=warning +UncreatableType=warning +UnqualifiedAccess=info +UnresolvedType=warning +UnusedImports=info +UseProperFunction=warning +VarUsedBeforeDeclaration=warning +WithStatement=warning + +# Quick +Anchors=info +AttachedPropertyReuse=info +AttachedPropertyType=info +ControlsAttachedPropertyReuse=warning +ControlsNativeCustomize=warning +LayoutsPositioning=info +PropertyChangesParsed=info +UnexpectedVarType=warning + +# Qt 6.5 duplicated categories +Quick.attached-property-type=info +Quick.layout-positioning=info +Quick.property-changes-parsed=info diff --git a/CMakeGraphVizOptions.cmake b/CMakeGraphVizOptions.cmake index ea5d2d78e..2fdae95c6 100644 --- a/CMakeGraphVizOptions.cmake +++ b/CMakeGraphVizOptions.cmake @@ -9,4 +9,3 @@ set(GRAPHVIZ_EXTERNAL_LIBS OFF) set(GRAPHVIZ_EXECUTABLES ON) set(GRAPHVIZ_GENERATE_PER_TARGET OFF) set(GRAPHVIZ_GENERATE_DEPENDERS OFF) -set(GRAPHVIZ_GRAPH_NAME AusweisApp2) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a14c5f91..d48e3b935 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,10 +14,32 @@ else() endif() if(UNIX AND NOT IOS) - set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0 CACHE STRING "Required macOS version") + set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0 CACHE STRING "Required macOS version") endif() -project(AusweisApp VERSION 2.0.1 LANGUAGES ${LANGUAGES}) +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) +else() + set(CMAKE_BUILD_TYPE "DEBUG" CACHE STRING "build type configuration" FORCE) +endif() + +get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(isMultiConfig) + if(NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE}) + endif() + + list(LENGTH CMAKE_CONFIGURATION_TYPES multiConfigCount) + if(NOT multiConfigCount EQUAL 1) + message(FATAL_ERROR "Multi-Config builds are not supported: QTBUG-123340") + endif() +endif() + +project(AusweisApp VERSION 2.2.2 LANGUAGES ${LANGUAGES}) + +if(ANDROID AND NOT GOVERNIKUS_TOOLCHAIN_FILE) + message(FATAL_ERROR "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_DIR}/android.toolchain.cmake is required") +endif() # Set TWEAK if not defined in PROJECT_VERSION above to # have a valid tweak version without propagating it @@ -29,10 +51,6 @@ if(APPLE AND NOT tools.only) enable_language(OBJCXX) endif() -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND (IOS OR ANDROID)) - set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/dist" CACHE PATH "default install path" FORCE) -endif() - option(BUILD_SHARED_LIBS "Enable build of shared libraries") option(INTEGRATED_SDK "Build platform specific SDK" OFF) option(CONTAINER_SDK "Build container specific SDK" OFF) @@ -46,10 +64,8 @@ include(Helper) if(NOT VENDOR) if(EXISTS "${CMAKE_DIR}/Vendor.internal.cmake") include(Vendor.internal) - elseif(LINUX OR BSD) - set(VENDOR "") # Qt uses Organization for paths else() - set(VENDOR AusweisApp_CE) # CommunityEdition + set(VENDOR "") # Qt uses Organization for paths endif() endif() if(VENDOR MATCHES "Governikus") @@ -74,7 +90,7 @@ if(ANDROID) message(STATUS "ANDROID_VERSION_CODE: ${ANDROID_VERSION_CODE}") endif() -if(IOS) +if(IOS OR MAC) if(NOT USE_DISTRIBUTION_PROFILE) set(USE_DISTRIBUTION_PROFILE false) endif() @@ -85,12 +101,6 @@ if("${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}" AND NOT FORCE_SOURCE message(FATAL_ERROR "in tree building is not supported!") endif() -if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) -else() - set(CMAKE_BUILD_TYPE "DEBUG" CACHE STRING "build type configuration" FORCE) -endif() - set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -99,12 +109,16 @@ set(TEST_DIR ${PROJECT_SOURCE_DIR}/test) set(DOCS_DIR ${PROJECT_SOURCE_DIR}/docs) set(RESOURCES_DIR ${PROJECT_SOURCE_DIR}/resources) set(PACKAGING_DIR ${RESOURCES_DIR}/packaging) -set(COPYRIGHT_TEXT "2014-2023 ${VENDOR}") +set(COPYRIGHT_TEXT "2014-2024 ${VENDOR}") if(APPLE) string(REPLACE " \& " " \& " COPYRIGHT_TEXT ${COPYRIGHT_TEXT}) endif() set(BUNDLE_IDENTIFIER com.governikus.ausweisapp2) +if(NOT CONTAINER_SDK) + include(CTest) +endif() + include(Tools) include(DVCS) add_subdirectory(docs) @@ -116,28 +130,10 @@ if(tools.only) return() endif() -if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND NOT CONTAINER_SDK) - set(VALGRIND_SUPPRESSIONS "${CMAKE_PREFIX_PATH}/test/valgrind.supp") - if(NOT EXISTS "${VALGRIND_SUPPRESSIONS}") - set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/libs/test/valgrind.supp") - endif() - message(STATUS "Using valgrind suppressions: ${VALGRIND_SUPPRESSIONS}") - set(VALGRIND_COMMAND_OPTIONS "--tool=memcheck --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=1 --gen-suppressions=all --suppressions=${VALGRIND_SUPPRESSIONS}") - - include(CTest) - configure_file("${CMAKE_DIR}/CTestCustom.cmake.in" "${CMAKE_BINARY_DIR}/CTestCustom.cmake" @ONLY) - - set(SONAR_CACHE_DIR ${CMAKE_BINARY_DIR}/../cache) - if(NOT EXISTS "${SONAR_CACHE_DIR}") - set(SONAR_CACHE_DIR ${CMAKE_BINARY_DIR}) - endif() - get_filename_component(SONAR_CACHE_DIR ${SONAR_CACHE_DIR} ABSOLUTE) - configure_file("${RESOURCES_DIR}/sonar-project.properties.in" "${CMAKE_BINARY_DIR}/sonar-project.properties" @ONLY) -endif() - option(USE_SMARTEID "Enable Smart-eID" OFF) include(Libraries) +include(PoliciesQt) include(Tools.Libraries) include(CompilerFlags) @@ -147,8 +143,7 @@ endif() add_subdirectory(resources) add_subdirectory(src) - -if(TARGET ${Qt}::Test AND NOT IOS) +if(BUILD_TESTING) add_subdirectory(test) endif() @@ -158,5 +153,23 @@ endif() include(Packaging) +if(BUILD_TESTING) + set(VALGRIND_SUPPRESSIONS "${CMAKE_PREFIX_PATH}/test/valgrind.supp") + if(NOT EXISTS "${VALGRIND_SUPPRESSIONS}") + set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/libs/test/valgrind.supp") + endif() + message(STATUS "Using valgrind suppressions: ${VALGRIND_SUPPRESSIONS}") + set(VALGRIND_COMMAND_OPTIONS "--tool=memcheck --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=1 --gen-suppressions=all --suppressions=${VALGRIND_SUPPRESSIONS}") + + configure_file("${CMAKE_DIR}/CTestCustom.cmake.in" "${CMAKE_BINARY_DIR}/CTestCustom.cmake" @ONLY) + + set(SONAR_CACHE_DIR ${CMAKE_BINARY_DIR}/../cache) + if(NOT EXISTS "${SONAR_CACHE_DIR}") + set(SONAR_CACHE_DIR ${CMAKE_BINARY_DIR}) + endif() + get_filename_component(SONAR_CACHE_DIR ${SONAR_CACHE_DIR} ABSOLUTE) + configure_file("${RESOURCES_DIR}/sonar-project.properties.in" "${CMAKE_BINARY_DIR}/sonar-project.properties" @ONLY) +endif() + include(FeatureSummary) FEATURE_SUMMARY(WHAT ALL) diff --git a/CMakePresets.json b/CMakePresets.json index 02c4485b2..2e6adebe1 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,263 +1,17 @@ { - "version": 3, + "version": 6, "cmakeMinimumRequired": { "major": 3, - "minor": 21, + "minor": 25, "patch": 0 }, - "configurePresets": [ - { - "name": "ci", - "hidden": true, - "generator": "Ninja", - "binaryDir": "${sourceParentDir}/build", - "cacheVariables": { - "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" - } - }, - { - "name": "ci-with-libs", - "hidden": true, - "inherits": "ci", - "cacheVariables": { - "CMAKE_PREFIX_PATH": "${sourceParentDir}/libs/build/dist" - } - }, - { - "name": "ci-win", - "inherits": "ci-with-libs" - }, - { - "name": "ci-win-release", - "inherits": "ci-win", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel", - "WIN_SIGN_KEYSTORE": "$env{WIN_SIGN_KEYSTORE}", - "WIN_SIGN_KEYSTORE_PSW": "$env{WIN_SIGN_KEYSTORE_PSW}", - "WIN_SIGN_SUBJECT_NAME": "$env{WIN_SIGN_SUBJECT_NAME}" - } - }, - { - "name": "ci-win-debug", - "inherits": "ci-win", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "DEBUG", - "WIN_SIGN_KEYSTORE": "$env{WIN_SIGN_KEYSTORE}", - "WIN_SIGN_KEYSTORE_PSW": "$env{WIN_SIGN_KEYSTORE_PSW}", - "WIN_SIGN_SUBJECT_NAME": "$env{WIN_SIGN_SUBJECT_NAME}" - } - }, - { - "name": "ci-macos", - "inherits": "ci-with-libs", - "generator": "Xcode", - "cacheVariables": { - "BUILD_SHARED_LIBS": "ON", - "SANITIZER": "ON" - } - }, - { - "name": "ci-macos-release", - "inherits": "ci-with-libs", - "generator": "Xcode", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel" - } - }, - { - "name": "ci-macos-integrated", - "inherits": "ci-with-libs", - "cacheVariables": { - "INTEGRATED_SDK": "ON", - "SANITIZER": "ON" - } - }, - { - "name": "ci-linux", - "inherits": "ci-with-libs", - "cacheVariables": { - "COVERAGE": "ON", - "BUILD_SHARED_LIBS": "ON", - "SANITIZER": "ON" - } - }, - { - "name": "ci-integrated", - "inherits": "ci-linux", - "cacheVariables": { - "INTEGRATED_SDK": "ON", - "CMAKE_CXX_COMPILER": "clazy" - } - }, - { - "name": "ci-bsd", - "inherits": "ci-linux" - }, - { - "name": "ci-ios", - "inherits": "ci-with-libs", - "generator": "Xcode", - "toolchainFile": "${sourceDir}/cmake/iOS.toolchain.cmake", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel" - } - }, - { - "name": "ci-ios-framework", - "inherits": "ci-ios", - "cacheVariables": { - "INTEGRATED_SDK": "ON" - } - }, - { - "name": "ci-ios-framework-simulator", - "inherits": "ci-ios-framework", - "generator": "Xcode", - "cacheVariables": { - "CMAKE_OSX_SYSROOT": "iphonesimulator", - "CMAKE_OSX_ARCHITECTURES": "x86_64" - } - }, - { - "name": "ci-ios-framework-simulator-arm64", - "inherits": "ci-ios-framework-simulator", - "cacheVariables": { - "CMAKE_OSX_ARCHITECTURES": "arm64" - } - }, - { - "name": "ci-android", - "hidden": true, - "inherits": "ci-with-libs", - "toolchainFile": "${sourceDir}/cmake/android.toolchain.cmake" - }, - { - "name": "ci-android-apk-release", - "inherits": "ci-android", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel", - "APK_SIGN_KEYSTORE": "$env{APK_SIGN_KEYSTORE}", - "APK_SIGN_KEYSTORE_ALIAS": "$env{APK_SIGN_KEYSTORE_ALIAS}", - "APK_SIGN_KEYSTORE_PSW": "$env{APK_SIGN_KEYSTORE_PSW}" - } - }, - { - "name": "ci-android-apk", - "inherits": "ci-android", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel", - "APK_SIGN_KEYSTORE": "$env{APK_SIGN_KEYSTORE_DEV}", - "APK_SIGN_KEYSTORE_ALIAS": "$env{APK_SIGN_KEYSTORE_ALIAS_DEV}", - "APK_SIGN_KEYSTORE_PSW": "$env{APK_SIGN_KEYSTORE_PSW_DEV}" - } - }, - { - "name": "ci-android-apk-review", - "inherits": "ci-android", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "DEBUG" - } - }, - { - "name": "ci-android-aar", - "inherits": "ci-android", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel", - "INTEGRATED_SDK": "ON" - } - }, - { - "name": "ci-android-aar-review", - "inherits": "ci-android", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "DEBUG", - "INTEGRATED_SDK": "ON" - } - }, - { - "name": "ci-translations", - "inherits": "ci-with-libs", - "cacheVariables": { - "UPDATE_TRANSLATIONS": "ON", - "UPDATE_TRANSLATIONS_NO_OBSOLETE": "ON" - } - }, - { - "name": "ci-tools", - "inherits": "ci", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RELEASE", - "tools.only": "ON", - "CMAKE_CXX_COMPILER_LAUNCHER": null - } - }, - { - "name": "ci-tools-with-libs", - "inherits": "ci-tools", - "cacheVariables": { - "CMAKE_PREFIX_PATH": "${sourceParentDir}/libs/build/dist" - } - }, - { - "name": "base", - "hidden": true, - "generator": "Ninja", - "binaryDir": "${sourceParentDir}/AusweisApp2-build/${presetName}", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" - } - }, - { - "name": "default", - "inherits": "base", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "DEBUG" - } - }, - { - "name": "integrated", - "inherits": "base", - "cacheVariables": { - "INTEGRATED_SDK": "ON" - } - }, - { - "name": "container", - "inherits": "base", - "cacheVariables": { - "CONTAINER_SDK": "ON" - } - }, - { - "name": "apk", - "inherits": "default", - "toolchainFile": "${sourceDir}/cmake/android.toolchain.cmake", - "cacheVariables": { - "CMAKE_PREFIX_PATH": "${sourceParentDir}/AusweisApp2-build/libs/android/dist" - } - }, - { - "name": "aar", - "inherits": "apk", - "cacheVariables": { - "INTEGRATED_SDK": "ON" - } - } - ], - "buildPresets": [ - { - "name": "default", - "configurePreset": "default" - } - ], - "testPresets": [ - { - "name": "default", - "configurePreset": "default", - "output": { - "outputOnFailure": true - } - } + "include": [ + "presets/ci-android.json", + "presets/ci-bsd.json", + "presets/ci-linux.json", + "presets/ci-macOS.json", + "presets/ci-iOS.json", + "presets/ci-tools.json", + "presets/ci-windows.json" ] } diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index fae3fd85a..98b53cea1 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -20,7 +20,7 @@ aufgenommen und mit dem nächsten Major-Release veröffentlicht. In der Zwischen wird die Änderung ebenfalls in dem ``community`` branch angenommen und beim offiziellen Release synchronisiert. -.. _`Repository`: https://github.com/Governikus/AusweisApp2 +.. _`Repository`: https://github.com/Governikus/AusweisApp diff --git a/Dockerfile b/Dockerfile index afc3c56df..588bb3a7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -ARG ALPINE_VERSION=3.18 +ARG ALPINE_VERSION=3.20 -FROM alpine:$ALPINE_VERSION as builder +FROM alpine:$ALPINE_VERSION AS builder # Install development stuff RUN apk --no-cache upgrade -a && \ apk --no-cache add patch cmake ccache make ninja g++ pkgconf pcsc-lite-dev binutils-gold eudev-libs perl python3 linux-headers @@ -32,6 +32,7 @@ RUN cmake /src/ausweisapp -B /build/app \ -DCONTAINER_SDK=ON \ -DCMAKE_BUILD_TYPE=MinSizeRel \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \ -GNinja && \ cmake --build /build/app && cmake --install /build/app && \ ccache -s -vv && rm -rf /build @@ -51,7 +52,7 @@ COPY --from=builder /usr/local/share /usr/local/share COPY --from=builder /usr/local/bin/AusweisApp /usr/local/bin/AusweisApp RUN apk --no-cache upgrade -a && \ - apk --no-cache add tini pcsc-lite pcsc-lite-libs ccid pcsc-cyberjack acsccid eudev-libs doas && \ + apk --no-cache add tini libstdc++ pcsc-lite-libs eudev-libs doas && \ echo 'permit nopass :wheel' > /etc/doas.d/wheel.conf && \ adduser ausweisapp -G wheel -s /bin/sh -D && \ mkdir -p /home/ausweisapp/.config && chown ausweisapp: /home/ausweisapp/.config @@ -60,4 +61,4 @@ USER ausweisapp VOLUME ["/home/ausweisapp/.config"] ENTRYPOINT ["/sbin/tini", "--"] EXPOSE 24727 -CMD ["AusweisApp", "--address", "0.0.0.0"] +CMD ["AusweisApp", "--address", "0.0.0.0", "--no-logfile"] diff --git a/LICENSE.officially.txt b/LICENSE.officially.txt index 788535120..caf1ed6d4 100644 --- a/LICENSE.officially.txt +++ b/LICENSE.officially.txt @@ -350,12 +350,12 @@ Die verwendeten Open-Source-Bibliotheken unterliegen den folgenden Nutzungsbedin OpenSSL Lizenz: Apache 2.0 - Version: 3.1.4 + Version: 3.3.2 Adresse: https://www.openssl.org/ Qt Lizenz: LGPL v3 - Version: 6.5.3 + Version: 6.7.2 Adresse: https://www.qt.io/ http_parser diff --git a/LICENSE.txt b/LICENSE.txt index 3367a1c08..dec10380c 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -318,12 +318,12 @@ Die verwendeten Open-Source-Bibliotheken unterliegen den folgenden Nutzungsbedin OpenSSL Lizenz: Apache 2.0 - Version: 3.1.4 + Version: 3.3.2 Adresse: https://www.openssl.org/ Qt Lizenz: LGPL v3 - Version: 6.5.3 + Version: 6.7.2 Adresse: https://www.qt.io/ http_parser diff --git a/README.rst b/README.rst index 1cbde0aee..8d5158fcd 100644 --- a/README.rst +++ b/README.rst @@ -110,14 +110,14 @@ Bei Android ist zu beachten, dass ein CMAKE_TOOLCHAIN_FILE angegeben werden muss Unter dem Ordner "./dist/bin" ist nun ein "AusweisApp...apk" erstellt worden. -Sofern der Parameter *CMAKE_BUILD_TYPE* auf RELEASE gesetzt wird, sind folgende CMake -Parameter notwendig um das APK zu signieren. +Sofern der Parameter *CMAKE_BUILD_TYPE* auf RELEASE gesetzt wird, sind folgende +Umgebungsvariablen notwendig um das APK zu signieren. :: - -DAPK_SIGN_KEYSTORE=/home/governikus/AusweisApp.apk.keystore.jks - -DAPK_SIGN_KEYSTORE_ALIAS=ausweisapp - -DAPK_SIGN_KEYSTORE_PSW=123456 + QT_ANDROID_KEYSTORE_PATH=/home/governikus/AusweisApp.apk.keystore.jks + QT_ANDROID_KEYSTORE_ALIAS=ausweisapp + QT_ANDROID_KEYSTORE_STORE_PASS=123456 Wie schon bei der Toolchain wird standardmäßig die Architektur "armeabi-v7a" verwendet. Dies kann mittels CMake Parameter "-DCMAKE_ANDROID_ARCH_ABI=x86" verändert werden. diff --git a/appveyor.yml b/appveyor.yml index 022dffb4b..324275ff7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,14 +5,14 @@ environment: - PlatformToolset: mingw-w64 platform: mingw-w64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - QTPath: C:\Qt\6.3.1\mingw_64 - OPENSSLPath: C:\OpenSSL-v30-Win64\bin + QTPath: C:\Qt\6.7\mingw_64 + OPENSSLPath: C:\OpenSSL-v33-Win64\bin - PlatformToolset: v142 platform: x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - QTPath: C:\Qt\6.3.1\msvc2019_64 - OPENSSLPath: C:\OpenSSL-v30-Win64\bin + QTPath: C:\Qt\6.7\msvc2019_64 + OPENSSLPath: C:\OpenSSL-v33-Win64\bin ARCHI: amd64 configuration: @@ -81,6 +81,6 @@ on_finish: - cd "%APPVEYOR_BUILD_FOLDER%" - ps: | - $version = Select-String -Path .\CMakeLists.txt -Pattern "AusweisApp2 VERSION ([0-9.]+)" | % { $_.Matches[0].Groups[1].Value } + $version = Select-String -Path .\CMakeLists.txt -Pattern "AusweisApp VERSION ([0-9.]+)" | % { $_.Matches[0].Groups[1].Value } Update-AppveyorBuild -Version "$version-$env:APPVEYOR_BUILD_NUMBER" diff --git a/ci.cmake b/ci.cmake new file mode 100644 index 000000000..6d810ccf1 --- /dev/null +++ b/ci.cmake @@ -0,0 +1,280 @@ +cmake_minimum_required(VERSION 3.19) + +########################################### +#### Usage: cmake -P ci.cmake -- cmake args +########################################### + +if(NOT CMAKE_SCRIPT_MODE_FILE) + message(FATAL_ERROR "Script mode is required") +endif() + +get_filename_component(CMAKE_SOURCE_DIR "${CMAKE_SCRIPT_MODE_FILE}" DIRECTORY) +message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}") +message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") +message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") + +set(CMAKE_DIR "${CMAKE_SOURCE_DIR}/cmake") +set(CMAKE_MODULE_PATH "${CMAKE_DIR}/ci") + +if(CMAKE_COMMAND MATCHES " ") + set(CMAKE_COMMAND cmake) +endif() +if(CMAKE_CTEST_COMMAND MATCHES " ") + set(CMAKE_CTEST_COMMAND ctest) +endif() + +set(IMPORT_PY ${CMAKE_SOURCE_DIR}/resources/jenkins/import.py) + + +function(GET_PARAMS _params _definitions) + foreach(_arg RANGE ${CMAKE_ARGC}) + if("${CMAKE_ARGV${_arg}}" STREQUAL "--") + math(EXPR delimiter "${_arg}+1") + break() + elseif("${CMAKE_ARGV${_arg}}" MATCHES "^-D") + list(APPEND definition ${CMAKE_ARGV${_arg}}) + endif() + endforeach() + + if(DEFINED delimiter) + foreach(_arg RANGE ${delimiter} ${CMAKE_ARGC}) + list(APPEND param ${CMAKE_ARGV${_arg}}) + endforeach() + set(${_params} "${param}" PARENT_SCOPE) + endif() + + if(DEFINED definition) + set(${_definitions} "${definition}" PARENT_SCOPE) + endif() +endfunction() + + +function(CALC_CHECKSUM _out_checksum _out_repatch) + set(CHECKSUM_FILES ${CMAKE_SCRIPT_MODE_FILE} ${IMPORT_PY}) + foreach(file ${CHECKSUM_FILES}) + file(MD5 "${file}" _hash) + string(MD5 hashes "${_hash}${hashes}") + endforeach() + + if((NOT DEFINED SPLITTED OR SPLITTED) AND PATCHED AND NOT ${_out_checksum} STREQUAL hashes) + set(${_out_repatch} ON PARENT_SCOPE) + endif() + + set(${_out_checksum} ${hashes} PARENT_SCOPE) +endfunction() + + +function(IMPORT_PATCH _out) + message(STATUS "Import patch(es)...") + find_package(Python REQUIRED) + step(${Python_EXECUTABLE} ${IMPORT_PY} ${ARGN} NO_ECHO OUTPUT output CHDIR ${CMAKE_SOURCE_DIR}) + if(output MATCHES "Pending patch: (.+)") + string(STRIP "${CMAKE_MATCH_1}" PENDING_PATCH) + set(${_out} "${PENDING_PATCH}" PARENT_SCOPE) + endif() +endfunction() + + +function(STEP) + set(options NO_ECHO) + set(oneValueArgs CHDIR OUTPUT RESULT PATH) + set(multiValueArgs ENV) + cmake_parse_arguments(_PARAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(_PARAM_ENV) + set(ENV_CMD ${CMAKE_COMMAND} -E env) + foreach(env ${_PARAM_ENV}) + if(env MATCHES "^PATH=") + message(FATAL_ERROR "Use explicit PATH parameter") + endif() + list(APPEND ENV_CMD "${env}") + endforeach() + list(APPEND ENV_CMD --) + endif() + + if(NOT _PARAM_CHDIR) + set(_PARAM_CHDIR ${CMAKE_BINARY_DIR}) + endif() + + if(_PARAM_OUTPUT) + set(OUTPUT_OPTION OUTPUT_VARIABLE) + set(OUTPUT _output) + endif() + + if(_PARAM_NO_ECHO OR NOT ECHO) + set(COMMAND_ECHO STDOUT) + else() + set(ECHO_CMD ${CMAKE_COMMAND} -E echo) + set(COMMAND_ECHO NONE) + endif() + + if(_PARAM_PATH) + set(TMP_PATH "$ENV{PATH}") + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") + set(SEP ";") + else() + set(SEP ":") + endif() + set(ENV{PATH} "${_PARAM_PATH}${SEP}$ENV{PATH}") + endif() + execute_process(COMMAND ${ECHO_CMD} ${ENV_CMD} ${_PARAM_UNPARSED_ARGUMENTS} + RESULT_VARIABLE _result + ${OUTPUT_OPTION} ${OUTPUT} + ECHO_OUTPUT_VARIABLE + WORKING_DIRECTORY ${_PARAM_CHDIR} + COMMAND_ECHO ${COMMAND_ECHO}) + if(TMP_PATH) + set(ENV{PATH} "${TMP_PATH}") + unset(TMP_PATH) + endif() + + if(NOT ${_result} EQUAL 0) + if(_PARAM_RESULT) + set(${_PARAM_RESULT} ${_result} PARENT_SCOPE) + else() + message(FATAL_ERROR "Process failed: ${_result}") + endif() + endif() + + if(_PARAM_OUTPUT) + set(${_PARAM_OUTPUT} ${${OUTPUT}} PARENT_SCOPE) + endif() +endfunction() + + +function(CALL_SCRIPT) + if(NOT SCRIPT) + message(FATAL_ERROR "SCRIPT is undefined") + endif() + + SET_TEMPLATES() + if(EXISTS ${T_BUILD_DIR}) + step(${CMAKE_COMMAND} -E rm -r ${T_BUILD_DIR}) + endif() + + message(STATUS "Use SCRIPT: ${SCRIPT}") + include(${SCRIPT}) +endfunction() + + +macro(PARSE_FROM_NAME) + if(DEFINED ENV{JOB_NAME} AND NOT NAME) + set(NAME $ENV{JOB_NAME}) + endif() + + if(NAME) + message(STATUS "Use NAME: ${NAME}") + + if(NAME MATCHES "^Release_" AND NOT DEFINED RELEASE) + set(RELEASE ON) + elseif(NAME MATCHES "_Review_" AND NOT DEFINED REVIEW) + set(REVIEW ON) + endif() + + if(NOT SCRIPT) + file(GLOB scripts "${CMAKE_MODULE_PATH}/*.cmake") + foreach(entry ${scripts}) + get_filename_component(entry "${entry}" NAME_WLE) + if(NAME MATCHES "_${entry}") + set(SCRIPT ${entry}) + break() + endif() + endforeach() + endif() + endif() + + if(NOT REVIEW AND NOT RELEASE) + set(DAILY ON) + endif() +endmacro() + + +macro(SET_TEMPLATES) # Provide some base templates for SCRIPTs + if(DEFINED ENV{WORKSPACE}) + set(WORKSPACE $ENV{WORKSPACE}) + else() + set(WORKSPACE ${CMAKE_BINARY_DIR}) + endif() + + set(T_BUILD_DIR build) + set(T_DIST_DIR ${T_BUILD_DIR}/dist) + set(T_BUILD ${CMAKE_COMMAND} --build ${T_BUILD_DIR}) + set(T_TARGET ${T_BUILD} --target) + set(T_CTEST ${CMAKE_CTEST_COMMAND} --test-dir ${T_BUILD_DIR} --output-on-failure) + set(T_CFG ${CMAKE_COMMAND} -S ${CMAKE_SOURCE_DIR} -B ${T_BUILD_DIR} ${PARAMS}) +endmacro() + + +function(RESPAWN_PATCHED) + if(NOT DEFINED SPLITTED OR SPLITTED) + set(SPLITTED_PARAM --splitted) + endif() + if(NOT PATCHED) + set(CLEAN_PARAM --clean) + endif() + if(DEFINED PENDING AND NOT PENDING AND SPLITTED_PARAM) + set(PENDING_PARAM --no-pending) + endif() + if(REPATCH) + set(REPATCH_PARAM --repatch) + endif() + + if(NOT PATCHED OR SPLITTED_PARAM) + unset(PENDING_PATCH CACHE) + IMPORT_PATCH(PENDING_PATCH ${SPLITTED_PARAM} ${CLEAN_PARAM} ${PENDING_PARAM} ${REPATCH_PARAM}) + + if(PENDING_PATCH OR NOT PATCHED) + set(PATCHED_OPTION "-DPATCHED=ON") + if(NOT PATCHED_OPTION IN_LIST DEFINITIONS) + list(APPEND DEFINITIONS ${PATCHED_OPTION}) + endif() + + set(PENDING_PATCH_OPTION "-DPENDING_PATCH") + list(FILTER DEFINITIONS EXCLUDE REGEX "${PENDING_PATCH_OPTION}") + if(PENDING_PATCH) + list(APPEND DEFINITIONS "${PENDING_PATCH_OPTION}=${PENDING_PATCH}") + endif() + + set(CHECKSUM_OPTION "-DCHECKSUM") + list(FILTER DEFINITIONS EXCLUDE REGEX "${CHECKSUM_OPTION}") + list(APPEND DEFINITIONS "${CHECKSUM_OPTION}=${CHECKSUM}") + + if(NOT PATCHED AND SPLITTED_PARAM) + set(INITIAL_RUNNER INITIAL_RUNNER_FAILED) + endif() + + message(STATUS "script runner: respawn") + step(${CMAKE_COMMAND} ${DEFINITIONS} -P ${CMAKE_SCRIPT_MODE_FILE} -- ${PARAMS} NO_ECHO RESULT ${INITIAL_RUNNER}) + if(INITIAL_RUNNER) + IMPORT_PATCH(_unused --clean-only) + if(INITIAL_RUNNER_FAILED) + message(FATAL_ERROR "script runner: failed") + else() + message(STATUS "script runner: done") + endif() + endif() + endif() + endif() +endfunction() + + +function(RUN) + PARSE_FROM_NAME() + GET_PARAMS(PARAMS DEFINITIONS) + CALC_CHECKSUM(CHECKSUM REPATCH) + + if(NOT REPATCH AND (NOT REVIEW OR PATCHED)) + CALL_SCRIPT() + endif() + + if(REVIEW) + RESPAWN_PATCHED() + endif() +endfunction() + + +if(PATCH_ONLY) + IMPORT_PATCH(_unused --clean) +else() + RUN() +endif() diff --git a/cmake/Appcast.cmake b/cmake/Appcast.cmake index d8c3b0fe7..b7947387d 100644 --- a/cmake/Appcast.cmake +++ b/cmake/Appcast.cmake @@ -17,7 +17,7 @@ if(MAC OR LINUX OR WIN32) if(NOT "${_system}" STREQUAL "src") file(READ ${PACKAGING_DIR}/updater/Appcast.item.json.in item) - string(REPLACE "AusweisApp2-" "" APPCAST_FILE_VERSION ${file}) + string(REPLACE "AusweisApp-" "" APPCAST_FILE_VERSION ${file}) string(REPLACE ".dmg" "" APPCAST_FILE_VERSION ${APPCAST_FILE_VERSION}) string(REPLACE ".msi" "" APPCAST_FILE_VERSION ${APPCAST_FILE_VERSION}) @@ -43,10 +43,6 @@ if(MAC OR LINUX OR WIN32) file(GLOB MSI_FILES ${PROJECT_BINARY_DIR}/*.msi) file(GLOB TAR_GZ_FILES ${PROJECT_BINARY_DIR}/*.tar.gz) - if(DMG_FILES) - ADD_APPCAST_FILE("${DMG_FILES}" "mac" "${CMAKE_OSX_DEPLOYMENT_TARGET}") - endif() - if(MSI_FILES) ADD_APPCAST_FILE("${MSI_FILES}" "win" "10") endif() diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index 1425cf547..704b2a1d3 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -1,17 +1,12 @@ add_definitions(-DUNICODE) add_definitions(-DQT_MESSAGELOGCONTEXT) add_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) +add_definitions(-DQT_NO_CAST_FROM_ASCII) add_definitions(-DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_FOREACH) add_definitions(-DQT_NO_KEYWORDS) add_definitions(-DQT_NO_EXCEPTIONS) - -if(NOT MSVC AND NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC" AND QT5) - add_definitions(-DQT_STRICT_ITERATORS) -endif() - -add_compile_definitions($<$:QT_RESTRICTED_CAST_FROM_ASCII>) -add_compile_definitions($<$>:QT_NO_CAST_FROM_ASCII>) +add_definitions(-DQT_NO_CONTEXTLESS_CONNECT) if(QT_VENDOR STREQUAL "Governikus") add_definitions(-DGOVERNIKUS_QT) @@ -134,6 +129,11 @@ else() if(ANDROID) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") + if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a" OR CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") + set(ANDROID_PAGE_SIZE_FLAGS "-Wl,-z,max-page-size=16384") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${ANDROID_PAGE_SIZE_FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${ANDROID_PAGE_SIZE_FLAGS}") + endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections") if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-limit=64") @@ -170,7 +170,7 @@ else() endif() - # QTBUG-82978 + # QTBUG-82978, QTBUG-122004, QTBUG-122582 if(CMAKE_CXX_FLAGS MATCHES "-Wextra-semi-stmt") list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-extra-semi-stmt") endif() @@ -179,8 +179,18 @@ else() list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-useless-cast") endif() - if(CMAKE_CXX_FLAGS MATCHES "-Wconversion" AND MAC) - list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-sign-conversion") + if(CMAKE_CXX_FLAGS MATCHES "-Wconversion") + list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-conversion") + endif() + + # codereview: 541911 + if(CMAKE_CXX_FLAGS MATCHES "-Wnewline-eof") + list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-newline-eof") + endif() + + # QTBUG-114897 + if(QT_VERSION VERSION_LESS "6.5.3" AND CMAKE_CXX_FLAGS MATCHES "-Wshadow") + list(APPEND INCOMPATIBLE_QT_COMPILER_FLAGS "-Wno-shadow") endif() endif() diff --git a/cmake/Helper.cmake b/cmake/Helper.cmake index 6b3d77371..e0c33a5d9 100644 --- a/cmake/Helper.cmake +++ b/cmake/Helper.cmake @@ -13,7 +13,7 @@ include(CheckCXXCompilerFlag) # group multiple flags or to indicate the usage. # LINK: Use these linker flags to try the compiler flag. The linker # flags won't be added unless LINK_GLOBAL is enabled. Otherwise they are for testing only. -# LINK_VAR: Checked link flags will be added to these variables. (default: CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) +# LINK_VAR: Checked link flags will be added to these variables. (default: CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) # VAR: Checked compiler flags will be added to these variables. (default: CMAKE_CXX_FLAGS) # It is possible to add multiple VAR parameter. # If VAR parameter is a cmake TARGET the compiler flag will be added @@ -29,7 +29,7 @@ function(ADD_FLAG) endif() if(NOT _PARAM_LINK_VAR) - set(_PARAM_LINK_VAR CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) + set(_PARAM_LINK_VAR CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) endif() if(_PARAM_LINK) @@ -109,34 +109,6 @@ function(GET_PUBLIC_HEADER _target _out) endfunction() -function(QUERY_QMAKE _out _var) - if(NOT TARGET ${Qt}::qmake) - message(WARNING "qmake not found") - return() - endif() - - get_target_property(qmake_bin ${Qt}::qmake LOCATION) - - if (IOS OR ANDROID) - find_file(TARGET_QT_CONF target_qt.conf PATH_SUFFIXES /bin CMAKE_FIND_ROOT_PATH_BOTH) - if(NOT TARGET_QT_CONF) - message(FATAL_ERROR "Could not find target_qt.conf") - endif() - - set(QT_CONFIG -qtconf ${TARGET_QT_CONF}) - endif() - -execute_process(COMMAND "${qmake_bin}" ${QT_CONFIG} -query ${_var} - RESULT_VARIABLE _result - OUTPUT_VARIABLE _output - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(_result EQUAL 0) - set(${_out} "${_output}" PARENT_SCOPE) - endif() -endfunction() - - function(GET_FILE_MATCHER _result_remove _result_keep) if(NOT ANDROID) list(APPEND matcher_remove "_android") @@ -204,7 +176,7 @@ endfunction() function(ADD_PLATFORM_LIBRARY _name) set(options) set(oneValueArgs) - set(multiValueArgs PATH) + set(multiValueArgs PATH EXCLUDE) cmake_parse_arguments(_PARAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) GET_FILE_EXTENSIONS(FILE_EXTENSIONS PATH ${_PARAM_PATH}) @@ -215,6 +187,21 @@ function(ADD_PLATFORM_LIBRARY _name) foreach(file ${FILES}) string(REPLACE "${CMAKE_SOURCE_DIR}" "" file_stripped "${file}") + if(_PARAM_EXCLUDE) + set(skip_file FALSE) + foreach(exclude ${_PARAM_EXCLUDE}) + if(file_stripped MATCHES "${exclude}") + set(skip_file TRUE) + break() + endif() + endforeach() + + if(skip_file) + list(REMOVE_ITEM FILES "${file}") + continue() + endif() + endif() + set(keep FALSE) foreach(match ${matcher_keep}) if("${file_stripped}" MATCHES ${match}) @@ -414,6 +401,25 @@ function(map_get_value _var _map _key) set(${_var} ${${_map}_${_key}} PARENT_SCOPE) endfunction() +function(configure_files _path _pattern _destination) + set(options FLATTEN) + set(oneValueArgs) + set(multiValueArgs) + cmake_parse_arguments(_PARAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(pattern ${_pattern}) + file(GLOB_RECURSE files RELATIVE "${_path}" "${_path}/${pattern}") + foreach(entry ${files}) + if(_PARAM_FLATTEN) + get_filename_component(destEntry "${entry}" NAME) + else() + set(destEntry ${entry}) + endif() + + configure_file("${_path}/${entry}" "${_destination}/${destEntry}" COPYONLY) + endforeach() + endforeach() +endfunction() if(WIN32) if(WIN_SIGN_SUBJECT_NAME OR (WIN_SIGN_KEYSTORE AND WIN_SIGN_KEYSTORE_PSW)) diff --git a/cmake/Install.cmake b/cmake/Install.cmake index 5ddcdcd21..8d880c78e 100644 --- a/cmake/Install.cmake +++ b/cmake/Install.cmake @@ -87,18 +87,21 @@ if(WIN32) FETCH_TARGET_LOCATION(pluginSvg "${Qt}::QSvgPlugin") FETCH_TARGET_LOCATION(pluginGif "${Qt}::QGifPlugin") FETCH_TARGET_LOCATION(pluginJpeg "${Qt}::QJpegPlugin") - FETCH_TARGET_LOCATION(pluginWebP "${Qt}::QWebpPlugin") FETCH_TARGET_LOCATION(platformWin "${Qt}::QWindowsIntegrationPlugin") - FETCH_TARGET_LOCATION(styleVista "${Qt}::QWindowsVistaStylePlugin") + + if(QT_VERSION VERSION_LESS 6.7) + FETCH_TARGET_LOCATION(styleWin "${Qt}::QWindowsVistaStylePlugin") + else() + FETCH_TARGET_LOCATION(styleWin "${Qt}::QModernWindowsStylePlugin") + endif() install(TARGETS AusweisAppBinary DESTINATION . COMPONENT Application) install(FILES ${pluginSvg} DESTINATION imageformats COMPONENT Runtime) install(FILES ${pluginGif} DESTINATION imageformats COMPONENT Runtime) install(FILES ${pluginJpeg} DESTINATION imageformats COMPONENT Runtime) - install(FILES ${pluginWebP} DESTINATION imageformats COMPONENT Runtime) install(FILES ${platformWin} DESTINATION platforms COMPONENT Runtime) - install(FILES ${styleVista} DESTINATION styles COMPONENT Runtime) - list(APPEND LIBS ${pluginSvg} ${pluginGif} ${pluginJpeg} ${platformWin} ${styleVista}) + install(FILES ${styleWin} DESTINATION styles COMPONENT Runtime) + list(APPEND LIBS ${pluginSvg} ${pluginGif} ${pluginJpeg} ${platformWin} ${styleWin}) install(CODE " @@ -152,11 +155,10 @@ elseif(MAC) include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QMacHeifPluginTargets.cmake") include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QMacJp2PluginTargets.cmake") include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QSvgPluginTargets.cmake") - include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QWebpPluginTargets.cmake") include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Gui/Qt6QCocoaIntegrationPluginTargets.cmake") include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Widgets/Qt6QMacStylePluginTargets.cmake") include("${QT_INSTALL_ARCHDATA}/lib/cmake/Qt6Network/Qt6QTlsBackendOpenSSLPluginTargets.cmake") - set(plugins ${Qt}::QTuioTouchPlugin ${Qt}::QSvgIconPlugin ${Qt}::QGifPlugin ${Qt}::QICNSPlugin ${Qt}::QICOPlugin ${Qt}::QJpegPlugin ${Qt}::QMacHeifPlugin ${Qt}::QMacJp2Plugin ${Qt}::QSvgPlugin ${Qt}::QWebpPlugin ${Qt}::QCocoaIntegrationPlugin ${Qt}::QMacStylePlugin ${Qt}::QTlsBackendOpenSSLPlugin) + set(plugins ${Qt}::QTuioTouchPlugin ${Qt}::QSvgIconPlugin ${Qt}::QGifPlugin ${Qt}::QICNSPlugin ${Qt}::QICOPlugin ${Qt}::QJpegPlugin ${Qt}::QMacHeifPlugin ${Qt}::QMacJp2Plugin ${Qt}::QSvgPlugin ${Qt}::QCocoaIntegrationPlugin ${Qt}::QMacStylePlugin ${Qt}::QTlsBackendOpenSSLPlugin) install_mac_plugins("${plugins}") if(TARGET ${Qt}::Qml) @@ -187,88 +189,12 @@ elseif(IOS) elseif(ANDROID) - set(ANDROID_PACKAGE_SRC_DIR ${PROJECT_BINARY_DIR}/package-src-dir) - set(ANDROID_DEST libs/${CMAKE_ANDROID_ARCH_ABI}) - set(PERMISSIONS PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - install(TARGETS AusweisAppBinary DESTINATION ${ANDROID_DEST} ${PERMISSIONS} COMPONENT Application) - - set(RESOURCES_IMG_ANDROID_DIR ${RESOURCES_DIR}/images/android) - if(BUILD_PREVIEW) - set(ANDROID_LAUNCHER_ICON "npa_preview.png") - set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa_preview.png") - elseif(IS_BETA_VERSION) - set(ANDROID_LAUNCHER_ICON "npa_beta.png") - set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa_beta.png") - else() - set(ANDROID_LAUNCHER_ICON "npa.png") - set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa.png") - endif() - - if(INTEGRATED_SDK) - set(ANDROID_MANIFEST AndroidManifest.xml.aar.in) - foreach(entry network/WifiInfo ui/aidl/AidlBinder android/LogHandler android/BootstrapHelper android/AusweisApp2Service android/AusweisApp2LocalIfdServiceConnection) - set(_java_file "${SRC_DIR}/${entry}.java") - if(NOT EXISTS "${_java_file}") - message(FATAL_ERROR "Cannot find file: ${_java_file}") - endif() - list(APPEND JAVA_FILES "${_java_file}") - endforeach() - - install(FILES ${PACKAGING_DIR}/android/res/values/strings.xml DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/values COMPONENT Runtime) - else() - set(ANDROID_MANIFEST AndroidManifest.xml.apk.in) - - if(USE_SMARTEID) - set(LOCAL_IFD_SERVICE_ENABLED true) - else() - set(LOCAL_IFD_SERVICE_ENABLED false) - endif() - - foreach(entry ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi) - install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/background_npa.png DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_background.png) - install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/foreground_${ANDROID_LAUNCHER_ICON} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_foreground.png) - install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/monochrome_${ANDROID_LAUNCHER_ICON} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry} COMPONENT Runtime RENAME npa_monochrome.png) - install(FILES ${RESOURCES_IMG_ANDROID_DIR}/${entry}/${ANDROID_SPLASH_SCREEN_ICON_NAME} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/res/drawable-${entry} COMPONENT Runtime RENAME splash_npa.png) - endforeach() - - install(DIRECTORY ${PACKAGING_DIR}/android/res DESTINATION ${ANDROID_PACKAGE_SRC_DIR} COMPONENT Runtime) - - file(GLOB_RECURSE JAVA_FILES "${SRC_DIR}/*.java") - endif() - - install(FILES ${JAVA_FILES} DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/src COMPONENT Runtime) - install(FILES ${PACKAGING_DIR}/android/IAusweisApp2Sdk.aidl DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/src/com/governikus/ausweisapp2/ COMPONENT Runtime) - install(FILES ${PACKAGING_DIR}/android/IAusweisApp2SdkCallback.aidl DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/src/com/governikus/ausweisapp2/ COMPONENT Runtime) - - set(ANDROID_VERSION_NAME ${VERSION_DVCS}) - configure_file(${PACKAGING_DIR}/android/${ANDROID_MANIFEST} ${ANDROID_PACKAGE_SRC_DIR}/AndroidManifest.xml @ONLY) if(INTEGRATED_SDK) - set(QML_ROOT_PATH []) - set(ANDROID_ROOT_LOGGER "java") - else() - set(QML_ROOT_PATH [\"${RESOURCES_DIR}/qml\"]) - set(ANDROID_ROOT_LOGGER "") - configure_file(${PACKAGING_DIR}/android/fileprovider.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/fileprovider.xml COPYONLY) - configure_file(${PACKAGING_DIR}/android/full_backup_content.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/full_backup_content.xml COPYONLY) - configure_file(${PACKAGING_DIR}/android/data_extraction_rules.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/data_extraction_rules.xml COPYONLY) + add_custom_command(TARGET AusweisAppBinary POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${ANDROID_BUILD_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/$" + ) endif() - set(ANDROID_SO_NAME libAusweisApp_${CMAKE_ANDROID_ARCH_ABI}.so) - set(ANDROID_APP_BINARY "${CMAKE_INSTALL_PREFIX}/${ANDROID_DEST}/${ANDROID_SO_NAME}") - set(SYMBOL_FOLDER "${CMAKE_BINARY_DIR}/debug.symbols") - set(ANDROID_APP_SYMBOLS "${SYMBOL_FOLDER}/${ANDROID_SO_NAME}") - - install(CODE - " - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E make_directory \"${SYMBOL_FOLDER}\") - execute_process(COMMAND \"${CMAKE_OBJCOPY}\" \"--only-keep-debug\" \"${ANDROID_APP_BINARY}\" \"${ANDROID_APP_SYMBOLS}\") - " COMPONENT Runtime) - - set(ANDROID_DEPLOYMENT_SETTINGS ${PROJECT_BINARY_DIR}/libAusweisApp.so-deployment-settings.json CACHE INTERNAL "apk deployment" FORCE) - configure_file(${PACKAGING_DIR}/android/libAusweisApp.so-deployment-settings.json.in ${ANDROID_DEPLOYMENT_SETTINGS} @ONLY) - configure_file(${PACKAGING_DIR}/android/gradle.properties.in ${CMAKE_INSTALL_PREFIX}/gradle.properties @ONLY) - - set(DEFAULT_FILE_DESTINATION ${ANDROID_PACKAGE_SRC_DIR}/assets) elseif(UNIX) if(BUILD_SHARED_LIBS) @@ -318,7 +244,7 @@ if(LINUX OR WIN32 OR MAC) endif() -if(NOT INTEGRATED_SDK OR CONTAINER_SDK) +if((NOT INTEGRATED_SDK OR CONTAINER_SDK) AND NOT ANDROID) # resources file install(FILES ${RCC} DESTINATION ${DEFAULT_FILE_DESTINATION} COMPONENT Runtime) endif() diff --git a/cmake/Libraries.cmake b/cmake/Libraries.cmake index 6e28a9d42..1035a35dc 100644 --- a/cmake/Libraries.cmake +++ b/cmake/Libraries.cmake @@ -3,7 +3,7 @@ if(DESKTOP) set(MIN_QT_VERSION 6.4) else() - set(MIN_QT_VERSION 6.5) + set(MIN_QT_VERSION 6.7) endif() if(IOS OR ANDROID) @@ -11,7 +11,7 @@ if(IOS OR ANDROID) # If no QT_HOST_PATH is set, see if it was build as part of the toolchain foreach(path ${CMAKE_PREFIX_PATH}) set(QT_HOST_PATH ${path}/qt-host/) - if(EXISTS QT_HOST_PATH) + if(EXISTS "${QT_HOST_PATH}") break() endif() endforeach() @@ -21,12 +21,11 @@ if(IOS OR ANDROID) message(FATAL_ERROR "QT_HOST_PATH does not exist") endif() - message(STATUS "Using QT_HOST_PATH: ${QT_HOST_PATH}") - set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${QT_HOST_PATH} ) + message(STATUS "QT_HOST_PATH: ${QT_HOST_PATH}") endif() set(Qt Qt6) -find_package(${Qt} ${MIN_QT_VERSION} COMPONENTS Core Concurrent Network StateMachine REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) +find_package(${Qt} ${MIN_QT_VERSION} REQUIRED COMPONENTS Core Concurrent Network StateMachine CMAKE_FIND_ROOT_PATH_BOTH) set(QT_VERSION "${Qt6Core_VERSION}") if(NOT CONTAINER_SDK) @@ -54,9 +53,8 @@ elseif(CONTAINER_SDK) endif() -QUERY_QMAKE(QT_INSTALL_ARCHDATA QT_INSTALL_ARCHDATA) -QUERY_QMAKE(QT_INSTALL_TRANSLATIONS QT_INSTALL_TRANSLATIONS) - +get_filename_component(QT_INSTALL_ARCHDATA ${QT6_INSTALL_PREFIX}/${QT6_INSTALL_ARCHDATA} ABSOLUTE) +get_filename_component(QT_INSTALL_TRANSLATIONS ${QT6_INSTALL_PREFIX}/${QT6_INSTALL_TRANSLATIONS} ABSOLUTE) message(STATUS "QT_INSTALL_ARCHDATA: ${QT_INSTALL_ARCHDATA}") message(STATUS "QT_INSTALL_TRANSLATIONS: ${QT_INSTALL_TRANSLATIONS}") @@ -86,10 +84,10 @@ endif() if(MINGW) find_package(PCSC REQUIRED) - set(WIN_DEFAULT_LIBS "-ladvapi32" "-lkernel32" "-lole32" "-lsetupapi" "-lversion" "-liphlpapi") + set(WIN_DEFAULT_LIBS "-ladvapi32" "-lkernel32" "-lole32" "-lsetupapi" "-lversion" "-liphlpapi" "-ldwmapi") elseif(MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") find_package(PCSC REQUIRED) - set(WIN_DEFAULT_LIBS setupapi.lib version.lib iphlpapi.lib) + set(WIN_DEFAULT_LIBS setupapi.lib version.lib iphlpapi.lib dwmapi.lib) elseif(ANDROID) elseif(IOS) @@ -131,20 +129,25 @@ elseif(UNIX) endif() -if(BUILD_TESTING AND NOT CONTAINER_SDK) - list(APPEND QT_COMPONENTS Test) - - if(INTEGRATED_SDK) - find_package(Threads REQUIRED) +if(BUILD_TESTING) + if(CMAKE_BUILD_TYPE STREQUAL DEBUG) + set(QT_TEST_COMPONENTS QT_COMPONENTS) + else() + set(QT_TEST_COMPONENTS QT_COMPONENTS_OPTIONAL) endif() + list(APPEND ${QT_TEST_COMPONENTS} Test) if(NOT INTEGRATED_SDK) - list(APPEND QT_COMPONENTS QuickTest) + list(APPEND ${QT_TEST_COMPONENTS} QuickTest) + endif() + + if(INTEGRATED_SDK) + find_package(Threads REQUIRED) endif() endif() if(QT_COMPONENTS) - find_package(${Qt} ${MIN_QT_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED) + find_package(${Qt} ${MIN_QT_VERSION} REQUIRED COMPONENTS ${QT_COMPONENTS} OPTIONAL_COMPONENTS ${QT_COMPONENTS_OPTIONAL}) endif() if(LINUX OR BSD) diff --git a/cmake/Merge.cmake b/cmake/Merge.cmake new file mode 100644 index 000000000..31f2a7110 --- /dev/null +++ b/cmake/Merge.cmake @@ -0,0 +1,185 @@ +cmake_minimum_required(VERSION 3.21) + +if(NOT CMAKE_SCRIPT_MODE_FILE) + message(FATAL_ERROR "Usage: cmake -P cmake/Merge.cmake") +endif() + +set(prefix ausweisapp) +set(extension .aar) + +set(XML_LOAD_LOCAL_LIBS "") +set(XML_QT_LIBS "") +set(XML_END_TAG "") + +function(remove_arch filename output) + list(APPEND ARCHS x86_64 x86 armeabi-v7a arm64-v8a) + foreach(arch ${ARCHS}) + string(REPLACE "-${arch}" "" filename "${filename}") + endforeach() + set(${output} ${filename} PARENT_SCOPE) +endfunction() + +function(get_version_filename _files _output) + foreach(filename ${_files}) + message(STATUS "Check AAR: ${filename}") + get_filename_component(filename ${filename} NAME) + remove_arch(${filename} filenameWithoutArch) + if(filename STREQUAL filenameWithoutArch) + message(STATUS "Ignore merged AAR: ${filename}") + continue() + else() + set(filename ${filenameWithoutArch}) + endif() + + # Check that any AAR has same version + string(REPLACE "${extension}" "" aar_version "${filename}") + string(REPLACE "${prefix}-" "" aar_version "${aar_version}") + if(APP_NAME_VERSION AND NOT APP_NAME_VERSION STREQUAL aar_version) + message(STATUS "Different package version: ${APP_NAME_VERSION} / ${aar_version}") + set(APP_NAME_VERSION version-mismatch) + else() + set(APP_NAME_VERSION ${aar_version}) + endif() + endforeach() + + set(${_output} ${APP_NAME_VERSION} PARENT_SCOPE) +endfunction() + +function(extract_aars _files _dir _dir_values) + foreach(filename ${_files}) + if(NOT EXISTS "${filename}") + continue() + endif() + + # Extract the .aar file to package the merged aar itself + if(EXISTS "${_dir}") + set(patterns "jni") + else() + set(patterns "") + endif() + + file(ARCHIVE_EXTRACT INPUT "${filename}" DESTINATION "${_dir}" PATTERNS ${patterns}) + get_filename_component(dirname ${filename} NAME) + file(ARCHIVE_EXTRACT INPUT "${filename}" DESTINATION "${_dir_values}/${dirname}" PATTERNS "res/values/values.xml") + endforeach() +endfunction() + +function(append_value _line) + cmake_parse_arguments(_PARAM "NOLF" "" "" ${ARGN}) + if(NOT _PARAM_NOLF) + set(LF "\n") + endif() + file(APPEND "${VALUES_XML}" "${_line}${LF}") +endfunction() + +function(read_values _all_values _out_local_libs _out_qt_libs) + foreach(valueFile ${_all_values}) + set(addLineLocalLibs FALSE) + set(addLineQtLibs FALSE) + file(STRINGS "${valueFile}" filecontent) + foreach(line ${filecontent}) + if(line MATCHES "${XML_LOAD_LOCAL_LIBS}") + set(addLineLocalLibs TRUE) + continue() + elseif(line MATCHES "${XML_QT_LIBS}") + set(addLineQtLibs TRUE) + continue() + elseif(line MATCHES "${XML_END_TAG}") + set(addLineLocalLibs FALSE) + set(addLineQtLibs FALSE) + endif() + + if(addLineLocalLibs) + string(APPEND LOCAL_LIBS "${line}\n") + endif() + if(addLineQtLibs) + string(APPEND QT_LIBS "${line}\n") + endif() + endforeach() + endforeach() + + set(${_out_local_libs} "${LOCAL_LIBS}" PARENT_SCOPE) + set(${_out_qt_libs} "${QT_LIBS}" PARENT_SCOPE) +endfunction() + +function(merge_values _dir _all_values) + set(VALUES_XML "${_dir}/res/values/values.xml") + if(NOT EXISTS "${VALUES_XML}") + message(FATAL_ERROR "Cannot find ${VALUES_XML}") + endif() + + read_values("${_all_values}" LOCAL_LIBS QT_LIBS) + + set(writeLine TRUE) + file(STRINGS "${VALUES_XML}" filecontent) + file(WRITE "${VALUES_XML}" "") + foreach(line ${filecontent}) + if(line MATCHES "${XML_LOAD_LOCAL_LIBS}") + set(writeLine FALSE) + append_value("${line}") + append_value("${LOCAL_LIBS}" NOLF) + elseif(line MATCHES "${XML_QT_LIBS}") + set(writeLine FALSE) + append_value("${line}") + append_value("${QT_LIBS}" NOLF) + elseif(line MATCHES "${XML_END_TAG}") + set(writeLine TRUE) + endif() + + if(writeLine) + append_value("${line}") + endif() + endforeach() +endfunction() + +function(copy_file _extension _destination) + file(GLOB files "${CMAKE_BINARY_DIR}/*.${_extension}") + if(files) + list(GET files 0 file) + message(STATUS "Copy ${file} to ${_destination}") + file(COPY_FILE "${file}" "${_destination}" ONLY_IF_DIFFERENT) + else() + message(WARNING "Missing files(s) (${_extension}) in: ${CMAKE_BINARY_DIR}") + endif() +endfunction() + +file(GLOB AAR_FILES "${CMAKE_BINARY_DIR}/*${extension}") +if(NOT AAR_FILES) + message(FATAL_ERROR "Missing AAR(s) in: ${CMAKE_BINARY_DIR}") +endif() + +get_version_filename("${AAR_FILES}" VERSION) +set(AAR_TMP_DIR ${CMAKE_BINARY_DIR}/${VERSION}) +set(AAR_VALUES_TMP_DIR ${AAR_TMP_DIR}-values) +if(DIST_DIR) + get_filename_component(DIST_DIR "${DIST_DIR}" ABSOLUTE) +else() + set(DIST_DIR ${CMAKE_BINARY_DIR}/dist) +endif() +set(BASE_NAME ${DIST_DIR}/${prefix}-${VERSION}) +set(AAR ${BASE_NAME}${extension}) +if(EXISTS "${AAR_TMP_DIR}") + file(REMOVE_RECURSE "${AAR_TMP_DIR}") +endif() +if(EXISTS "${AAR_VALUES_TMP_DIR}") + file(REMOVE_RECURSE "${AAR_VALUES_TMP_DIR}") +endif() +if(EXISTS "${AAR}") + message(STATUS "Remove AAR: ${AAR}") + file(REMOVE "${AAR}") +endif() +if(NOT EXISTS "${DIST_DIR}") + file(MAKE_DIRECTORY ${DIST_DIR}) +endif() + +extract_aars("${AAR_FILES}" "${AAR_TMP_DIR}" "${AAR_VALUES_TMP_DIR}") +file(GLOB_RECURSE ALL_VALUES_XML "${AAR_VALUES_TMP_DIR}/values.xml") +merge_values("${AAR_TMP_DIR}" "${ALL_VALUES_XML}") + +message(STATUS "Create AAR: ${AAR}") +execute_process(COMMAND ${CMAKE_COMMAND} -E tar cf "${AAR}" --format=zip . WORKING_DIRECTORY "${AAR_TMP_DIR}") +file(REMOVE_RECURSE "${AAR_TMP_DIR}") +file(REMOVE_RECURSE "${AAR_VALUES_TMP_DIR}") + +copy_file("pom" "${BASE_NAME}.pom") +copy_file("jar" "${BASE_NAME}-sources.jar") diff --git a/cmake/Messages.cmake b/cmake/Messages.cmake index e3c63199d..417302f9b 100644 --- a/cmake/Messages.cmake +++ b/cmake/Messages.cmake @@ -11,6 +11,7 @@ if(APPLE) message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") +message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") message(STATUS "CMAKE_CXX_SIMULATE_ID: ${CMAKE_CXX_SIMULATE_ID}") if(ANDROID) @@ -21,7 +22,7 @@ if(ANDROID) message(STATUS "CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION: ${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}") message(STATUS "CMAKE_CXX_ANDROID_TOOLCHAIN_MACHINE: ${CMAKE_CXX_ANDROID_TOOLCHAIN_MACHINE}") - message(STATUS "ANDROID_SDK: ${ANDROID_SDK}") + message(STATUS "ANDROID_SDK_ROOT: ${ANDROID_SDK_ROOT}") message(STATUS "ANDROID_BUILD_TOOLS_REVISION: ${ANDROID_BUILD_TOOLS_REVISION}") message(STATUS "ANDROID_NDK_REVISION: ${ANDROID_NDK_REVISION}") @@ -29,3 +30,4 @@ endif() message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") +message(STATUS "BUILD_TESTING: ${BUILD_TESTING}") diff --git a/cmake/Packaging.android.cmake b/cmake/Packaging.android.cmake new file mode 100644 index 000000000..9351f24c0 --- /dev/null +++ b/cmake/Packaging.android.cmake @@ -0,0 +1,209 @@ +set(RESOURCES_IMG_ANDROID_DIR ${RESOURCES_DIR}/images/android) +if(BUILD_PREVIEW) + set(ANDROID_LAUNCHER_ICON "npa_preview.png") + set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa_preview.png") +elseif(IS_BETA_VERSION) + set(ANDROID_LAUNCHER_ICON "npa_beta.png") + set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa_beta.png") +else() + set(ANDROID_LAUNCHER_ICON "npa.png") + set(ANDROID_SPLASH_SCREEN_ICON_NAME "splash_npa.png") +endif() + +if(INTEGRATED_SDK) + set(ANDROID_MANIFEST AndroidManifest.xml.aar.in) + set(JAVA_FILES network/WifiInfo.java ui/aidl/AidlBinder.java android/LogHandler.java android/BootstrapHelper.java android/AusweisApp2Service.java android/AusweisApp2LocalIfdServiceConnection.java) + + configure_file(${PACKAGING_DIR}/android/res/values/strings.xml ${ANDROID_PACKAGE_SRC_DIR}/res/values/strings.xml COPYONLY) +else() + set(ANDROID_MANIFEST AndroidManifest.xml.apk.in) + set(JAVA_FILES *.java) + + if(USE_SMARTEID) + set(LOCAL_IFD_SERVICE_ENABLED true) + else() + set(LOCAL_IFD_SERVICE_ENABLED false) + endif() + + foreach(entry ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi) + configure_file(${RESOURCES_IMG_ANDROID_DIR}/${entry}/background_npa.png ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry}/npa_background.png COPYONLY) + configure_file(${RESOURCES_IMG_ANDROID_DIR}/${entry}/foreground_${ANDROID_LAUNCHER_ICON} ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry}/npa_foreground.png COPYONLY) + configure_file(${RESOURCES_IMG_ANDROID_DIR}/${entry}/monochrome_${ANDROID_LAUNCHER_ICON} ${ANDROID_PACKAGE_SRC_DIR}/res/mipmap-${entry}/npa_monochrome.png COPYONLY) + configure_file(${RESOURCES_IMG_ANDROID_DIR}/${entry}/${ANDROID_SPLASH_SCREEN_ICON_NAME} ${ANDROID_PACKAGE_SRC_DIR}/res/drawable-${entry}/splash_npa.png COPYONLY) + endforeach() + + configure_files("${PACKAGING_DIR}/android" "res/*" "${ANDROID_PACKAGE_SRC_DIR}") +endif() + +configure_files(${SRC_DIR} "${JAVA_FILES}" ${ANDROID_PACKAGE_SRC_DIR}/src/com/governikus/ausweisapp2 FLATTEN) +configure_file(${PACKAGING_DIR}/android/IAusweisApp2Sdk.aidl ${ANDROID_PACKAGE_SRC_DIR}/src/com/governikus/ausweisapp2/IAusweisApp2Sdk.aidl COPYONLY) +configure_file(${PACKAGING_DIR}/android/IAusweisApp2SdkCallback.aidl ${ANDROID_PACKAGE_SRC_DIR}/src/com/governikus/ausweisapp2/IAusweisApp2SdkCallback.aidl COPYONLY) + +set(ANDROID_VERSION_NAME ${VERSION_DVCS}) +configure_file(${PACKAGING_DIR}/android/${ANDROID_MANIFEST} ${ANDROID_PACKAGE_SRC_DIR}/AndroidManifest.xml @ONLY) +if(INTEGRATED_SDK) + set(ANDROID_ROOT_LOGGER "java") + set(ANDROID_DEPLOYMENT_SETTINGS ${PROJECT_BINARY_DIR}/libAusweisApp.so-deployment-settings.json CACHE INTERNAL "aar deployment" FORCE) + configure_file(${PACKAGING_DIR}/android/libAusweisApp.so-deployment-settings.json.in ${ANDROID_DEPLOYMENT_SETTINGS} @ONLY) +else() + set(ANDROID_ROOT_LOGGER "") + configure_file(${PACKAGING_DIR}/android/fileprovider.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/fileprovider.xml COPYONLY) + configure_file(${PACKAGING_DIR}/android/full_backup_content.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/full_backup_content.xml COPYONLY) + configure_file(${PACKAGING_DIR}/android/data_extraction_rules.xml ${ANDROID_PACKAGE_SRC_DIR}/res/xml/data_extraction_rules.xml COPYONLY) +endif() + + +set(QT_BUILD_GRADLE "${QT_INSTALL_ARCHDATA}/src/android/templates/build.gradle") +set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append") +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${QT_BUILD_GRADLE}") +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${BUILD_GRADLE_APPEND}") + +file(READ "${QT_BUILD_GRADLE}" BUILD_GRADLE) + +if(INTEGRATED_SDK) + string(REPLACE "apply plugin: 'com.android.application'" "apply plugin: 'com.android.library'" BUILD_GRADLE "${BUILD_GRADLE}") +endif() + +file(WRITE "${ANDROID_BUILD_DIR}/build.gradle" "${BUILD_GRADLE}") +file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) +file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "${BUILD_GRADLE}") + +if(INTEGRATED_SDK) + set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.aar") + file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "${BUILD_GRADLE}") +elseif(USE_SMARTEID) + set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.smarteid") + file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "${BUILD_GRADLE}") +endif() + +if(NOT INTEGRATED_SDK) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "android.defaultConfig.applicationId '${BUNDLE_IDENTIFIER}'\n") + + if(BUILD_PREVIEW) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "android.defaultConfig.applicationIdSuffix '.dev'\n") + endif() +endif() + +option(ANDROID_LINT "Lint Android package" ON) +if(NOT ANDROID_LINT) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "tasks.lint.enabled = false\n") +endif() + +if(INTEGRATED_SDK) + set(ANDROID_FILE_EXT aar) + file(APPEND "${ANDROID_BUILD_DIR}/build.gradle" "android.defaultConfig.consumerProguardFiles 'consumer-rules.pro'\n") + if(DEFINED dvcs_revision) + set(POM_SNAPSHOT "-SNAPSHOT") + endif() + configure_file(${PACKAGING_DIR}/android/pom.xml.in ${ANDROID_BUILD_DIR}/${CPACK_PACKAGE_FILE_NAME}.pom @ONLY) + configure_file("${PACKAGING_DIR}/android/lint.aar.xml" "${ANDROID_BUILD_DIR}/lint.xml" COPYONLY) + configure_file("${PACKAGING_DIR}/android/consumer-rules.pro" "${ANDROID_BUILD_DIR}/consumer-rules.pro" COPYONLY) +else() + set(ANDROID_FILE_EXT apk) + if(USE_SMARTEID) + configure_file("${PACKAGING_DIR}/android/lint.apk.smarteid.xml" "${ANDROID_BUILD_DIR}/lint.xml" COPYONLY) + else() + configure_file("${PACKAGING_DIR}/android/lint.apk.xml" "${ANDROID_BUILD_DIR}/lint.xml" COPYONLY) + endif() +endif() +configure_file(${PACKAGING_DIR}/android/gradle.properties.in ${ANDROID_BUILD_DIR}/gradle.properties @ONLY) + +message(STATUS "Prepare ${ANDROID_FILE_EXT} file generation") + +if(CMAKE_BUILD_TYPE STREQUAL "DEBUG") + if(QT_ANDROID_SIGN_APK) + set(ANDROID_FILE ${ANDROID_BUILD_NAME}-debug-signed.${ANDROID_FILE_EXT}) + else() + set(ANDROID_FILE ${ANDROID_BUILD_NAME}-debug.${ANDROID_FILE_EXT}) + endif() + set(ANDROID_FILE_AAB ${ANDROID_BUILD_NAME}-debug.aab) +else() + if(INTEGRATED_SDK) + set(DEPLOY_CMD_SIGN --release) + set(ANDROID_FILE ${ANDROID_BUILD_NAME}-release.aar) + elseif(QT_ANDROID_SIGN_APK) + message(STATUS "Release build will be signed using: $ENV{QT_ANDROID_KEYSTORE_PATH} | Alias: $ENV{QT_ANDROID_KEYSTORE_ALIAS}") + set(ANDROID_FILE ${ANDROID_BUILD_NAME}-release-signed.apk) + else() + set(ANDROID_FILE ${ANDROID_BUILD_NAME}-release-unsigned.apk) + message(WARNING "Cannot sign release build! Set environment like QT_ANDROID_KEYSTORE_PATH") + endif() + set(ANDROID_FILE_AAB ${ANDROID_BUILD_NAME}-release.aab) +endif() + +set(SOURCE_ANDROID_FILE_OUTPUT ${ANDROID_BUILD_DIR}/build/outputs) +set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE_OUTPUT}/${ANDROID_FILE_EXT}) +if(NOT INTEGRATED_SDK) + set(SOURCE_ANDROID_FILE_AAB ${SOURCE_ANDROID_FILE_OUTPUT}/bundle) + if(CMAKE_BUILD_TYPE STREQUAL "DEBUG") + set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/debug) + set(SOURCE_ANDROID_FILE_AAB ${SOURCE_ANDROID_FILE_AAB}/debug) + else() + set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/release) + set(SOURCE_ANDROID_FILE_AAB ${SOURCE_ANDROID_FILE_AAB}/release) + endif() +endif() +set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/${ANDROID_FILE}) +set(SOURCE_ANDROID_FILE_AAB ${SOURCE_ANDROID_FILE_AAB}/${ANDROID_FILE_AAB}) + +set(DESTINATION_ANDROID_FILE_BASE ${PROJECT_BINARY_DIR}/dist/${CPACK_PACKAGE_FILE_NAME}) +set(DESTINATION_ANDROID_FILE ${DESTINATION_ANDROID_FILE_BASE}.${ANDROID_FILE_EXT}) +if(INTEGRATED_SDK) + find_program(androiddeployqt androiddeployqt HINTS "${QT_HOST_PATH}/bin" CMAKE_FIND_ROOT_PATH_BOTH) + if(NOT androiddeployqt) + message(FATAL_ERROR "Cannot find androiddeployqt to create AARs") + endif() + message(STATUS "Using androiddeployqt: ${androiddeployqt}") + set(DEPLOY_CMD ${androiddeployqt} --verbose --gradle --input ${ANDROID_DEPLOYMENT_SETTINGS} --android-platform android-${ANDROID_TARGET_SDK_VERSION} --output ${ANDROID_BUILD_DIR} ${DEPLOY_CMD_SIGN}) + add_custom_target(${ANDROID_FILE_EXT} + COMMAND ${DEPLOY_CMD} + DEPENDS AusweisAppBinary + USES_TERMINAL) + + add_custom_command(TARGET ${ANDROID_FILE_EXT} POST_BUILD + COMMAND ${ANDROID_BUILD_DIR}/gradlew sourcesJar + COMMAND ${CMAKE_COMMAND} -E copy_if_different "build/libs/${ANDROID_BUILD_NAME}-sources.jar" "${PROJECT_BINARY_DIR}/dist/${CPACK_PACKAGE_FILE_NAME}-sources.jar" + WORKING_DIRECTORY ${ANDROID_BUILD_DIR} + USES_TERMINAL) +else() + add_custom_command(TARGET aab POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SOURCE_ANDROID_FILE_AAB}" "${DESTINATION_ANDROID_FILE_BASE}.aab" + WORKING_DIRECTORY ${ANDROID_BUILD_DIR} + USES_TERMINAL) + + if(QT_ANDROID_SIGN_APK) + add_custom_command(TARGET apk POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SOURCE_ANDROID_FILE}.idsig" "${DESTINATION_ANDROID_FILE}.idsig" + WORKING_DIRECTORY ${ANDROID_BUILD_DIR} + USES_TERMINAL) + endif() +endif() + +add_custom_command(TARGET ${ANDROID_FILE_EXT} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SOURCE_ANDROID_FILE}" "${DESTINATION_ANDROID_FILE}" + COMMAND ${ANDROID_BUILD_DIR}/gradlew lint + WORKING_DIRECTORY ${ANDROID_BUILD_DIR} + USES_TERMINAL) + +if(INTEGRATED_SDK) + add_custom_command(TARGET aar POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ANDROID_BUILD_DIR}/${CPACK_PACKAGE_FILE_NAME}.pom" "${PROJECT_BINARY_DIR}/dist/${CPACK_PACKAGE_FILE_NAME}.pom" + WORKING_DIRECTORY ${ANDROID_BUILD_DIR}) +else() + find_program(apksigner apksigner HINTS ${ANDROID_SDK_ROOT}/build-tools/${ANDROID_BUILD_TOOLS_REVISION} CMAKE_FIND_ROOT_PATH_BOTH) + if(apksigner) + if(QT_ANDROID_SIGN_APK) + set(APKSIGNER_PARAM -v4-signature-file ${DESTINATION_ANDROID_FILE}.idsig) + endif() + add_custom_target(verify.signature COMMAND ${apksigner} verify --verbose --print-certs -Werr ${APKSIGNER_PARAM} ${DESTINATION_ANDROID_FILE}) + endif() + + find_program(aapt NAMES aapt2 aapt HINTS ${ANDROID_SDK_ROOT}/build-tools/${ANDROID_BUILD_TOOLS_REVISION} CMAKE_FIND_ROOT_PATH_BOTH) + if(aapt) + set(ANDROID_DUMP ${DESTINATION_ANDROID_FILE}.dump) + add_custom_command(OUTPUT ${ANDROID_DUMP} COMMAND ${aapt} dump badging ${DESTINATION_ANDROID_FILE} > ${ANDROID_DUMP}) + add_custom_target(dump.apk DEPENDS ${ANDROID_DUMP}) + endif() +endif() diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index 7cf02126b..7923a754a 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -3,7 +3,7 @@ set(PACKAGE_VERSION ${PROJECT_VERSION}) -if(ANDROID AND NOT INTEGRATED_SDK) +if(ANDROID) set(PACKAGE_VERSION ${PACKAGE_VERSION}-${CMAKE_ANDROID_ARCH_ABI}) endif() @@ -47,6 +47,7 @@ set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME}) if(NOT CONTAINER_SDK) set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.rst") set(CPACK_RESOURCE_FILE_LICENSE "${LICENSE_FILE}") + set(CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE ON) endif() @@ -146,124 +147,13 @@ elseif(APPLE) set(CPACK_DMG_BACKGROUND_IMAGE ${RESOURCES_DIR}/images/macos/dmg_background.png) set(CPACK_DMG_SLA_DIR ${MACOS_PACKAGING_DIR}/sla) set(CPACK_DMG_SLA_LANGUAGES English German) - set(CPACK_DMG_DS_STORE_SETUP_SCRIPT ${MACOS_PACKAGING_DIR}/prepare-ds_store.applescript) -elseif(ANDROID) - find_program(androiddeployqt androiddeployqt CMAKE_FIND_ROOT_PATH_BOTH) - if(NOT androiddeployqt) - message(FATAL_ERROR "Cannot find androiddeployqt to create APKs") - endif() - message(STATUS "Using androiddeployqt: ${androiddeployqt}") - - set(QT_BUILD_GRADLE "${QT_INSTALL_ARCHDATA}/src/android/templates/build.gradle") - set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append") - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${QT_BUILD_GRADLE}") - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${BUILD_GRADLE_APPEND}") - - file(READ "${QT_BUILD_GRADLE}" BUILD_GRADLE) - - if(INTEGRATED_SDK) - string(REPLACE "apply plugin: 'com.android.application'" "apply plugin: 'com.android.library'" BUILD_GRADLE "${BUILD_GRADLE}") - endif() - - file(WRITE "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}") - file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}") - - if(INTEGRATED_SDK) - set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.aar") - file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}") - elseif(USE_SMARTEID) - set(BUILD_GRADLE_APPEND "${PACKAGING_DIR}/android/build.gradle.append.smarteid") - file(READ "${BUILD_GRADLE_APPEND}" BUILD_GRADLE) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "${BUILD_GRADLE}") - endif() - - if(NOT INTEGRATED_SDK) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "android.defaultConfig.applicationId '${BUNDLE_IDENTIFIER}'\n") - - if(BUILD_PREVIEW) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "android.defaultConfig.applicationIdSuffix '.dev'\n") - endif() - endif() + # Temporarily toggle the following lines to generate a new DS_Store, preferably with CI. + # set(CPACK_DMG_DS_STORE_SETUP_SCRIPT ${MACOS_PACKAGING_DIR}/prepare-ds_store.applescript) + set(CPACK_DMG_DS_STORE ${MACOS_PACKAGING_DIR}/DS_Store) - option(ANDROID_LINT "Lint Android package" ON) - if(NOT ANDROID_LINT) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "tasks.lint.enabled = false\n") - endif() - - if(INTEGRATED_SDK) - set(ANDROID_FILE_EXT aar) - file(APPEND "${CMAKE_INSTALL_PREFIX}/build.gradle" "android.defaultConfig.consumerProguardFiles 'consumer-rules.pro'\n") - if(DEFINED dvcs_revision) - set(POM_SNAPSHOT "-SNAPSHOT") - endif() - configure_file(${PACKAGING_DIR}/android/pom.xml.in ${CMAKE_INSTALL_PREFIX}/${CPACK_PACKAGE_FILE_NAME}.pom @ONLY) - configure_file("${PACKAGING_DIR}/android/lint.aar.xml" "${CMAKE_INSTALL_PREFIX}/lint.xml" COPYONLY) - configure_file("${PACKAGING_DIR}/android/consumer-rules.pro" "${CMAKE_INSTALL_PREFIX}/consumer-rules.pro" COPYONLY) - else() - set(ANDROID_FILE_EXT apk) - configure_file("${PACKAGING_DIR}/android/lint.apk.xml" "${CMAKE_INSTALL_PREFIX}/lint.xml" COPYONLY) - endif() - message(STATUS "Prepare ${ANDROID_FILE_EXT} file generation") - - if(CMAKE_BUILD_TYPE STREQUAL "DEBUG") - set(ANDROID_FILE dist-debug.${ANDROID_FILE_EXT}) - else() - set(DEPLOY_CMD_SIGN --release) - - if(INTEGRATED_SDK) - set(ANDROID_FILE dist-release.aar) - elseif(APK_SIGN_KEYSTORE AND APK_SIGN_KEYSTORE_ALIAS AND APK_SIGN_KEYSTORE_PSW) - message(STATUS "Release build will be signed using: ${APK_SIGN_KEYSTORE} | Alias: ${APK_SIGN_KEYSTORE_ALIAS}") - set(DEPLOY_CMD_SIGN ${DEPLOY_CMD_SIGN} --sign ${APK_SIGN_KEYSTORE} ${APK_SIGN_KEYSTORE_ALIAS} --storepass ${APK_SIGN_KEYSTORE_PSW} --digestalg SHA-256 --sigalg SHA256WithRSA) - set(ANDROID_FILE dist-release-signed.apk) - else() - set(ANDROID_FILE dist-release-unsigned.apk) - message(WARNING "Cannot sign release build! Set APK_SIGN_KEYSTORE, APK_SIGN_KEYSTORE_ALIAS and APK_SIGN_KEYSTORE_PSW!") - endif() - endif() - - set(DEPLOY_CMD ${androiddeployqt} --verbose --gradle --input ${ANDROID_DEPLOYMENT_SETTINGS} --android-platform android-${ANDROID_TARGET_SDK_VERSION} --output ${CMAKE_INSTALL_PREFIX} ${DEPLOY_CMD_SIGN}) - set(SOURCE_ANDROID_FILE ${CMAKE_INSTALL_PREFIX}/build/outputs/${ANDROID_FILE_EXT}) - - if(NOT INTEGRATED_SDK) - if(CMAKE_BUILD_TYPE STREQUAL "DEBUG") - set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/debug) - else() - set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/release) - endif() - endif() - - set(SOURCE_ANDROID_FILE ${SOURCE_ANDROID_FILE}/${ANDROID_FILE}) - - set(DESTINATION_ANDROID_FILE ${CMAKE_INSTALL_PREFIX}/${CPACK_PACKAGE_FILE_NAME}.${ANDROID_FILE_EXT}) - # Add DEPENDS install someday - # https://gitlab.kitware.com/cmake/cmake/issues/8438 - add_custom_target(${ANDROID_FILE_EXT} - COMMAND ${DEPLOY_CMD} - COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_ANDROID_FILE} ${DESTINATION_ANDROID_FILE} - USES_TERMINAL) - - add_custom_command(TARGET ${ANDROID_FILE_EXT} POST_BUILD - COMMAND ${CMAKE_INSTALL_PREFIX}/gradlew sourcesJar lint - COMMAND ${CMAKE_COMMAND} -E copy build/libs/dist-sources.jar ${CPACK_PACKAGE_FILE_NAME}-sources.jar - WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}) - - if(NOT INTEGRATED_SDK) - find_program(apksigner apksigner HINTS ${ANDROID_SDK}/build-tools/${ANDROID_BUILD_TOOLS_REVISION} CMAKE_FIND_ROOT_PATH_BOTH) - if(apksigner) - add_custom_target(verify.signature COMMAND ${apksigner} verify --verbose --print-certs -Werr ${DESTINATION_ANDROID_FILE}) - endif() - - find_program(aapt NAMES aapt2 aapt HINTS ${ANDROID_SDK}/build-tools/${ANDROID_BUILD_TOOLS_REVISION} CMAKE_FIND_ROOT_PATH_BOTH) - if(aapt) - set(ANDROID_DUMP ${DESTINATION_ANDROID_FILE}.dump) - add_custom_command(OUTPUT ${ANDROID_DUMP} COMMAND ${aapt} dump badging ${DESTINATION_ANDROID_FILE} > ${ANDROID_DUMP}) - add_custom_target(dump.apk DEPENDS ${ANDROID_DUMP}) - endif() - endif() +elseif(ANDROID) + include(Packaging.android) elseif(UNIX) set(CPACK_GENERATOR STGZ) diff --git a/cmake/Policies.cmake b/cmake/Policies.cmake index c556daec6..4b5bf0e25 100644 --- a/cmake/Policies.cmake +++ b/cmake/Policies.cmake @@ -44,4 +44,8 @@ endif() if(POLICY CMP0099) cmake_policy(SET CMP0099 NEW) -endif() \ No newline at end of file +endif() + +if(POLICY CMP0133) + cmake_policy(SET CMP0133 NEW) +endif() diff --git a/cmake/PoliciesQt.cmake b/cmake/PoliciesQt.cmake new file mode 100644 index 000000000..3cb44a55c --- /dev/null +++ b/cmake/PoliciesQt.cmake @@ -0,0 +1,7 @@ +if(QT_KNOWN_POLICY_QTP0001) + qt_policy(SET QTP0001 NEW) +endif() + +if(QT_KNOWN_POLICY_QTP0002) + qt_policy(SET QTP0002 NEW) +endif() diff --git a/cmake/SignFiles.cmake.in b/cmake/SignFiles.cmake.in index f9a2d3e25..f23a83b86 100644 --- a/cmake/SignFiles.cmake.in +++ b/cmake/SignFiles.cmake.in @@ -122,5 +122,5 @@ if(APPLE AND NOT IOS) file(GLOB_RECURSE APP_BINARY ${CMAKE_BINARY_DIR}/*/@PROJECT_NAME@) message("Signing app bundle: ${APP_BINARY}") - execute_process(COMMAND "@SIGNTOOL_CMD@" ${BUNDLE_APPLE_CODESIGN_PARAMETER} --entitlements @PACKAGING_DIR@/macos/@PROJECT_NAME@.entitlements -i @BUNDLE_IDENTIFIER@ ${APP_BINARY}) + execute_process(COMMAND "@SIGNTOOL_CMD@" ${BUNDLE_APPLE_CODESIGN_PARAMETER} --entitlements @CMAKE_BINARY_DIR@/entitlements.plist -i @BUNDLE_IDENTIFIER@ ${APP_BINARY}) endif() diff --git a/cmake/SwiftPackage.cmake b/cmake/SwiftPackage.cmake index ac65ab2af..ebe52ee28 100644 --- a/cmake/SwiftPackage.cmake +++ b/cmake/SwiftPackage.cmake @@ -66,7 +66,16 @@ get_filename_component(SCRIPT_DIR "${CMAKE_SCRIPT_MODE_FILE}" DIRECTORY) set(PACKAGING_DIR "${SCRIPT_DIR}/../resources/packaging") configure_file("${PACKAGING_DIR}/ios/Package.swift" "${CMAKE_BINARY_DIR}/Package.swift" COPYONLY) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/dist) -set(dist_filename dist/${prefix}-${APP_NAME_VERSION}${APP_MISMATCH}.swiftpackage.zip) +if(DIST_DIR) + get_filename_component(DIST_DIR "${DIST_DIR}" ABSOLUTE) +else() + set(DIST_DIR ${CMAKE_BINARY_DIR}/dist) +endif() + +if(NOT EXISTS "${DIST_DIR}") + file(MAKE_DIRECTORY ${DIST_DIR}) +endif() + +set(dist_filename ${DIST_DIR}/${prefix}-${APP_NAME_VERSION}${APP_MISMATCH}.swiftpackage.zip) message(STATUS "Create package: ${dist_filename}") execute_process(COMMAND ${CMAKE_COMMAND} -E tar cf "${dist_filename}" --format=zip ${prefix}.xcframework Package.swift) diff --git a/cmake/Tools.Libraries.cmake b/cmake/Tools.Libraries.cmake index 9237c91ca..73f02d7cd 100644 --- a/cmake/Tools.Libraries.cmake +++ b/cmake/Tools.Libraries.cmake @@ -26,7 +26,6 @@ if(NOT TARGET format.qml) unset(QMLFORMAT CACHE) # let's retry later else() file(GLOB_RECURSE FILES_QML ${PROJECT_SOURCE_DIR}/*.qml) - set(QMLFORMAT_CMD ${QMLFORMAT} -i -n -l unix -t -w 4) set(FORMATTING_FILE ${PROJECT_BINARY_DIR}/formatting.files.qml) file(WRITE ${FORMATTING_FILE} "") @@ -35,7 +34,9 @@ if(NOT TARGET format.qml) file(APPEND ${FORMATTING_FILE} "\n") endforeach() - add_custom_target(format.qml COMMAND ${QMLFORMAT_CMD} -F ${FORMATTING_FILE} SOURCES ${FILES_QML}) + add_custom_target(format.qml + COMMAND ${CMAKE_COMMAND} -E echo Calling ${QMLFORMAT} in version ${QMLFORMAT_VERSION} + COMMAND ${QMLFORMAT} -F ${FORMATTING_FILE} SOURCES ${FILES_QML}) add_dependencies(format format.qml) endif() endif() diff --git a/cmake/Tools.cmake b/cmake/Tools.cmake index 135ea668f..f7fb2c64b 100644 --- a/cmake/Tools.cmake +++ b/cmake/Tools.cmake @@ -115,6 +115,25 @@ if(UNCRUSTIFY) endif() endif() +find_program(DOS2UNIX dos2unix CMAKE_FIND_ROOT_PATH_BOTH) +if(DOS2UNIX) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.cpp) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.h) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.rst) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.svg) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/CMakeLists.txt) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.cmake) + list(APPEND GLOB_FILES ${PROJECT_SOURCE_DIR}/*.cmake.in) + file(GLOB_RECURSE FILES ${GLOB_FILES}) + + foreach(FILE ${FILES}) + list(APPEND commands COMMAND ${DOS2UNIX} -q -k --add-eol ${FILE}) + endforeach() + + add_custom_target(format.dos2unix ${commands}) + add_dependencies(format format.dos2unix) +endif() + find_program(PYTHON python CMAKE_FIND_ROOT_PATH_BOTH) if(PYTHON) list(APPEND GLOB_JSON ${RESOURCES_DIR}/updatable-files/*.json) @@ -130,16 +149,6 @@ if(PYTHON) add_dependencies(format format.json) endif() -find_program(QMLLINT_BIN qmllint CMAKE_FIND_ROOT_PATH_BOTH) -if(QMLLINT_BIN) - file(GLOB_RECURSE TEST_FILES_QML ${TEST_DIR}/qml/*.qml) - file(GLOB_RECURSE FILES_QML ${RESOURCES_DIR}/qml/*.qml) - file(GLOB_RECURSE FILES_JS ${RESOURCES_DIR}/qml/*.js) - set(QMLLINT_CMD ${QMLLINT_BIN} ${FILES_QML} ${FILES_JS}) - - add_custom_target(qmllint COMMAND ${QMLLINT_CMD} SOURCES ${TEST_FILES_QML} ${FILES_QML} ${FILES_JS}) -endif() - # doc8 (https://pypi.python.org/pypi/doc8) find_program(DOC8_BIN doc8 CMAKE_FIND_ROOT_PATH_BOTH) function(CREATE_DOC8_TARGET _dir _name) @@ -323,12 +332,9 @@ if(INKSCAPE) add_custom_target(readerimages COMMAND ${INKSCAPE} img_RemoteReader.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_RemoteReader.png - COMMAND ${INKSCAPE} img_RemoteReader_mit_ausweis.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_RemoteReader_mit_ausweis.png COMMAND ${INKSCAPE} img_PersoSim.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_PersoSim.png - COMMAND ${INKSCAPE} img_PersoSim_mit_ausweis.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_PersoSim_mit_ausweis.png COMMAND ${INKSCAPE} img_Simulator.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_Simulator.png - COMMAND ${INKSCAPE} img_Simulator_mit_ausweis.svg -w 512 -h 512 -y 0 -o ${RESOURCES_DIR}/updatable-files/reader/img_Simulator_mit_ausweis.png - WORKING_DIRECTORY ${RESOURCES_DIR}/images/reader/src) + WORKING_DIRECTORY ${RESOURCES_DIR}/images/src) endif() find_program(PNGQUANT pngquant CMAKE_FIND_ROOT_PATH_BOTH) @@ -496,11 +502,8 @@ if(PNGQUANT) add_custom_target(pngquant.readerimages COMMAND ${PNGQUANT_CMD} img_RemoteReader.png -- img_RemoteReader.png - COMMAND ${PNGQUANT_CMD} img_RemoteReader_mit_ausweis.png -- img_RemoteReader_mit_ausweis.png COMMAND ${PNGQUANT_CMD} img_PersoSim.png -- img_PersoSim.png - COMMAND ${PNGQUANT_CMD} img_PersoSim_mit_ausweis.png -- img_PersoSim_mit_ausweis.png COMMAND ${PNGQUANT_CMD} img_Simulator.png -- img_Simulator.png - COMMAND ${PNGQUANT_CMD} img_Simulator_mit_ausweis.png -- img_Simulator_mit_ausweis.png WORKING_DIRECTORY ${RESOURCES_DIR}/updatable-files/reader) endif() @@ -527,7 +530,7 @@ if(INKSCAPE AND APPLE AND NOT IOS) COMMAND ${INKSCAPE} appIcon.svg -w 512 -h 512 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_256x256@2x.png COMMAND ${INKSCAPE} appIcon.svg -w 512 -h 512 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_512x512.png COMMAND ${INKSCAPE} appIcon.svg -w 1024 -h 1024 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_512x512@2x.png - COMMAND ${ICONUTIL} -c icns --output AusweisApp2.icns ${BUNDLE_ICON_SET_DIR} + COMMAND ${ICONUTIL} -c icns --output "${PROJECT_NAME}.icns" ${BUNDLE_ICON_SET_DIR} COMMAND ${CMAKE_COMMAND} -E remove_directory ${BUNDLE_ICON_SET_DIR} WORKING_DIRECTORY ${RESOURCES_DIR}/images/macos) @@ -543,7 +546,7 @@ if(INKSCAPE AND APPLE AND NOT IOS) COMMAND ${INKSCAPE} appIconBeta.svg -w 512 -h 512 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_256x256@2x.png COMMAND ${INKSCAPE} appIconBeta.svg -w 512 -h 512 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_512x512.png COMMAND ${INKSCAPE} appIconBeta.svg -w 1024 -h 1024 -y 0 -o ${BUNDLE_ICON_SET_DIR}/icon_512x512@2x.png - COMMAND ${ICONUTIL} -c icns --output beta/AusweisApp2.icns ${BUNDLE_ICON_SET_DIR} + COMMAND ${ICONUTIL} -c icns --output "beta/${PROJECT_NAME}.icns" ${BUNDLE_ICON_SET_DIR} COMMAND ${CMAKE_COMMAND} -E remove_directory ${BUNDLE_ICON_SET_DIR} WORKING_DIRECTORY ${RESOURCES_DIR}/images/macos) endif() @@ -569,11 +572,10 @@ if(DOT) # 1. Strip line of plugins as it is misleading # 2. Strip "AusweisApp" prefix add_custom_target(architecture.sed - COMMAND ${SED} -i -E '/AusweisApp -> AusweisApp\(Ui|Card|Activation\).+/d' ${architecture_file} - COMMAND ${SED} -i'' -e 's/"AusweisApp"/"AusweisApp2"/' ${architecture_file} - COMMAND ${SED} -i'' -e 's/"AusweisApp2"/"REPLACE"/' ${architecture_file} + COMMAND ${SED} -i -E '/AusweisAppBinary -> AusweisApp\(Ui|Card|Activation\).+/d' ${architecture_file} + COMMAND ${SED} -i'' -e 's/"AusweisApp"/"REPLACE"/' ${architecture_file} COMMAND ${SED} -i'' -e 's/AusweisApp//' ${architecture_file} - COMMAND ${SED} -i'' -e 's/"REPLACE"/"AusweisApp2"/' ${architecture_file} + COMMAND ${SED} -i'' -e 's/"REPLACE"/"AusweisApp"/' ${architecture_file} COMMAND ${SED} -i'' -e 's/diamond/box/' ${architecture_file} DEPENDS ${ARCHI_PDF_DEPENDS} WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) diff --git a/cmake/Translation.cmake.in b/cmake/Translation.cmake.in index d276ead4d..ca02af662 100644 --- a/cmake/Translation.cmake.in +++ b/cmake/Translation.cmake.in @@ -8,9 +8,15 @@ foreach(file @TRANSLATION_FILES@) \n\ DvcsAttributes\n\ \n\ - revision\n\ + @dvcs_revision@\n\ + revision\n\ @dvcs_revision@\n\ \n\ + \n\ + @PROJECT_VERSION@\n\ + version\n\ + @PROJECT_VERSION@\n\ + \n\ \n\ " TR_FILE "${TR_FILE}") file(WRITE ${file} "${TR_FILE}") diff --git a/cmake/android.toolchain.cmake b/cmake/android.toolchain.cmake index 51635da33..bfaf2131c 100644 --- a/cmake/android.toolchain.cmake +++ b/cmake/android.toolchain.cmake @@ -1,8 +1,3 @@ -cmake_minimum_required(VERSION 3.16.0) -if(CMAKE_VERSION VERSION_LESS "3.16.4") - message(WARNING "Check your cmake: https://gitlab.kitware.com/cmake/cmake/commit/e3d3b7ddeb5922a4d17b962984e698e6387f7544") -endif() - function(READ_REVISION _var _regex _files) foreach(file ${_files}) if(EXISTS "${file}") @@ -27,15 +22,15 @@ IF(NOT CMAKE_ANDROID_NDK) endif() endif() -set(ANDROID_SDK $ENV{ANDROID_SDK_ROOT}) +set(ANDROID_SDK_ROOT $ENV{ANDROID_SDK_ROOT}) set(ANDROID_BUILD_TOOLS_REVISION $ENV{ANDROID_BUILD_TOOLS_REVISION}) -if(NOT EXISTS "${ANDROID_SDK}") +if(NOT EXISTS "${ANDROID_SDK_ROOT}") message(FATAL_ERROR "Environment variable ANDROID_SDK_ROOT is undefined") endif() if(NOT ANDROID_BUILD_TOOLS_REVISION) - set(_android_build_tools_dir "${ANDROID_SDK}/build-tools") + set(_android_build_tools_dir "${ANDROID_SDK_ROOT}/build-tools") file(GLOB build_tools_list ${_android_build_tools_dir}/*) list(LENGTH build_tools_list build_tools_len) @@ -53,18 +48,49 @@ endif() READ_REVISION(ANDROID_NDK_REVISION ".*Revision = ([0-9|\\.]+)" "${CMAKE_ANDROID_NDK}/source.properties") +if(NOT QT_TOOLCHAIN_FILE) + foreach(path ${CMAKE_PREFIX_PATH}) + set(file ${path}/lib/cmake/Qt6/qt.toolchain.cmake) + if(EXISTS "${file}") + set(QT_TOOLCHAIN_FILE ${file}) + break() + endif() + endforeach() +endif() + +if(QT_TOOLCHAIN_FILE) + message(STATUS "QT_TOOLCHAIN_FILE: ${QT_TOOLCHAIN_FILE}") + include(${QT_TOOLCHAIN_FILE}) +endif() + +set(ANDROID_BUILD_NAME android-build) +set(ANDROID_BUILD_DIR "${PROJECT_BINARY_DIR}/src/${ANDROID_BUILD_NAME}") +set(ANDROID_PACKAGE_SRC_DIR ${PROJECT_BINARY_DIR}/package-src-dir) +set(QT_ENABLE_VERBOSE_DEPLOYMENT ON) + +if(DEFINED ENV{QT_ANDROID_KEYSTORE_PATH} AND NOT INTEGRATED_SDK) + set(QT_ANDROID_SIGN_APK ON) + set(QT_ANDROID_SIGN_AAB ON) +endif() + set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang) set(CMAKE_SYSTEM_NAME Android) -set(CMAKE_SYSTEM_VERSION 26) -set(ANDROID_TARGET_SDK_VERSION 34) +set(CMAKE_SYSTEM_VERSION 28) +set(ANDROID_TARGET_SDK_VERSION 35) set(CMAKE_ANDROID_STL_TYPE c++_shared) if(NOT CMAKE_ANDROID_ARCH_ABI) - if(INTEGRATED_SDK) - set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) - else() - set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) - endif() + set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) +endif() + +# Only required by CMake < 3.30.3 with Android NDK 27 when +# CMAKE_ANDROID_ARCH_ABI is not set. Will be fixed with Android NDK 27b. +# https://bugreports.qt.io/browse/QTBUG-127468 +if(ANDROID_NDK_REVISION VERSION_EQUAL "27.0.12077973" AND CMAKE_VERSION VERSION_LESS "3.30.3") + set(NDK_PROC_aarch64_ABI "DUMMY") + set(NDK_PROC_armv7-a_ABI "DUMMY") + set(NDK_PROC_i686_ABI "DUMMY") + set(NDK_PROC_x86_64_ABI "DUMMY") endif() if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") @@ -72,7 +98,8 @@ if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") set(CMAKE_ANDROID_ARM_NEON ON) endif() -set(CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH} CACHE STRING "android find search path root") set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +set(GOVERNIKUS_TOOLCHAIN_FILE ON) diff --git a/cmake/ci/Android.cmake b/cmake/ci/Android.cmake new file mode 100644 index 000000000..6016522e4 --- /dev/null +++ b/cmake/ci/Android.cmake @@ -0,0 +1,41 @@ +if(NAME MATCHES "_APK_") + set(APK ON) + set(PRESET ci-android-apk) +elseif(NAME MATCHES "_AAR_") + set(AAR ON) + set(PRESET ci-android-aar) +else() + step(${CMAKE_COMMAND} -DDIST_DIR=${T_DIST_DIR} -P ${CMAKE_DIR}/Merge.cmake) + + if(RELEASE) + set(files *-sources.jar *.aar *.pom) + foreach(file ${files}) + file(GLOB file "${T_DIST_DIR}/${file}") + step(gpg --batch --passphrase $ENV{GPG_PSW} --pinentry-mode loopback -a --detach-sig -u $ENV{GPG_ID} ${file}) + endforeach() + endif() + + if(NOT REVIEW) + step(${CMAKE_COMMAND} -DCMD=DEPLOY_NEXUS -DPUBLISH=$ENV{PUBLISH} -P ${CMAKE_DIR}/cmd.cmake CHDIR ${T_DIST_DIR}) + endif() + return() +endif() + +if(REVIEW) + set(PRESET ${PRESET}-review) +endif() + +step(${T_CFG} --preset ${PRESET}) +step(${T_BUILD}) + +if(APK) + step(${T_TARGET} apk) + step(${T_TARGET} verify.signature) + step(${T_TARGET} dump.apk) +elseif(AAR) + step(${T_TARGET} aar) +endif() + +if(NOT RELEASE) + step(${T_CTEST}) +endif() diff --git a/cmake/ci/Configuration.cmake b/cmake/ci/Configuration.cmake new file mode 100644 index 000000000..bc4b74fab --- /dev/null +++ b/cmake/ci/Configuration.cmake @@ -0,0 +1,4 @@ +step(${T_CFG} --preset ci-linux) +step(${T_TARGET} ALL_Test_configuration) +step(${T_CTEST} -R Test_configuration ENV QT_PLUGIN_PATH=${WORKSPACE}/libs/dist/plugins) +step(${T_CTEST} -L json) diff --git a/cmake/ci/Container.cmake b/cmake/ci/Container.cmake new file mode 100644 index 000000000..ef3c81d4b --- /dev/null +++ b/cmake/ci/Container.cmake @@ -0,0 +1,65 @@ +if(NAME MATCHES "VNC") + set(TARGET vnc) + set(Dockerfile -f ${CMAKE_SOURCE_DIR}/resources/jenkins/docker/Dockerfile) +else() + set(TARGET sdk) +endif() + +if(RELEASE) + set(TAG $ENV{changeset}) + set(FILE_TAG ${TAG}) +elseif(REVIEW) + set(TAG $ENV{BUILD_TAG}) + set(FILE_TAG ${TAG}) +else() + set(TAG dev-$ENV{MERCURIAL_REVISION_BRANCH}) + string(REPLACE "-default" "" TAG "${TAG}") + set(FILE_TAG $ENV{MERCURIAL_REVISION_SHORT}) +endif() + +if(NOT EXISTS ${T_BUILD_DIR}) + step(${CMAKE_COMMAND} -E make_directory ${T_BUILD_DIR}) +endif() + +if(NOT VNC) + step(docker container prune -f) +endif() + +step(docker build --pull + -t dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG} + --build-arg CCACHE_REMOTE_STORAGE=redis://$ENV{CCACHE_REMOTE_STORAGE_HOST} + ${Dockerfile} + ${CMAKE_SOURCE_DIR} +) + +step(docker run --rm dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG} AusweisApp --help) + +step(docker save -o ${T_BUILD_DIR}/AusweisApp-${FILE_TAG}.tar dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG}) + +if(REVIEW) + step(docker rmi -f dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG}) +else() + step(docker push dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG}) +endif() + + +if(DAILY AND NOT VNC) + step(docker images --filter "dangling=true" -q OUTPUT IMAGES) + if(IMAGES) + string(STRIP "${IMAGES}" IMAGES) + string(REPLACE "\n" ";" IMAGES "${IMAGES}") + list(REVERSE IMAGES) + list(SUBLIST IMAGES 0 50 IMAGES) + foreach(entry ${IMAGES}) + step(docker rmi -f ${entry}) + endforeach() + endif() +endif() + + +if(RELEASE AND DEFINED ENV{LATEST}) + if($ENV{LATEST}) + step(docker tag dev-docker.govkg.de/ausweisapp/${TARGET}:${TAG} dev-docker.govkg.de/ausweisapp/${TARGET}:latest) + step(docker push dev-docker.govkg.de/ausweisapp/${TARGET}:latest) + endif() +endif() diff --git a/cmake/ci/Docker.cmake b/cmake/ci/Docker.cmake new file mode 100644 index 000000000..38d73c309 --- /dev/null +++ b/cmake/ci/Docker.cmake @@ -0,0 +1 @@ +include(Container) diff --git a/cmake/ci/Docs.cmake b/cmake/ci/Docs.cmake new file mode 100644 index 000000000..3959d673a --- /dev/null +++ b/cmake/ci/Docs.cmake @@ -0,0 +1,20 @@ +step(${T_CFG} --preset ci-tools) + +step(${T_TARGET} notes) +step(${T_TARGET} notes.latex.pdf) +step(${CMAKE_COMMAND} -E tar cfJ ../AusweisApp_ReleaseNotes.tar.xz . CHDIR ${T_BUILD_DIR}/docs/notes) + +step(${T_TARGET} sdk) +step(${T_TARGET} sdk.latex.pdf) +step(${CMAKE_COMMAND} -E tar cfJ ../AusweisApp_SDK.tar.xz . CHDIR ${T_BUILD_DIR}/docs/sdk/html) + +step(${T_TARGET} failurecodes) +step(${T_TARGET} failurecodes.latex.pdf) + +step(${T_TARGET} installation_integration.latex.pdf) + +step(${T_TARGET} license) + +if(NOT RELEASE) + step(${T_TARGET} doc8) +endif() diff --git a/cmake/ci/Formatting.cmake b/cmake/ci/Formatting.cmake new file mode 100644 index 000000000..966ea5f80 --- /dev/null +++ b/cmake/ci/Formatting.cmake @@ -0,0 +1,3 @@ +step(${T_CFG} --preset ci-tools-with-libs) +step(${CMAKE_SOURCE_DIR}/resources/jenkins/check_formatting.sh ${PENDING_PATCH} CHDIR ${CMAKE_SOURCE_DIR}) +step(${CMAKE_COMMAND} -DCMD=CHECK_FAILURE_CODES -P ${CMAKE_DIR}/cmd.cmake CHDIR ${CMAKE_SOURCE_DIR}) diff --git a/cmake/ci/FreeBSD.cmake b/cmake/ci/FreeBSD.cmake new file mode 100644 index 000000000..5e028311f --- /dev/null +++ b/cmake/ci/FreeBSD.cmake @@ -0,0 +1,5 @@ +set(LD_ENV LD_LIBRARY_PATH=${WORKSPACE}/libs/dist/lib) + +step(${T_CFG} --preset ci-bsd) +step(${T_BUILD} ENV ${LD_ENV}) +step(${T_CTEST} ENV ${LD_ENV} QT_PLUGIN_PATH=${WORKSPACE}/libs/dist/plugins QML2_IMPORT_PATH=${WORKSPACE}/libs/dist/qml) diff --git a/cmake/ci/Linux.cmake b/cmake/ci/Linux.cmake new file mode 100644 index 000000000..ec3dd3247 --- /dev/null +++ b/cmake/ci/Linux.cmake @@ -0,0 +1,22 @@ +if(NAME MATCHES "Integrated") + set(INTEGRATED ON) +endif() + +if(INTEGRATED) + set(PRESET ci-integrated) +else() + set(PRESET ci-linux) +endif() + +step(${T_CFG} --preset ${PRESET}) +step(${T_BUILD}) +step(${T_CTEST} ENV QT_PLUGIN_PATH=${WORKSPACE}/libs/dist/plugins QML2_IMPORT_PATH=${WORKSPACE}/libs/dist/qml) + +if(NOT INTEGRATED) + step(${CMAKE_COMMAND} --install ${T_BUILD_DIR} ENV DESTDIR=${WORKSPACE}/install) +endif() + +if(DAILY AND NOT INTEGRATED) + step(${T_TARGET} gcovr) + step(${T_TARGET} cloc.report) +endif() diff --git a/cmake/ci/MacOS.cmake b/cmake/ci/MacOS.cmake new file mode 100644 index 000000000..ccaf84e6e --- /dev/null +++ b/cmake/ci/MacOS.cmake @@ -0,0 +1,53 @@ +if(NAME MATCHES "Integrated") + set(INTEGRATED ON) +endif() + +if(NAME MATCHES "DMG_PKG" OR RELEASE) + set(PACKAGES ON) +endif() + +if(PACKAGES) + set(PRESET ci-macos-release) +elseif(INTEGRATED) + set(PRESET ci-macos-integrated) +else() + set(PRESET ci-macos) + set(CTEST_CFG -C Debug) +endif() + +step(security unlock-keychain $ENV{KEYCHAIN_CREDENTIALS} $ENV{HOME}/Library/Keychains/login.keychain-db) + +step(${T_CFG} --preset ${PRESET}) + +if(PACKAGES) + step(${T_TARGET} package --config MinSizeRel) + step(${CMAKE_COMMAND} -E tar cf ../../AusweisApp.app.dSYM.zip --format=zip AusweisApp.app.dSYM CHDIR ${T_BUILD_DIR}/src/MinSizeRel) + + file(GLOB_RECURSE apps LIST_DIRECTORIES ON "${T_BUILD_DIR}/_CPack_Packages/Darwin") + list(FILTER apps INCLUDE REGEX "\\.app$") + set(dragndrop ${apps}) + list(FILTER dragndrop INCLUDE REGEX "/DragNDrop/") + if(NOT dragndrop OR NOT apps) + message(FATAL_ERROR "no *.app directory found") + endif() + foreach(app ${apps}) + step(codesign -vvvv ${app}) + endforeach() + foreach(app ${dragndrop}) + step(spctl -a -vv ${app}) + endforeach() + + if(NOT REVIEW) + step(${CMAKE_COMMAND} -P ${CMAKE_DIR}/Notarization.cmake CHDIR ${T_BUILD_DIR}) + endif() +else() + step(${T_BUILD}) + step(${T_CTEST} ${CTEST_CFG} ENV QT_PLUGIN_PATH=${WORKSPACE}/libs/dist/plugins QML2_IMPORT_PATH=${WORKSPACE}/libs/dist/qml) +endif() + +if(RELEASE AND DEFINED ENV{USE_DISTRIBUTION_PROFILE}) + if($ENV{USE_DISTRIBUTION_PROFILE}) + file(GLOB pkgfile "${T_BUILD_DIR}/*.pkg") + step(xcrun altool -t osx --upload-app -u "ausweisapp@governikus.com" -p @env:PASSWORD -f ${pkgfile}) + endif() +endif() diff --git a/cmake/ci/SonarQube.cmake b/cmake/ci/SonarQube.cmake new file mode 100644 index 000000000..36bda2960 --- /dev/null +++ b/cmake/ci/SonarQube.cmake @@ -0,0 +1,49 @@ +set(CACHE_DIR cache) +if(NOT EXISTS ${CACHE_DIR}) + step(${CMAKE_COMMAND} -E make_directory ${CACHE_DIR}) +endif() + +set(SONARPATH ${WORKSPACE}/sonarqubetools) + +step(${CMAKE_COMMAND} -P ${CMAKE_DIR}/prepare_sonarqube_env.cmake) + +step(${T_CFG} --preset ci-linux) + +step(${SONARPATH}/dependency-check/bin/dependency-check.sh + --enableExperimental -f HTML -f JSON --scan ${CMAKE_DIR} --noupdate + --connectionString=jdbc:mariadb://dependency-check-db.govkg.de/dependencycheck + --dbUser=$ENV{DEPENDENCY_CHECK_USER} + --dbPassword=$ENV{DEPENDENCY_CHECK_PASSWORD} + --dbDriverName=org.mariadb.jdbc.Driver + CHDIR ${T_BUILD_DIR} +) + +step(${SONARPATH}/sonar-build-wrapper/build-wrapper-linux-x86-64 --out-dir ${T_BUILD_DIR} ${T_BUILD}) + +step(${T_CTEST} -LE qml -E Test_ui_qml_Qml) + +step(${T_TARGET} gcovr.sonar) + + + +if(REVIEW) + set(SONAR_CMDLINE + -Dsonar.pullrequest.key=$ENV{REVIEWBOARD_REVIEW_ID} + -Dsonar.pullrequest.branch=$ENV{REVIEWBOARD_REVIEW_ID} + -Dsonar.pullrequest.base=$ENV{MERCURIAL_REVISION_BRANCH} + ) +else() + set(SONAR_CMDLINE + -Dsonar.branch.name=$ENV{MERCURIAL_REVISION_BRANCH} + ) +endif() + +step( + ${SONARPATH}/sonar-scanner/bin/sonar-scanner + -Dsonar.scanner.metadataFilePath=${WORKSPACE}/tmp/sonar-metadata.txt + ${SONAR_CMDLINE} + -Dsonar.token=$ENV{SONARQUBE_TOKEN} + -Dsonar.qualitygate.wait=true + -Dsonar.qualitygate.timeout=90 + CHDIR ${T_BUILD_DIR} +) diff --git a/cmake/ci/Source.cmake b/cmake/ci/Source.cmake new file mode 100644 index 000000000..c25da4f19 --- /dev/null +++ b/cmake/ci/Source.cmake @@ -0,0 +1,7 @@ +step(${T_CFG} --preset ci-tools) +step(${T_TARGET} package_source) + +if(RELEASE) + file(GLOB TARBALL "${T_BUILD_DIR}/*.tar.gz") + step(gpg --batch --passphrase $ENV{GPG_PSW} --pinentry-mode loopback -a --detach-sig -u $ENV{GPG_ID} ${TARBALL}) +endif() diff --git a/cmake/ci/Win.cmake b/cmake/ci/Win.cmake new file mode 100644 index 000000000..83b5f596c --- /dev/null +++ b/cmake/ci/Win.cmake @@ -0,0 +1,37 @@ +if(NAME MATCHES "MSI") + set(PACKAGES ON) +endif() + +if(NAME MATCHES "GNU") + set(GNU ON) +elseif(NAME MATCHES "clang" AND DEFINED ENV{LLVM}) + set(PATH "$ENV{LLVM}") +endif() + +if(NOT GNU) + set(VCVARS cmd /c vcvarsall.bat amd64 && call) +endif() + +if(NAME MATCHES "_dev") + set(PRESET ci-win-debug) +elseif(PACKAGES) + set(PRESET ci-win-release) +else() + set(PRESET ci-win) +endif() + +step(${VCVARS} ${T_CFG} --preset ${PRESET} PATH "${PATH}") + +if(PACKAGES) + step(${VCVARS} ${T_TARGET} package) + step(${VCVARS} ${T_TARGET} package.sign) + if(NOT RELEASE) + step(${CMAKE_COMMAND} -DCMD=CHECK_WIX_WARNING -DFILE=${T_BUILD_DIR}/_CPack_Packages/win64/WIX/wix.log -P ${CMAKE_DIR}/cmd.cmake) + endif() +else() + step(${VCVARS} ${T_BUILD}) +endif() + +if(NOT RELEASE AND NOT PACKAGES) + step(${T_CTEST} ENV QT_PLUGIN_PATH=${WORKSPACE}/libs/dist/plugins QML2_IMPORT_PATH=${WORKSPACE}/libs/dist/qml PATH "${WORKSPACE}/libs/dist/bin") +endif() diff --git a/cmake/ci/iOS.cmake b/cmake/ci/iOS.cmake new file mode 100644 index 000000000..1fa4b0c29 --- /dev/null +++ b/cmake/ci/iOS.cmake @@ -0,0 +1,48 @@ +if(NAME MATCHES "IPA") + set(IPA ON) + set(TARGET ipa) + set(PRESET ci-ios) +elseif(NAME MATCHES "Framework") + set(TARGET zip) + + if(NAME MATCHES "Simulator_arm64_Framework") + set(PRESET ci-ios-framework-simulator-arm64) + elseif(NAME MATCHES "Simulator_Framework") + set(PRESET ci-ios-framework-simulator) + else() + set(PRESET ci-ios-framework) + endif() +elseif(NAME MATCHES "SwiftPackage") + step(${CMAKE_COMMAND} -DDIST_DIR=${T_DIST_DIR} -P ${CMAKE_DIR}/SwiftPackage.cmake) + return() +endif() + +step(security unlock-keychain $ENV{KEYCHAIN_CREDENTIALS} $ENV{HOME}/Library/Keychains/login.keychain-db) + +step(${T_CFG} --preset ${PRESET}) + +if(IPA AND NOT REVIEW) + step(xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -scheme AusweisAppBinary archive CHDIR ${T_BUILD_DIR}) + step(xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -exportArchive -exportOptionsPlist exportOptions.plist -exportPath . CHDIR ${T_BUILD_DIR}) +else() + step(xcodebuild -configuration MinSizeRel CHDIR ${T_BUILD_DIR}) +endif() + +if(RELEASE) + step(${CMAKE_COMMAND} -E tar cf AusweisApp_BuildDir.tar.zstd --zstd build) +endif() + +step(xcodebuild -configuration MinSizeRel -target ${TARGET} CHDIR ${T_BUILD_DIR}) + +if(IPA AND NOT RELEASE) + step(${T_CTEST} -C MinSizeRel) +endif() + +if(IPA AND RELEASE AND DEFINED ENV{USE_DISTRIBUTION_PROFILE}) + if($ENV{USE_DISTRIBUTION_PROFILE}) + set(USER "ausweisapp@governikus.com") + file(GLOB ipafile "${T_BUILD_DIR}/*.ipa") + step(xcrun altool -t ios --validate-app --verbose -u "${USER}" -p @env:PASSWORD -f ${ipafile}) + step(xcrun altool -t ios --upload-app -u "${USER}" -p @env:PASSWORD -f ${ipafile}) + endif() +endif() diff --git a/cmake/cmd.cmake b/cmake/cmd.cmake index d9fb3e648..5b87d3510 100644 --- a/cmake/cmd.cmake +++ b/cmake/cmd.cmake @@ -1,15 +1,11 @@ -cmake_minimum_required(VERSION 3.13.0) -cmake_policy(SET CMP0057 NEW) +cmake_minimum_required(VERSION 3.19) ########################################### #### Usage: cmake -DCMD= -P cmake/cmd.cmake ########################################### function(EXECUTE) - execute_process(COMMAND ${ARGV} RESULT_VARIABLE _result) - if(NOT ${_result} EQUAL 0) - message(FATAL_ERROR "Process failed: ${_result}") - endif() + execute_process(COMMAND ${ARGV} COMMAND_ECHO STDOUT COMMAND_ERROR_IS_FATAL ANY) endfunction(EXECUTE) function(MESSAGE type) @@ -21,7 +17,7 @@ function(MESSAGE type) endfunction() -function(CREATE_HASH) +function(HASH) if(NOT FILES) message(FATAL_ERROR "You need to specify 'FILES'") endif() @@ -85,33 +81,26 @@ function(CHECK_WIX_WARNING) endfunction() -function(IMPORT_PATCH) - message(STATUS "Import patch...") - find_package(Python REQUIRED) - EXECUTE(${Python_EXECUTABLE} "${CMAKE_BINARY_DIR}/resources/jenkins/import.py") -endfunction() - - function(DEPLOY_NEXUS) - if(NOT DEFINED ENV{NEXUS_USERNAME} OR NOT DEFINED ENV{NEXUS_PSW}) - message(FATAL_ERROR "Please provide environment variable NEXUS_USERNAME and NEXUS_PSW") - endif() - - set(GNUPG_KEY 699BF3055B0A49224EFDE7C72D7479A531451088) - if(DEFINED ENV${GNUPG_KEY}) - set(GNUPG_KEY ENV${GNUPG_KEY}) - endif() - find_program(MVN_BIN mvn) if(NOT MVN_BIN) message(FATAL_ERROR "Cannot find mvn") endif() - set(SETTINGS_XML " - nexus - \${env.NEXUS_USERNAME} - \${env.NEXUS_PSW} - ") + set(SETTINGS_XML " + + + nexus + \${env.NEXUS_USERNAME} + \${env.NEXUS_PSW} + + + central + \${env.CENTRAL_USERNAME} + \${env.CENTRAL_PSW} + + + ") file(WRITE settings.xml "${SETTINGS_XML}") function(get_file _suffix _out_var) @@ -121,7 +110,7 @@ function(DEPLOY_NEXUS) if(list_length GREATER 1) message(FATAL_ERROR "Found more than one entry: ${file}") elseif(asc_length EQUAL 0) - message(FATAL_ERROR "File ${file} not found. Maybe signature is missing?: gpg -a -u ${GNUPG_KEY} --detach-sig") + message(FATAL_ERROR "File ${file} not found. Maybe signature is missing?") endif() set(${_out_var} ${file} PARENT_SCOPE) @@ -135,22 +124,22 @@ function(DEPLOY_NEXUS) if(is_snapshot) set(NEXUS_URL https://repo.govkg.de/repository/ausweisapp-snapshots) else() - if(PUBLIC) - set(NEXUS_URL https://s01.oss.sonatype.org/service/local/staging/deploy/maven2) - else() - set(NEXUS_URL https://repo.govkg.de/repository/ausweisapp-releases) - endif() + set(NEXUS_URL https://repo.govkg.de/repository/ausweisapp-releases) endif() - EXECUTE(${MVN_BIN} deploy:deploy-file -Dfile=${FILE_AAR} -DpomFile=${FILE_POM} -Dsources=${FILE_JAR} -DrepositoryId=nexus -Durl=${NEXUS_URL} --settings settings.xml) + set(MVN_CMD ${MVN_BIN} deploy:3.1.3:deploy-file -Dfile=${FILE_AAR} -DpomFile=${FILE_POM} -Dsources=${FILE_JAR} --settings settings.xml) + EXECUTE(${MVN_CMD} -DrepositoryId=nexus -Durl=${NEXUS_URL}) + + if(PUBLISH AND NOT is_snapshot) + set(CENTRAL_PARAMS -DrepositoryId=central -Durl=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2) + EXECUTE(${MVN_CMD} ${CENTRAL_PARAMS}) - if(PUBLIC) get_file("*.aar.asc" FILE_AAR_ASC) get_file("*.pom.asc" FILE_POM_ASC) get_file("*-sources.jar.asc" FILE_SOURCES_ASC) function(mvn_upload _file _packaging _classifier) - EXECUTE(${MVN_BIN} deploy:deploy-file -Dfile=${_file} -Dpackaging=${_packaging} -Dclassifier=${_classifier} -DpomFile=${FILE_POM} -DrepositoryId=nexus -Durl=${NEXUS_URL} --settings settings.xml) + EXECUTE(${MVN_BIN} deploy:3.1.3:deploy-file -Dfile=${_file} -Dpackaging=${_packaging} -Dclassifier=${_classifier} -DpomFile=${FILE_POM} ${CENTRAL_PARAMS} --settings settings.xml) endfunction() mvn_upload("${FILE_AAR_ASC}" "aar.asc" "") @@ -221,20 +210,107 @@ function(CHECK_FAILURE_CODES) endforeach() endfunction() +function(CHECK_QMLDIR) + file(GLOB_RECURSE QMLDIRS "${CMAKE_CURRENT_BINARY_DIR}/qmldir") + + if(QMLDIRS STREQUAL "") + message(FATAL_ERROR "no qmldirs found: ${CMAKE_CURRENT_BINARY_DIR}") + endif() + + foreach(file ${QMLDIRS}) + get_filename_component(dir "${file}" DIRECTORY) + file(GLOB_RECURSE QMLFILES RELATIVE "${dir}" "${dir}/*.qml") + set(flatten_qmlfiles) + foreach(entry ${QMLFILES}) + get_filename_component(name "${entry}" NAME) + list(APPEND flatten_qmlfiles ${name}) + endforeach() + + file(STRINGS "${file}" content) + # check if qmldir has invalid files + foreach(line ${content}) + string(REGEX MATCH "[A-Za-z]+\\.qml$" _unused "${line}") + if(CMAKE_MATCH_0) + list(FIND flatten_qmlfiles ${CMAKE_MATCH_0} found) + if(found EQUAL -1) + string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" subdir "${file}") + message(STATUS "${CMAKE_MATCH_0} not found in ${subdir}") + set(failed TRUE) + endif() + endif() + endforeach() + + # check if qmldir has missing files + foreach(qmlfile ${flatten_qmlfiles}) + string(REGEX MATCH "([A-Za-z]+)_[0-9\\.]+\\.qml" _unused "${qmlfile}") + if(CMAKE_MATCH_1) + set(qmlfile "${CMAKE_MATCH_1}.qml") + endif() + file(STRINGS "${file}" content REGEX " ${qmlfile}") + if(content STREQUAL "") + string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" qmldir "${file}") + message(STATUS "${qmlfile} not found in ${qmldir}") + set(failed TRUE) + endif() + endforeach() + endforeach() + + if(failed) + message(FATAL_ERROR "qmldir seems invalid") + endif() +endfunction() + +function(CHECK_QMLTYPES) + file(GLOB_RECURSE QMLTYPES "${CMAKE_CURRENT_BINARY_DIR}/*.qmltypes") + + if(QMLTYPES STREQUAL "") + message(FATAL_ERROR "no qmltypes found: ${CMAKE_CURRENT_BINARY_DIR}") + endif() + + set(failed FALSE) + foreach(file ${QMLTYPES}) + file(STRINGS "${file}" filecontent) + set(PARENT_NAME "") + set(ENUM_FOUND FALSE) + set(ENUM_NAME "") + set(ENUM_SCOPED FALSE) + + foreach(line ${filecontent}) + if(ENUM_FOUND) + if(line MATCHES "}") + if(NOT ENUM_SCOPED AND NOT PARENT_NAME MATCHES "governikus::Enum${ENUM_NAME}") + get_filename_component(file "${file}" NAME) + message(STATUS "${file}: ${ENUM_NAME} of ${PARENT_NAME} is not scoped") + set(failed TRUE) + endif() + set(ENUM_FOUND FALSE) + set(ENUM_NAME "") + set(ENUM_SCOPED FALSE) + elseif(line MATCHES "name: \"([A-Za-z]+)\"") + set(ENUM_NAME ${CMAKE_MATCH_1}) + elseif(line MATCHES "isScoped: true") + set(ENUM_SCOPED TRUE) + endif() + elseif(line MATCHES "Enum {") + set(ENUM_FOUND TRUE) + elseif(line MATCHES "name: \"([A-Za-z:]+)\"") + set(PARENT_NAME ${CMAKE_MATCH_1}) + endif() + endforeach() + endforeach() + + if(failed) + message(FATAL_ERROR "Enum in qmltypes is not scoped") + endif() +endfunction() + + if(NOT CMD) message(FATAL_ERROR "You need to specify 'CMD'") endif() -if(CMD STREQUAL "HASH") - CREATE_HASH() -elseif(CMD STREQUAL "CHECK_WIX_WARNING") - CHECK_WIX_WARNING() -elseif(CMD STREQUAL "IMPORT_PATCH") - IMPORT_PATCH() -elseif(CMD STREQUAL "DEPLOY_NEXUS") - DEPLOY_NEXUS() -elseif(CMD STREQUAL "CHECK_FAILURE_CODES") - CHECK_FAILURE_CODES() +if(COMMAND "${CMD}") + cmake_language(CALL ${CMD}) else() message(FATAL_ERROR "Unknown CMD: ${CMD}") endif() diff --git a/cmake/iOS.toolchain.cmake b/cmake/iOS.toolchain.cmake index 86d66b092..6f80bd816 100644 --- a/cmake/iOS.toolchain.cmake +++ b/cmake/iOS.toolchain.cmake @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.14) - set(CMAKE_SYSTEM_NAME iOS) if(NOT CMAKE_OSX_ARCHITECTURES) diff --git a/cmake/mingw.toolchain.cmake b/cmake/mingw.toolchain.cmake index e55dbe334..f47e21196 100644 --- a/cmake/mingw.toolchain.cmake +++ b/cmake/mingw.toolchain.cmake @@ -1,7 +1,7 @@ # This toolchain is not officially supported! -# It's just a helper to cross-compile the libraries and AusweisApp2 on Linux for Windows. +# It's just a helper to cross-compile the libraries and AusweisApp on Linux for Windows. -# You need to adjust your PATH variable to let AusweisApp2.exe find all necessary DLLs. +# You need to adjust your PATH variable to let AusweisApp.exe find all necessary DLLs. # Another approach is to copy all DLLs. # $ cp /usr/i686-w64-mingw32/bin/*.dll . # $ cp ~/libs/dist/bin/*.dll . diff --git a/cmake/prepare_sonarqube_env.cmake b/cmake/prepare_sonarqube_env.cmake index 5ce9404d0..e7d7bc70b 100644 --- a/cmake/prepare_sonarqube_env.cmake +++ b/cmake/prepare_sonarqube_env.cmake @@ -13,20 +13,20 @@ message(STATUS "Use PACKAGES_DIR: ${PACKAGES_DIR}") set(BUILDWRAPPER_ZIP_NAME build-wrapper-linux-x86.zip) set(BUILDWRAPPER_URL https://sonar.govkg.de/static/cpp/${BUILDWRAPPER_ZIP_NAME}) -set(SONARSCANNERCLI_VERSION 5.0.1.3006-linux) # https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/ +set(SONARSCANNERCLI_VERSION 6.1.0.4477-linux-x64) # https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ set(SONARSCANNERCLI_ZIP_NAME sonar-scanner-cli-${SONARSCANNERCLI_VERSION}.zip) set(SONARSCANNERCLI_URL https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/${SONARSCANNERCLI_ZIP_NAME}) -set(SONARSCANNERCLI_HASH 350dbdb517c10fcb3ce70425db95c415b313cad7296c407d416d88f3d50121f8) +set(SONARSCANNERCLI_HASH aa985eacaa4155a064647370b62fc82d1b0e06caf1d493e04c2389dd5ac74fcb) -set(DEPENDENCYCHECK_VERSION 8.4.0) # https://github.com/jeremylong/DependencyCheck/releases +set(DEPENDENCYCHECK_VERSION 10.0.3) # https://github.com/jeremylong/DependencyCheck/releases set(DEPENDENCYCHECK_ZIP_NAME dependency-check-${DEPENDENCYCHECK_VERSION}-release.zip) set(DEPENDENCYCHECK_URL https://github.com/jeremylong/DependencyCheck/releases/download/v${DEPENDENCYCHECK_VERSION}/${DEPENDENCYCHECK_ZIP_NAME}) -set(DEPENDENCYCHECK_HASH 937a6bf8ced9d8494767082c1f588f26ea379324cb089dabb045321e8b0ab01a) +set(DEPENDENCYCHECK_HASH 5263fbafb15010823364274b83e9a2219b654d00a557d92941c37736d4076ba4) -set(MARIADB_CONNECTOR_VERSION 3.2.0) +set(MARIADB_CONNECTOR_VERSION 3.4.1) set(MARIADB_CONNECTOR_ZIP_NAME mariadb-java-client-${MARIADB_CONNECTOR_VERSION}.jar) set(MARIADB_CONNECTOR_URL https://downloads.mariadb.com/Connectors/java/connector-java-${MARIADB_CONNECTOR_VERSION}/${MARIADB_CONNECTOR_ZIP_NAME}) -set(MARIADB_CONNECTOR_HASH adf9df10bc9b2a137def36d6a495812258f430d4a8f7946727c61558e6c73941) +set(MARIADB_CONNECTOR_HASH f60e4b282f1f4bdb74f0a26436ba7078a5e480b6f6702f6a7b45d9ba5e604a24) set(SONARQUBETOOLS_DIR ${CMAKE_BINARY_DIR}/sonarqubetools) diff --git a/cmake/tests/openssl.cpp b/cmake/tests/openssl.cpp index 78d90ffa2..54b4b5c3a 100644 --- a/cmake/tests/openssl.cpp +++ b/cmake/tests/openssl.cpp @@ -1,7 +1,8 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ +#include #include #include @@ -25,8 +26,11 @@ #error RSA-PSK is required. #endif -int main() +int main(int argc, char** argv) { + QCoreApplication app(argc, argv); + Q_UNUSED(app) + // It is required that Qt and AusweisApp uses the library and the same version. // Also this binary will crash if your libraries aren't binary compatible. For example // this occurs if you link Qt against OpenSSL and the AusweisApp against LibreSSL. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index c9b41e12c..e33692bdd 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,7 +1,7 @@ if(SPHINX_FOUND) SPHINX_GEN("${CMAKE_CURRENT_SOURCE_DIR}/releasenotes" "notes" BUILDER singlehtml html latex text) - SPHINX_GEN("${CMAKE_CURRENT_SOURCE_DIR}/sdk" "sdk" BUILDER changes html latex DEFAULT_LANG en) + SPHINX_GEN("${CMAKE_CURRENT_SOURCE_DIR}/sdk" "sdk" BUILDER html latex DEFAULT_LANG en) SPHINX_GEN("${CMAKE_CURRENT_SOURCE_DIR}/installation" "installation_integration" BUILDER changes html latex) diff --git a/docs/failurecodes/conf.py.in b/docs/failurecodes/conf.py.in index cf14817dd..407d19f9f 100644 --- a/docs/failurecodes/conf.py.in +++ b/docs/failurecodes/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = '@PROJECT_NAME@ Failure Codes' -copyright = '2023, Governikus GmbH & Co. KG' +copyright = '2023-2024, Governikus GmbH & Co. KG' author = 'Governikus GmbH & Co. KG' # The version info for the project you're documenting, acts as replacement for @@ -169,4 +169,4 @@ latex_show_urls = 'footnote' rst_epilog = """ .. |AppName| replace:: @PROJECT_NAME@ -""" \ No newline at end of file +""" diff --git a/docs/failurecodes/failurecodes.rst b/docs/failurecodes/failurecodes.rst index 01d68899a..5c5eeec06 100644 --- a/docs/failurecodes/failurecodes.rst +++ b/docs/failurecodes/failurecodes.rst @@ -231,6 +231,11 @@ Codes a new PIN at the citizens' office (Bürgeramt) or let it be set with the CAN at https://www.pin-ruecksetzbrief-bestellen.de. + - | **Establish_Pace_Channel_Unknown_Password_Id** + | The establishment of a PACE channel was finished. However, an unsupported + password type was used (PIN, CAN, PUK are supported). + | **Possible Solutions:** :ref:`failure_code_contact_support`. + - | **Establish_Pace_Channel_User_Cancelled** | The user canceled the workflow on a comfort USB reader or a smartphone as a card reader with keyboard mode enabled. @@ -483,6 +488,11 @@ Codes | Like Change_Pin_User_Cancelled but at a higher log level. | **Possible Solutions:** Carry out the PIN change without abortion. + - | **Change_Pin_Unrecoverable** + | The change PIN workflow encountered an error, which prevents the continuation of the workflow. + This often indicates a problem with the card connection. + | **Possible Solutions:** :ref:`failure_code_card_position`. + - | **Start_Ifd_Service_Failed** | The IFD service according to TR-03112-6 appendix "IFD Service" could not be started. Either no suitable TLS certificate could be found/generated or the start of the TLS server failed. This diff --git a/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po b/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po index 4f0782622..571f71034 100644 --- a/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po +++ b/docs/failurecodes/locales/de/LC_MESSAGES/failurecodes.po @@ -1,15 +1,14 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) 2023, Governikus GmbH & Co. KG -# This file is distributed under the same license as the AusweisApp2 Failure -# Codes package. -# FIRST AUTHOR , 2023. +# Copyright (C) 2023-2024, Governikus GmbH & Co. KG +# This file is distributed under the same license as the AusweisApp +# Failure Codes package. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: AusweisApp2 Failure Codes 1.26.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-31 05:28+0200\n" +"POT-Creation-Date: 2024-04-09 07:58+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -18,7 +17,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.12.1\n" +"Generated-By: Babel 2.14.0\n" msgid "Failure Codes" msgstr "Fehlercodes" @@ -107,8 +106,8 @@ msgid "" "configuration as well as your local network hardware. Ultimately the " "problem may be with your telecommunications provider, or the service " "provider. Please refer to the attached \\\"Network_Error\\\" for details." -" If you are using the |AppName|, the diagnosis, which is located in the" -" help section, may assist you in finding issues." +" If you are using the |AppName|, the diagnosis, which is located in the " +"help section, may assist you in finding issues." msgstr "" "Bei sämtlichen Fehlercodes, welche Verbindungsprobleme als Ursache " "aufzeigen, empfiehlt sich vorab eine Überprüfung der aktuellen " @@ -374,11 +373,11 @@ msgid "**Pre_Verification_No_Test_Environment**" msgstr "" msgid "" -"Occurs when the development mode of |AppName| is activated and a " -"genuine ID card is used." +"Occurs when the development mode of |AppName| is activated and a genuine " +"ID card is used." msgstr "" -"Tritt auf, wenn der Entwicklermodus der |AppName| aktiviert ist und ein" -" Echtausweis verwendet wird." +"Tritt auf, wenn der Entwicklermodus der |AppName| aktiviert ist und ein " +"Echtausweis verwendet wird." msgid "" "**Possible Solutions:** Disable developer mode. The use of genuine ID " @@ -393,12 +392,10 @@ msgstr "" msgid "**Pre_Verification_Invalid_Certificate_Chain**" msgstr "" -msgid "" -"A certificate chain was sent from the server that is unknown to " -"|AppName|." +msgid "A certificate chain was sent from the server that is unknown to |AppName|." msgstr "" -"Vom Server wurde eine Zertifikatskette gesendet, die der |AppName| " -"nicht bekannt ist." +"Vom Server wurde eine Zertifikatskette gesendet, die der |AppName| nicht " +"bekannt ist." msgid "**Pre_Verification_Invalid_Certificate_Signature**" msgstr "" @@ -521,15 +518,6 @@ msgstr "" "Fehlversuchen nicht freigeschaltet werden. Bitte richten Sie Ihre Smart-" "eID erneut ein." -msgid "" -"**Possible Solutions:** The |AppName| automatically leads the user to " -"the PIN change to set a six-digit PIN. If this error occurs in a third-" -"party app, you have to start a PIN change on your own." -msgstr "" -"**Mögliche Lösungen:** Die |AppName| führt den Benutzer direkt zur PIN-" -"Änderung, damit dieser eine sechsstellige PIN festlegen kann. Tritt der " -"Fall im SDK auf, muss sich die Anwendung selbst darum kümmern." - msgid "**Establish_Pace_Channel_Basic_Reader_No_Pin**" msgstr "" @@ -542,9 +530,6 @@ msgstr "" "aufzubauen. Jedoch wurde die PIN, CAN oder PUK nach der Nutzereingabe " "nicht übernommen." -msgid "**Possible Solutions:** :ref:`failure_code_contact_support`." -msgstr "**Mögliche Lösungen:** :ref:`failure_code_contact_support`." - msgid "**Establish_Pace_Channel_Puk_Inoperative**" msgstr "" @@ -570,6 +555,16 @@ msgstr "" "neue PIN setzen oder auf https://www.pin-ruecksetzbrief-bestellen.de mit " "der CAN setzen lassen." +msgid "**Establish_Pace_Channel_Unknown_Password_Id**" +msgstr "" + +msgid "" +"The establishment of a PACE channel was finished. However, an unsupported" +" password type was used (PIN, CAN, PUK are supported)." +msgstr "" +"Der Aufbau eines PACE-Kanals wurde abgeschlossen. Dabei wurde jedoch ein " +"nicht unterstützter Passworttyp angefragt (Unterstützt werden PIN, CAN, PUK)." + msgid "**Establish_Pace_Channel_User_Cancelled**" msgstr "" @@ -673,8 +668,8 @@ msgid "" "The server intended for the PAOS communication during authentication is " "temporarily unavailable." msgstr "" -"Der für PAOS-Kommunikation vorgesehene Server ist temporär " -"nicht verfügbar." +"Der für PAOS-Kommunikation vorgesehene Server ist temporär nicht " +"verfügbar." msgid "**Generic_Send_Receive_Server_Error**" msgstr "" @@ -774,8 +769,8 @@ msgid "" "|AppName| or the ID card did not behave as expected by the server." msgstr "" "Die Nachricht \"StartPaosResponse\" vom Server hat einen Fehler " -"geliefert. Die |AppName| oder die Karte hat sich nicht entsprechend der" -" Erwartung des Servers verhalten." +"geliefert. Die |AppName| oder die Karte hat sich nicht entsprechend der " +"Erwartung des Servers verhalten." msgid "**Check_Refresh_Address_Fatal_Tls_Error_Before_Reply**" msgstr "" @@ -804,22 +799,24 @@ msgstr "" msgid "The server providing the return address is temporarily unavailable." msgstr "" -"Der für das Bereitstellen der Rücksprungadresse vorgesehene Server ist temporär " -"nicht verfügbar." +"Der für das Bereitstellen der Rücksprungadresse vorgesehene Server ist " +"temporär nicht verfügbar." msgid "**Check_Refresh_Address_Server_Error**" msgstr "" msgid "A server error 5xx occurred on requesting the return address." msgstr "" -"Bei der Anfrage der Rücksprungadresse ist ein Serverfehler 5xx aufgetreten." +"Bei der Anfrage der Rücksprungadresse ist ein Serverfehler 5xx " +"aufgetreten." msgid "**Check_Refresh_Address_Client_Error**" msgstr "" msgid "A client error 4xx occurred on requesting the return address." msgstr "" -"Bei der Anfrage der Rücksprungadresse ist ein Clientfehler 4xx aufgetreten." +"Bei der Anfrage der Rücksprungadresse ist ein Clientfehler 4xx " +"aufgetreten." msgid "**Check_Refresh_Address_Service_Timeout**" msgstr "" @@ -838,8 +835,8 @@ msgid "" "A proxy server was configured by the operating system or the settings of " "|AppName|. This didn't work for checking the return address." msgstr "" -"Durch das Betriebssystem oder die Einstellungen der |AppName| wurde ein" -" Proxyserver konfiguriert. Dieser hat für die Überprüfung der " +"Durch das Betriebssystem oder die Einstellungen der |AppName| wurde ein " +"Proxyserver konfiguriert. Dieser hat für die Überprüfung der " "Rücksprungadresse nicht funktioniert." msgid "**Check_Refresh_Address_Fatal_Tls_Error_After_Reply**" @@ -927,6 +924,19 @@ msgstr "" "Das Server-Zertifikat der Rücksprungadresse ist nicht in der Beschreibung" " des Diensteanbieterzertifikats enthalten." +msgid "**Browser_Send_Failed**" +msgstr "" + +msgid "" +"On desktop systems, the web browser waits for a response from |AppName| " +"after starting authentication. However, for unknown reasons, the web " +"browser connection to the browser is lost and the answer cannot be sent." +msgstr "" +"Auf Desktop-Systemen wartet der Webbrowser nach Start einer " +"Authentisierung auf eine Antwort der |AppName|. Aus unbekannten Gründen " +"ist die Verbindung zum Browser abgebrochen, sodass die Antwort nicht mehr" +" gesendet werden kann." + msgid "" "**Possible Solutions:** If the problem occurs repeatedly and changing the" " browser does not help, please :ref:`failure_code_contact_support`." @@ -935,18 +945,6 @@ msgstr "" "Problem bestehen bleibt, beachten Sie " ":ref:`failure_code_contact_support`." -msgid "**Browser_Send_Failed**" -msgstr "" - -msgid "" -"On desktop systems, the web browser waits for a response from |AppName| " -"after starting authentication. However, for unknown reasons, the web browser " -"connection to the browser is lost and the answer cannot be sent." -msgstr "" -"Auf Desktop-Systemen wartet der Webbrowser nach Start einer Authentisierung " -"auf eine Antwort der |AppName|. Aus unbekannten Gründen ist die Verbindung " -"zum Browser abgebrochen, sodass die Antwort nicht mehr gesendet werden kann." - msgid "**Generic_Provider_Communication_Network_Error**" msgstr "" @@ -969,8 +967,8 @@ msgid "" msgstr "" "Bei der Kommunikation mit einem Diensteanbieter ist der durch den TLS-" "Handshake generierte symmetrische Schlüssel nicht lang genug. Das " -"betrifft nur Dienste, die aus der |AppName| heraus gestartet werden, " -"wie zum Beispiel die Selbstauskunft." +"betrifft nur Dienste, die aus der |AppName| heraus gestartet werden, wie " +"zum Beispiel die Selbstauskunft." msgid "**Generic_Provider_Communication_Certificate_Error**" msgstr "" @@ -995,15 +993,14 @@ msgid "" msgstr "" "Bei der Kommunikation mit einem Diensteanbieter ist während des TLS-" "Handshakes ein Fehler aufgetreten. Das TLS-Zertifikat ist fehlerhaft. Das" -" betrifft nur Dienste, die aus der |AppName| heraus gestartet werden, " -"wie zum Beispiel die Selbstauskunft." +" betrifft nur Dienste, die aus der |AppName| heraus gestartet werden, wie" +" zum Beispiel die Selbstauskunft." msgid "**Generic_Provider_Communication_ServiceUnavailable**" msgstr "" msgid "The server of the service provider is temporarily unavailable." -msgstr "" -"Der Server des Diensteanbieters ist temporär nicht verfügbar." +msgstr "Der Server des Diensteanbieters ist temporär nicht verfügbar." msgid "**Generic_Provider_Communication_Server_Error**" msgstr "" @@ -1012,7 +1009,8 @@ msgid "" "A server error 5xx occurred in the communication with the service " "provider." msgstr "" -"Bei der Kommunikation mit dem Diensteanbieter ist ein Serverfehler 5xx aufgetreten." +"Bei der Kommunikation mit dem Diensteanbieter ist ein Serverfehler 5xx " +"aufgetreten." msgid "**Generic_Provider_Communication_Client_Error**" msgstr "" @@ -1021,7 +1019,8 @@ msgid "" "A client error 4xx occurred in the communication with the service " "provider." msgstr "" -"Bei der Kommunikation mit dem Diensteanbieter ist ein Clientfehler 4xx aufgetreten." +"Bei der Kommunikation mit dem Diensteanbieter ist ein Clientfehler 4xx " +"aufgetreten." msgid "**Get_SelfAuthData_Invalid_Or_Empty**" msgstr "" @@ -1130,6 +1129,18 @@ msgstr "" msgid "Like Change_Pin_User_Cancelled but at a higher log level." msgstr "Wie Change_Pin_User_Cancelled aber auf einer höheren Protokollebene." +msgid "**Change_Pin_Unrecoverable**" +msgstr "" + +msgid "" +"The change PIN workflow encountered an error, which prevents the " +"continuation of the workflow. This often indicates a problem with the " +"card connection." +msgstr "" +"Bei der PIN-Änderung ist es zu einer Fehlersituation gekommen, die " +"keine Fortsetzung ermöglicht. Das ist oft ein Zeichen für Probleme " +"mit der Kartenverbindung." + msgid "**Start_Ifd_Service_Failed**" msgstr "" @@ -1137,8 +1148,8 @@ msgid "" "The IFD service according to TR-03112-6 appendix \"IFD Service\" could " "not be started. Either no suitable TLS certificate could be " "found/generated or the start of the TLS server failed. This applies to " -"both remote access and the local service of |AppName| on Android that " -"is used through the SDK." +"both remote access and the local service of |AppName| on Android that is " +"used through the SDK." msgstr "" "Der IFD-Service gemäß TR-03112-6 Anhang „IFD Service“ konnte nicht " "gestartet werden. Entweder konnte kein passendes TLS-Zertifikat " diff --git a/docs/installation/README.de.rst b/docs/installation/README.de.rst index 78d2c3118..195bddc6d 100644 --- a/docs/installation/README.de.rst +++ b/docs/installation/README.de.rst @@ -1,5 +1,7 @@ -Deutsch -======= +.. raw:: latex + + \part*{Deutsch} + \addcontentsline{toc}{part}{Deutsch} Installation ~~~~~~~~~~~~ @@ -44,10 +46,12 @@ PROXYSERVICE AUTOSTART Durch Angabe von AUTOSTART=true wird ein Autostart-Eintrag für alle Benutzer - erstellt. Die Deaktivierung des Autostarts ist den Benutzern in der |AppName| + erstellt und beim Schließen per Klick auf das X wird die |AppName| in den + Infobereich minimiert. + Die Deaktivierung des Autostarts ist den Benutzern in der |AppName| dadurch nicht möglich. Ohne Angabe wird der Autostart-Eintrag nicht erstellt - (false). In diesem Fall ist es jedoch jedem Benutzer möglich, die Autostart- - Funktion innerhalb der |AppName| für sich zu aktivieren. + (false). In diesem Fall ist es jedoch jedem Benutzer möglich, die + Autostart-Funktion innerhalb der |AppName| für sich zu aktivieren. AUTOHIDE Betrifft die automatische Minimierung nach Abschluss einer erfolgreichen @@ -56,8 +60,10 @@ AUTOHIDE REMINDTOCLOSE Wenn der Benutzer die |AppName| per Klick auf das X schließt, wird er darauf - hingewiesen, dass nur die Benutzeroberfläche geschlossen wird und die - |AppName| weiterhin im Infobereich zur Verfügung steht. Zu diesem Zeitpunkt + hingewiesen, dass nur die Benutzeroberfläche geschlossen wird und die |AppName| + weiterhin im Infobereich zur Verfügung steht (falls der Autostart der |AppName| + aktiviert ist) bzw. dass die |AppName| geschlossen wird und erneut geöffnet + werden muss um sich gegenüber Diensteanbietern auszuweisen. Zu diesem Zeitpunkt ist es möglich, den Hinweis zukünftig zu unterdrücken. Durch REMINDTOCLOSE=false kann dieser Hinweis von vornherein deaktiviert werden. Ohne Angabe ist er aktiviert (true). @@ -106,11 +112,6 @@ UPDATECHECK Aktualisierung der Anbieterliste noch die Aktualisierung der Kartenleserinformationen. -ONSCREENKEYBOARD - Für die Eingabe von PIN, CAN und PUK kann eine Bildschirmtastatur verwendet - werden. Durch Setzen von ONSCREENKEYBOARD auf false oder true kann diese - deaktiviert bzw. aktiviert werden. Der Benutzer kann diese Einstellung anpassen. - SHUFFLESCREENKEYBOARD Ist die Bildschirmtastatur aktiviert, können die Zifferntasten zufällig angeordnet werden. Durch Setzen von SHUFFLESCREENKEYBOARD auf false oder true kann die zufällige Anordnung @@ -179,8 +180,6 @@ dargestellt: proxy.example.org customProxyPort 1337 - keylessPassword - shuffleScreenKeyboard visualPrivacy @@ -196,22 +195,21 @@ Für die einzelnen Werte gelten die gleichen Beschreibungen wie für die Windows-Version wobei die Bennennung der Attribute der folgenden Tabelle zu entnehmen ist. -======================= ======================= -macOS Windows -======================= ======================= -autoCloseWindow AUTOHIDE -remindToClose REMINDTOCLOSE -uiStartupModule ASSISTANT -transportPinReminder TRANSPORTPINREMINDER -customProxyType CUSTOMPROXYTYPE -customProxyPort CUSTOMPROXYPORT -customProxyHost CUSTOMPROXYHOST -keylessPassword ONSCREENKEYBOARD -shuffleScreenKeyboard SHUFFLESCREENKEYBOARD -visualPrivacy SECURESCREENKEYBOARD -enableCanAllowed ENABLECANALLOWED -skipRightsOnCanAllowed SKIPRIGHTSONCANALLOWED -======================= ======================= +======================== ======================= +macOS Windows +======================== ======================= +autoCloseWindow AUTOHIDE +remindToClose [#dialog]_ REMINDTOCLOSE +uiStartupModule ASSISTANT +transportPinReminder TRANSPORTPINREMINDER +customProxyType CUSTOMPROXYTYPE +customProxyPort CUSTOMPROXYPORT +customProxyHost CUSTOMPROXYHOST +shuffleScreenKeyboard SHUFFLESCREENKEYBOARD +visualPrivacy SECURESCREENKEYBOARD +enableCanAllowed ENABLECANALLOWED +skipRightsOnCanAllowed SKIPRIGHTSONCANALLOWED +======================== ======================= Nach Änderung der Datei kann es notwending sein, ein erneutes Laden der vom Betriebssystem gecachten Daten zu erzwingen: :code:`killall -u $USER cfprefsd` @@ -219,7 +217,7 @@ Betriebssystem gecachten Daten zu erzwingen: :code:`killall -u $USER cfprefsd` .. [#msiexecreturnvalues] https://docs.microsoft.com/de-de/windows/desktop/msi/error-codes .. [#standardarguments] https://docs.microsoft.com/de-de/windows/desktop/msi/standard-installer-command-line-options .. [#orca] https://docs.microsoft.com/de-de/windows/desktop/Msi/orca-exe - +.. [#dialog] Unter macOS wird die |AppName| in die Menüleiste minimiert. Anforderungen an die Einsatzumgebung @@ -316,7 +314,7 @@ CA-Zertifikate im Windows-Truststore werden daher ignoriert. Diensteanbieter können durch Weiterleitungen beliebige andere Ports zum Einsatz kommen. .. [#TR-03112] Siehe TR-03112-6 des BSI -.. [#govurl] Erreichbar unter dem URL https://appl.governikus-asp.de/ausweisapp2/ +.. [#govurl] Erreichbar unter dem URL https://updates.autentapp.de/ .. [#updatecheck] Die Überprüfung auf neue |AppName|-Versionen kann deaktiviert werden, siehe Kommandozeilenparameter UPDATECHECK @@ -336,32 +334,29 @@ CA-Zertifikate im Windows-Truststore werden daher ignoriert. Entwickleroptionen ~~~~~~~~~~~~~~~~~~ -Die |AppName| verfügt über sogenannte Entwickleroptionen. Diese sind -für die unterstützten Betriebssystem Windows und macOS verfügbar. Sie -unterstützen die Integration eines eID-Dienstes. - - -Windows & macOS ---------------- - -Das Aktivieren der Entwickleroptionen erfolgt sowohl für Windows als auch -für macOS über 10 Klicks auf die Versionsnummer im Bereich "Hilfe" -> -"Versionsinformationen". Nach der Aktivierung sind die Entwickleroptionen -über den Bereich "Einstellungen" erreichbar. - +Die |AppName| verfügt über sogenannte Entwickleroptionen. Diese bieten erweiterte +Einstellmöglichkeiten und unterstützen die Integration eines eID-Dienstes. +Die Entwickleroptionen werden standardmäßig ausgeblendet. -Android & iOS -------------- +Aktivieren der Entwickleroptionen +--------------------------------- -In den mobilen Versionen der |AppName| ist der Entwicklermodus nicht -verfügbar. Lediglich der Testmodus (Test-PKI) für die Selbstauskunft kann -durch 10 Klicks auf die Lupe auf der Startseite aktiviert und deaktiviert werden. +Um die Entwickleroptionen zu aktivieren, öffnen Sie im Menü „Hilfe“ den Punkt +„Information“. Klicken Sie zehnmal auf die „Anwendungsversion“. +Versionsinformationen. Nach dem zehnten Klick erhalten Sie eine Benachrichtigung, +dass die Entwickleroptionen aktiviert sind. Im Bereich Einstellungen befindet +sich nun eine neue Kategorie „Entwickleroptionen“. In den mobilen Versionen +erscheinen zusätzlich Optionen zum "Vor-Ort-Auslesen". +Außerdem kann in den mobilen Versionen der |AppName| der Testmodus (Test-PKI) +für die Selbstauskunft durch zehn Klicks auf die Lupe im Bereich +"Meine Daten einsehen" aktiviert und deaktiviert werden. -Einstellungen -------------- +Erweiterte Einstellungen +------------------------ -Die Entwickleroptionen bieten zwei Einstellungsmöglichkeiten: +Die Entwickleroptionen bieten erweiterte Einstellungsmöglichkeiten, die +nachfolgend erläutert werden. Testmodus für die Selbstauskunft (Test-PKI) ''''''''''''''''''''''''''''''''''''''''''' @@ -371,20 +366,123 @@ nur mit Echtausweisen genutzt werden. Wird der Testmodus (Test-PKI) aktiviert, nutzt die |AppName| einen Test-Dienst, der es ermöglicht, eine Selbstauskunft mit einem Testausweis durchzuführen. -Entwicklermodus -''''''''''''''' +Interner Kartensimulator +'''''''''''''''''''''''' + +Der interne Kartensimulator ermöglicht die Durchführung einer Authentisierung in +der Test-PKI ohne Ausweis oder Kartenleser. Beachten Sie, dass in den stationären +Versionen kein anderer Kartenleser verwendet werden kann, während der Simulator +aktiviert ist. + +In der aktuellen Version ist ein einzelnes statisches Profil hinterlegt, das über +die grafische Oberfläche nicht geändert werden kann. Lediglich im SDK ist es +möglich die Daten über das Kommando SET_CARD zu beeinflussen. +Weitere Informationen dazu finden Sie in der Dokumentation des +|AppName| SDK (siehe :ref:`Software Development Kit (SDK) `). + +Entwicklermodus (nur stationär) +''''''''''''''''''''''''''''''' Mit der Aktivierung des Entwicklermodus werden einige Sicherheitsabfragen während einer Authentisierung ignoriert. In Entwicklungsszenarien, in denen ohnehin mit Test-Diensten gearbeitet wird, führt das Ignorieren der Sicherheitsabfragen dazu, dass eine Authentisierung erfolgreich durchgeführt -werden kann. Dazu gehört beispielweise, dass neben sicheren TLS-Verbindungen -(https) auch unsichere Verbindungen ohne TLS (http) akzeptiert werden. Auch -werden abgelaufene Zertifikate ignoriert. Auf jede Sicherheitsverletzung wird -in den internen Benachrichtigungen der |AppName| bzw. des Betriebssystems +werden kann. Auf jede Sicherheitsverletzung wird in den internen +Benachrichtigungen der |AppName| bzw. des Betriebssystems hingewiesen. +Die folgenden Sicherheitsüberprüfungen sind im Entwicklermodus abgeschaltet: + +* Die verwendeten TLS-Schlüssel und ephemeralen TLS-Schlüssel haben die + notwendige Mindestlänge. +* Die URL der Beschreibung des TLS-Zertifikats des eID-Servers und die + TcToken-URL müssen die Same-Origin-Policy erfüllen. +* Die verwendeten TLS-Zertifikate müssen mit dem Berechtigungszertifikat + verschränkt sein. +* Die RefreshAddress-URL und etwaige Redirect-URL müssen das HTTPS-Schema + erfüllen. + +Der Entwicklermodus ist nur unter Windows und macOS verfügbar. **Wichtig:** Der Entwicklermodus kann nur für Test-Dienste verwendet werden, eine Verwendung mit echten Berechtigungszertifikaten ist nicht möglich. +CAN-Allowed Modus für Vor-Ort-Auslesen untertützen (nur mobil) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Aktiviert die Unterstützung für den CAN-Allowed-Modus (Vor-Ort-Auslesen). Wenn +ein entsprechendes Berechtigungszertifikat vorliegt, muss zum Auslesen die CAN +anstelle der PIN eingegeben werden. + +Anzeige der Berechtigungen überspringen (nur mobil) +''''''''''''''''''''''''''''''''''''''''''''''''''' + +Überspringt die Anzeige des Berechtigungszertifikat im CAN-Allowed-Modus und +wechselt direkt zur CAN-Eingabe. + + +.. _SDK_De: + +Software Development Kit (SDK) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Einsatzmöglichkeiten +-------------------- + +Mit dem Software Development Kit (SDK) der |AppName| ist es Ihnen möglich, die +Online-Ausweisfunktion direkt in die eigene Anwendung bzw. App zu integrieren. +Damit ermöglichen Sie Ihren Benutzern die medienbruchfreie Durchführung einer +Authentisierung - z.B. für Registrierungen oder Logins. + +Das SDK bietet Ihnen dabei den Vorteil, die Online-Authentisierung durchgehend im +eigenen Markendesign durchzuführen - ohne dass die Benutzer die gewohnte Umgebung +verlassen müssen. + +Das |AppName| SDK ermöglicht auch die Integration des Vor-Ort-Auslesens. +Hierbei wird anstelle der PIN zur Freigabe der Datenübertragung die CAN +übermittelt. Diese ist auf der Vorderseite des Ausweises aufgedruckt und wird zur +Freigabe des Auslesevorgangs benötigt. + +Integrationsmöglichkeiten +------------------------- + +Bei der voll-integrierten Version des SDKs wird die |AppName| als AAR Package +bzw. Swift Package in Ihre eigene Anwendung eingebunden. +Der Vorteil: Die |AppName| wird direkt mit ausgeliefert, sodass Benutzer die +|AppName| nicht separat auf Ihrem Smartphone installiert haben müssen. + +Bei der teil-integrierten Version des SDKs wird die |AppName| im Hintergrund +aufgerufen. Ggf. kann die App jedoch trotz Teil-Integration mit dem Installer +ausgeliefert werden. + +.. table:: Integrationsmöglichkeiten auf den verschiedenen Platformen + + +-----------------+------------------+------------------+ + | | Teil-Integration | Voll-Integration | + +=================+==================+==================+ + | Windows / macOS | Ja | Nein | + +-----------------+------------------+------------------+ + | Android | Nein | Ja | + +-----------------+------------------+------------------+ + | iOS | Nein | Ja | + +-----------------+------------------+------------------+ + +Entwicklerdokumentation +----------------------- + +Eine ausführliche Entwicklerdokumentation des SDKs und eine Auflistung der +möglichen Fehlercodes finden Sie unter https://www.ausweisapp.bund.de/sdk/. + +SDK Wrapper +----------- + +Sie können den SDK Wrapper der |AppName| zur Vereinfachung der Einbindung +des SDKs in Ihre App verwenden. Der SDK Wrapper bietet Swift und Kotlin +Bindings für iOS und Android an. + +Informationen zur Integration des SDK Wrappers finden Sie in der +Entwicklerdokumentation unter https://www.ausweisapp.bund.de/sdkwrapper/. + +.. raw:: latex + + \newpage diff --git a/docs/installation/README.en.rst b/docs/installation/README.en.rst index 43dcfdece..4be6ffebd 100644 --- a/docs/installation/README.en.rst +++ b/docs/installation/README.en.rst @@ -1,5 +1,7 @@ -English -======= +.. raw:: latex + + \part*{English} + \addcontentsline{toc}{part}{English} Installation ~~~~~~~~~~~~ @@ -41,10 +43,11 @@ PROXYSERVICE in application server mode. AUTOSTART - Setting AUTOSTART=true creates autostart entry for all users. Users are unable - to deactivate the autostart function in the |AppName|. Not specified, no - autostart entry is created (false). In that case, users are able to activate the - autostart function in the |AppName|. + By setting AUTOSTART=true, an autostart entry is created for all users and + closing |AppName| by clicking on the X, it is minimized into the info tray. + Users are unable to deactivate the autostart function in the |AppName|. Not + specified, no autostart entry is created (false). In that case, users are able + to activate the autostart function in the |AppName|. AUTOHIDE Concerns the automatic minimization after a successful authentication. Not @@ -54,7 +57,9 @@ AUTOHIDE REMINDTOCLOSE Closing the |AppName| by clicking on the X, the user is notified that only the user interface is closed and that the |AppName| is still available in the info - tray. At this point, it is possible to prevent future notifications. Setting + tray (if autostart of |AppName| is enabled) or that the |AppName| will be shut + down and the user needs to restart it to identify towards providers. + At this point, it is possible to prevent future notifications. Setting REMINDTOCLOSE=false deactivates this notification from the outset. Not specified, it is activated (true). @@ -98,11 +103,6 @@ UPDATECHECK The UPDATECHECK parameter affects neither updates of the service provider list nor updates of card reader information. -ONSCREENKEYBOARD - An on-screen keyboard is available to enter PIN, CAN or PUK. It is deactivated or - activated by setting ONSCREENKEYBOARD to false or true. Users are able to adjust - the setting. - SHUFFLESCREENKEYBOARD If the on-screen keyboard is activated, the number keys can be arranged at random. By setting SHUFFLESCREENKEYBOARD to false or true, the random arrangement can be @@ -167,8 +167,6 @@ the file must be "com.governikus.AusweisApp2.plist". The content is shown below: proxy.example.org customProxyPort 1337 - keylessPassword - shuffleScreenKeyboard visualPrivacy @@ -183,22 +181,21 @@ the file must be "com.governikus.AusweisApp2.plist". The content is shown below: The description for each value is applicable for both Windows and macOS, although the naming of the attributes differs, as shown in the following table: -======================= ======================= -macOS Windows -======================= ======================= -autoCloseWindow AUTOHIDE -remindToClose REMINDTOCLOSE -uiStartupModule ASSISTANT -transportPinReminder TRANSPORTPINREMINDER -customProxyType CUSTOMPROXYTYPE -customProxyPort CUSTOMPROXYPORT -customProxyHost CUSTOMPROXYHOST -keylessPassword ONSCREENKEYBOARD -shuffleScreenKeyboard SHUFFLESCREENKEYBOARD -visualPrivacy SECURESCREENKEYBOARD -enableCanAllowed ENABLECANALLOWED -skipRightsOnCanAllowed SKIPRIGHTSONCANALLOWED -======================= ======================= +======================== ======================= +macOS Windows +======================== ======================= +autoCloseWindow AUTOHIDE +remindToClose [#dialog]_ REMINDTOCLOSE +uiStartupModule ASSISTANT +transportPinReminder TRANSPORTPINREMINDER +customProxyType CUSTOMPROXYTYPE +customProxyPort CUSTOMPROXYPORT +customProxyHost CUSTOMPROXYHOST +shuffleScreenKeyboard SHUFFLESCREENKEYBOARD +visualPrivacy SECURESCREENKEYBOARD +enableCanAllowed ENABLECANALLOWED +skipRightsOnCanAllowed SKIPRIGHTSONCANALLOWED +======================== ======================= It might be necessary to force a reload of the data cached by the operating system: :code:`killall -u $USER cfprefsd` @@ -206,6 +203,7 @@ system: :code:`killall -u $USER cfprefsd` .. [#msiexecreturnvalues] https://docs.microsoft.com/en-us/windows/desktop/msi/error-codes .. [#standardarguments] https://docs.microsoft.com/en-us/windows/desktop/msi/standard-installer-command-line-options .. [#orca] https://docs.microsoft.com/en-us/windows/desktop/Msi/orca-exe +.. [#dialog] On macOS the |AppName| is minimized to the menu bar. Operational Environment Requirements @@ -294,7 +292,7 @@ TLS termination proxy. eID server. Due to configuration of the service on the service provider's behalf, any other port might be used by forwarding. .. [#TR-03112] See TR-03112-6 specifiaction from the BSI -.. [#govurl] All updates are based on the URL https://appl.governikus-asp.de/ausweisapp2/ +.. [#govurl] All updates are based on the URL https://updates.autentapp.de/ .. [#updatecheck] Automatic checks for new |AppName| versions can be deactivated, see commandline parameter UPDATECHECK. @@ -314,52 +312,138 @@ TLS termination proxy. Developer Options ~~~~~~~~~~~~~~~~~ -|AppName| features so-called developer options, available for the -supported operating systems of Windows and macOS. They facilitate -the integration of eID services. - +|AppName| features so-called developer options. They provide advanced settings and +facilitate the integration of eID services. +The developer options are hidden by default. -Windows & macOS ---------------- - -Developer options are activated by the version number accessible via -"Help" -> "Version Information" 10 times. This is applicable for both -Windows and macOS. Once activated, the developer options are accessible -via "Settings". - - -Android & iOS -------------- +Activating the Developer Options +-------------------------------- -The mobile version of |AppName| does not feature the developer mode. Solely -the test mode (Test-PKI) for self-authentication may be activated and -deactivated by clicking the magnifying glass on the start screen 10 times. +Developer options are activated by clicking the "Application Version" accessible +via "Help" -> "Information" 10 times. After the 10th time, you will receive a +notification that the developer options are activated. Once activated, you will +find a new category "developer options" in the settings menu. In the mobile +versions additional options for "on-site reading" appear. +In the mobile versions of |AppName| you can also activate and deactivate the test +mode (Test PKI) for self-authentication by clicking the magnifying glass on the +start screen 10 times. -Settings --------- +Advanced Settings +----------------- -Developer options allow to adjust two different settings: +The developer options offer advanced settings, which are explained below. -Test mode for self-authentication (Test-PKI) +Test mode for self-authentication (Test PKI) '''''''''''''''''''''''''''''''''''''''''''' In general, the self-authentication is a built-in service of |AppName| and can only be used with genuine ID cards. However, when in test mode, |AppName| uses a test service allowing for self-authentication with a test ID card. -Developer mode -'''''''''''''' +Internal card Simulator +''''''''''''''''''''''' + +The internal card simulator allows to run an authentication in the Test PKI +without any ID card or card reader. Note that no other card reader can be used in +the stationary versions while the simulator is activated. + +A single static profile is stored in the current version, which cannot be changed +via the graphical user interface. Only the SDK allows to change the profile's data +using the SET_CARD command. Further information can be found at the documentation +of |AppName| SDK (see :ref:`Software Development Kit (SDK) `). + +Developer mode (stationary only) +'''''''''''''''''''''''''''''''' When the developer mode is activated, some safety measures during an authentication process are ignored. Ignoring the safety measures with test services usually employed in test scenarios, yields a successful authentication. -For example, secure TLS connections (https) as well as insecure connections -without TLS (http) are accepted. Invalid certificates will be ignored. Each -safety breach will be highlighted as an internal notification in |AppName| +Each safety breach will be highlighted as an internal notification in |AppName| or the operating system respectively. +The following safety tests are disabled in the developer mode: + +* The used TLS keys and ephemeral TLS keys have the necessary minimum length. +* The URL of the TLS certificate description of the eID server and the TcToken URL + must fulfill the same-origin policy. +* The used TLS certificates must be entwined with the authorization certificate. +* The RefreshAddress URL and possible redirect URLs must conform to the HTTPS + scheme. **Please note:** Developer mode can only be used for test services, usage with genuine provider certificates is not possible. + +Support CAN Allowed mode for on-site reading (mobile only) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Enables support for the CAN allowed mode. If the provider got issued a +corresponding authorization certificate the ID card can be read by entering the +CAN instead of the PIN. + +Skip rights page +'''''''''''''''' + +Skips the page with the authorization certificate in the CAN allowed mode and asks +directly for the CAN. + +.. _SDK_En: + +Software Development Kit (SDK) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Possible Uses +------------- + +The software development kit (SDK) of |AppName| enables you to integrate the eID +function directly into your own application or app. This enables users to +authenticate themselves without media discontinuity. + +The SDK offers the advantage of being able to carry out an online +authentication in your own brand design - without users having to leave the +familiar environment. + +The |AppName| SDK also enables the integration of on-site reading. In this case, +the CAN is transmitted instead of the PIN to enable data transmission. You find +the CAN on the front of the ID card and you need it to enable the readout process. + +Integration Options +------------------- + +With the fully integrated version of the SDK, |AppName| is integrated into your +own application as an AAR package or Swift package. The advantage: |AppName| is +delivered directly with the application so that users don't have to install +|AppName| separately on their smartphone. + +With the partially integrated version of the SDK, |AppName| is called in the +background. Where applicable, however, the app can be delivered with the installer +regardless of partial integration. + +.. table:: Integration options for the different platforms + + +-----------------+----------------------+------------------+ + | | partially integrated | fully integrated | + +=================+======================+==================+ + | Windows / macOS | Ja | Nein | + +-----------------+----------------------+------------------+ + | Android | Nein | Ja | + +-----------------+----------------------+------------------+ + | iOS | Nein | Ja | + +-----------------+----------------------+------------------+ + +Developer documentation +----------------------- + +You can find a detailed developer documentation of the SDK with a list of possible +failure codes at https://www.ausweisapp.bund.de/sdk/. + +SDK Wrapper +----------- + +You can use the SDK Wrapper of the |AppName| to simplify the integration of +the SDK into your app. The SDK Wrapper offers Swift and Kotlin bindings for iOS +and Android. + +You can find information for integrating the SDK Wrapper in the developer +documentation at https://www.ausweisapp.bund.de/sdkwrapper/. diff --git a/docs/installation/conf.py.in b/docs/installation/conf.py.in index 07425e7a9..64948833d 100644 --- a/docs/installation/conf.py.in +++ b/docs/installation/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = '@PROJECT_NAME@ Erweiterte Dokumentation für Administratoren und Entwickler' -copyright = '2018-2023, Governikus GmbH & Co. KG' +copyright = '2018-2024, Governikus GmbH & Co. KG' author = 'Governikus GmbH & Co. KG' # The version info for the project you're documenting, acts as replacement for @@ -137,10 +137,6 @@ latex_elements = { \\@starttoc{toc} \\makeatother -% Only show part title without "Part I" -\\renewcommand{\\thepart}{} -\\renewcommand{\\partname}{} - \\newpage \\pagestyle{plain} \\pagenumbering{arabic} @@ -148,6 +144,7 @@ latex_elements = { # Latex figure (float) alignment 'figure_align': 'H', +'sphinxsetup' : 'HeaderFamily=\\linespread{1.9}\\sffamily\\bfseries', } # Grouping the document tree into LaTeX files. List of tuples @@ -167,7 +164,7 @@ latex_logo = '@SPHINX_DOCS_DIR@/../../resources/images/npa.png' #latex_use_parts = False # If true, show page references after internal links. -latex_show_pagerefs = True +#latex_show_pagerefs = False # If true, show URL addresses after external links. latex_show_urls = 'footnote' @@ -178,8 +175,6 @@ latex_show_urls = 'footnote' # If false, no module index is generated. #latex_domain_indices = True -latex_toplevel_sectioning = 'part' - rst_epilog = """ .. |AppName| replace:: @PROJECT_NAME@ -""" \ No newline at end of file +""" diff --git a/docs/releasenotes/2.0.0.rst b/docs/releasenotes/2.0.0.rst index 5769215c2..1be2c268a 100644 --- a/docs/releasenotes/2.0.0.rst +++ b/docs/releasenotes/2.0.0.rst @@ -8,19 +8,24 @@ Anwender """""""" - Umbenennung der AusweisApp2 zu AusweisApp. -- Überarbeitung der grafischen Oberfläche. +- Komplett überarbeitete grafische Oberfläche. -- Unterstützung des Dark-Modes. +- Dark-Mode wird auf allen Plattformen unterstützt. -- Das Querformat wird nun automatisch unterstützt. +- Die Darstellung im Querformat wurde optimiert und wird nun automatisch eingestellt. - Berücksichtigung der Systemschriftgröße und Systemschriftart. - Optimierung der Bedienbarkeit der Titelleiste. -- Online-Hilfe, Anbieterliste und Verlauf entfernt. +- Online-Hilfe steht nicht mehr zur Verfügung. -- PDF-Export-Funktion der Selbstauskunft entfernt. +- Die Anbieterliste ist nicht mehr in der AusweisApp integriert, sondern wird über + das AusweisApp-Portal aufgerufen. + +- Verlauf der Authentisierungsvorgänge wurde entfernt. + +- PDF-Export-Funktion der Selbstauskunft wurde entfernt. - macOS Catalina 10.15 wird nicht mehr unterstützt. diff --git a/docs/releasenotes/2.0.2.rst b/docs/releasenotes/2.0.2.rst new file mode 100644 index 000000000..60d0cae94 --- /dev/null +++ b/docs/releasenotes/2.0.2.rst @@ -0,0 +1,13 @@ +AusweisApp 2.0.2 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 12. Januar 2024 + + +Anwender +"""""""" +- Vermeidung von Verweisen auf den PIN-Rücksetzdienst. + + +Entwickler +"""""""""" diff --git a/docs/releasenotes/2.0.3.rst b/docs/releasenotes/2.0.3.rst new file mode 100644 index 000000000..c507235d3 --- /dev/null +++ b/docs/releasenotes/2.0.3.rst @@ -0,0 +1,17 @@ +AusweisApp 2.0.3 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 19. Januar 2024 + + +Anwender +"""""""" +- Absturz unter macOS 11 korrigiert. + +- Fehlende deutsche Übersetzung ergänzt. + +- Anzeige der Release Notes korrigiert. + + +Entwickler +"""""""""" diff --git a/docs/releasenotes/2.1.0.rst b/docs/releasenotes/2.1.0.rst new file mode 100644 index 000000000..5b6e1503a --- /dev/null +++ b/docs/releasenotes/2.1.0.rst @@ -0,0 +1,34 @@ +AusweisApp 2.1.0 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 29. Februar 2024 + + +Anwender +"""""""" +- Visuelle Anpassungen und Optimierungen der grafischen Oberfläche. + +- Erkennung der Systemsprache auf macOS verbessert. + +- Entfernung des Zeitlimits von 5 Minuten zur Passworteingabe bei aufliegendem Ausweis. + +- Korrekte Anzeige geänderter Gerätenamen bei der Nutzung von "Smartphone als Kartenleser". + +- Deaktivierung von Animationen ermöglicht. + +- Verhaltenskorrektur von "Smartphone als Kartenleser" mit + aktivierter Passworteingabe bei der Verwendung eines PUKs. + +- Korrektur des Verbindungstests mit einem passwortgeschützten + Proxy in der Diagnose auf Desktop-Systemen. + +- macOS Big Sur 11 wird nicht mehr unterstützt. + + +Entwickler +"""""""""" +- Korrekte Verarbeitung von Zertifikaten mit CAv3-Extension. + +- Dokumentation zur Installation und Integration vereinheitlicht. + +- Aktualisierung von OpenSSL auf die Version 3.1.5. diff --git a/docs/releasenotes/2.1.1.rst b/docs/releasenotes/2.1.1.rst new file mode 100644 index 000000000..34e8d3920 --- /dev/null +++ b/docs/releasenotes/2.1.1.rst @@ -0,0 +1,20 @@ +AusweisApp 2.1.1 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 10. April 2024 + + +Anwender +"""""""" +- Visuelle Anpassungen und Optimierungen der grafischen Oberfläche. + +- Korrektur von selten auftretenden Problemen im Zusammenhang + mit dem verwendeten Browser. + +- Textuelle Anpassungen. + + +Entwickler +"""""""""" +- Korrektur von READER Messages im SDK bei der Verwendung von + unbekannten Karten oder bei instabiler Verbindung zur Karte. diff --git a/docs/releasenotes/2.2.0.rst b/docs/releasenotes/2.2.0.rst new file mode 100644 index 000000000..757b729aa --- /dev/null +++ b/docs/releasenotes/2.2.0.rst @@ -0,0 +1,41 @@ +AusweisApp 2.2.0 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 02. Juli 2024 + + +Anwender +"""""""" +- Visuelle Anpassungen und Optimierungen der grafischen Oberfläche. + +- Anzeige des alten und neuen Gerätenamen bei der Nutzung von "Smartphone + als Kartenleser", falls sich der Name eines Geräts geändert hat. + +- Am Ende einer Authentisierung wurde ein Seite zur Information + eingefügt, bevor eine Weiterleitung zum Diensteanbieter erfolgt. + +- Erhöhung der zulässigen Zeit für die Antwort auf Kartenkommandos + auf Android um Ausweise zu unterstützen, die nach zu vielen falschen + Eingaben der CAN in einen sicheren langsamen Modus gewechselt haben. + +- Optimierung der Barrierearmut. + +- Unterstützung von Android 8 wurde eingestellt. + +- Die Funktion "Smartphone als Kartenleser" benötigt nun mindestens + die Version 2.1.0. + +- Supportunterstützung von ChromeOS. + + +Entwickler +"""""""""" +- Die Unterstützung von Schlüssellängen kleiner als 3000 Bit wurde eingestellt. + +- Erweiterung der Dokumentation für das SDK um ein Changelog. + +- Funktionserweiterung des SDKs (siehe Changelog). + +- Aktualisierung von Qt auf die Version 6.7.2. + +- Aktualisierung von OpenSSL auf die Version 3.3.1. diff --git a/docs/releasenotes/2.2.1.rst b/docs/releasenotes/2.2.1.rst new file mode 100644 index 000000000..4fd83acb0 --- /dev/null +++ b/docs/releasenotes/2.2.1.rst @@ -0,0 +1,33 @@ +AusweisApp 2.2.1 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 11. September 2024 + + +Anwender +"""""""" +- Visuelle Anpassungen und Optimierungen der grafischen Oberfläche. + +- Optimierung der Barrierearmut und Tastaturbedienbarkeit. + +- Verhinderung der Anzeige externer Inhalte in der grafischen Oberfläche. + +- Unterstützung von Smartphones mit Android 15, bei denen + eine optimierte Speicherverwaltung aktiviert wurde. + + +Entwickler +"""""""""" +- Unterstützung von 16 KB Page Sizes unter Android. + +- Stabilisierung des iOS SDK bei schnellen Neustarts. + +- Korrektur des Verhaltens bei der Verwendung von Qt 6.6.3. + +- Vermeidung einer Logdatei innerhalb des Containers im Container-SDK. + +- Aktualisierung vom Android NDK auf r27b (27.1.12297006). + +- Aktualisierung der Android SDK Platform auf Android 15 (API-Level 35). + +- Aktualisierung von OpenSSL auf die Version 3.3.2. diff --git a/docs/releasenotes/2.2.2.rst b/docs/releasenotes/2.2.2.rst new file mode 100644 index 000000000..00e5e5af6 --- /dev/null +++ b/docs/releasenotes/2.2.2.rst @@ -0,0 +1,16 @@ +AusweisApp 2.2.2 +^^^^^^^^^^^^^^^^ + +**Releasedatum:** 23. Oktober 2024 + + +Anwender +"""""""" +- Visuelle Anpassungen und Optimierungen der grafischen Oberfläche. + +- Optimierung der Barrierearmut und Tastaturbedienbarkeit. + + +Entwickler +"""""""""" +- Ergänzung der Android-ABIs armeabi-v7a und x86_64 zusätzlich zu arm64-v8a im SDK. diff --git a/docs/releasenotes/announce.rst b/docs/releasenotes/announce.rst index c4435458e..22f435946 100644 --- a/docs/releasenotes/announce.rst +++ b/docs/releasenotes/announce.rst @@ -1,18 +1,22 @@ Abkündigungen ============= -Mit der Version 2.1.0 der AusweisApp wird die Unterstützung +Mit der Version 2.3.0 der AusweisApp wird die Unterstützung +folgender Systeme eingestellt. + +- macOS Monterey 12 +- iOS 14 +- iOS 15 + + +Mit der Version 2.2.0 der AusweisApp wurde die Unterstützung folgender Systeme und Funktionen eingestellt. -- macOS Big Sur 11 +- Android 8 - TLS-Schlüssellängen unter 3000 Bit entsprechend TR-03116-4 (ausgenommen EC) -Mit der Version 2.0.0 der AusweisApp wurde die Unterstützung -folgender Systeme und Funktionen eingestellt. +Mit der Version 2.1.0 der AusweisApp wurde die Unterstützung +folgender Systeme eingestellt. -- macOS Catalina 10.15 -- Android 7 -- iOS 13 -- Online-Hilfe -- PDF-Export-Funktion der Selbstauskunft +- macOS Big Sur 11 diff --git a/docs/releasenotes/appcast.rst b/docs/releasenotes/appcast.rst index 0282b04d0..1439c4aff 100644 --- a/docs/releasenotes/appcast.rst +++ b/docs/releasenotes/appcast.rst @@ -4,6 +4,8 @@ Release Notes .. toctree:: :maxdepth: 1 - 2.0.0 + 2.2.2 + 2.2.1 + 2.2.0 announce issues diff --git a/docs/releasenotes/conf.py.in b/docs/releasenotes/conf.py.in index baa71f3f2..1196efdf2 100644 --- a/docs/releasenotes/conf.py.in +++ b/docs/releasenotes/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = '@PROJECT_NAME@' -copyright = '2016-2023, Governikus GmbH & Co. KG' +copyright = '2016-2024, Governikus GmbH & Co. KG' author = 'Governikus GmbH & Co. KG' # The version info for the project you're documenting, acts as replacement for @@ -171,4 +171,4 @@ latex_show_urls = 'footnote' rst_epilog = """ .. |AppName| replace:: @PROJECT_NAME@ -""" \ No newline at end of file +""" diff --git a/docs/releasenotes/issues.rst b/docs/releasenotes/issues.rst index ea3827dcc..9f6b82386 100644 --- a/docs/releasenotes/issues.rst +++ b/docs/releasenotes/issues.rst @@ -3,18 +3,6 @@ Bekannte Fehler Folgende Fehler und Einschränkungen sind zum Auslieferungszeitpunkt bekannt: -Alle Plattformen -"""""""""""""""" - -- Ausgewählte Elemente sind nicht im Hochkontrastmodus erkennbar. - Im "Kontrast Weiß" Modus sind zusätzlich die Radiocontrols nicht sichtbar. - -- Einige Animationen/Illustrationen/Icons werden im Hochkontrastmodus nicht - abgebildet. - -- Einige Elemente sind im Dark Mode schlecht erkennbar. - - Windows / macOS """"""""""""""" @@ -43,31 +31,25 @@ Windows / macOS - Der Installationsdialog (bei Installation und auch Deinstallation) richtet sich nicht nach der Systemsprache. -- Auf macOS kann es vorkommen, dass die Systemsprache von der AusweisApp nicht - erkannt wird. - -- Wenn mit einer MSI-Datei ein Update für die AusweisApp durchgeführt wird, - während diese noch läuft, kann es zu einer falschen Fehlermeldung kommen, - dass sie nicht beendet werden konnte. - Die Installation ist dennoch erfolgreich. +- Auf macOS ist derzeit keine Unterstützung für die Funktion "Full Keyboard + Access" gegeben. Android / iOS """"""""""""" - Zu Nutzungseinschränkungen einzelner Geräte beachten Sie bitte unsere - Homepage https://www.ausweisapp.bund.de/aa2/mobile-devices + Webseite https://www.ausweisapp.bund.de/aa2/mobile-devices - Unter Umständen kommt es zu Stabilitätsproblemen der NFC-Schnittstelle. -- Unter Android führen einige Änderungen der Systemeinstellungen bei laufender - |AppName| zu einem Absturz. Dazu zählt die Änderung der Systemsprache und - die Änderung des Typs der Navigationsleiste (Gesten / Schaltflächen). +- Unter Android führen unter Umständen einige Änderungen der + Systemeinstellungen bei laufender |AppName| zu einem Neustart oder Absturz. + Dazu zählt die Änderung der Systemsprache und die Änderung des Typs der + Navigationsleiste (Gesten / Schaltflächen). -- Unter iOS wird ein Workflow im SDK fälschlicherweise nicht abgebrochen, wenn - das SDK zur Eingabe einer PIN, CAN oder PUK aufgefordert hat aber der Benutzer - den NFC-Scan im Dialog abbricht, bevor das Passwort gesetzt oder ein INTERRUPT - ausgelöst wurde. +- Unter iOS ist derzeit keine Unterstützung für die Funktion "Full Keyboard + Access" gegeben. Barrierearmut @@ -78,35 +60,7 @@ Barrierearmut - Unter Android werden unsichtbare Inhalte vom Screenreader vorgelesen. -- Unter iOS kann der sichtbare Bereich vom Systemfokus abweichen. - -- Die aktivierbaren Elemente von eingeklappten Listen können ungewollte - Aktionen auslösen. - -- Aktuell sind die Bereiche "Softwarelizenz" und "Release Notes" nicht mit - dem Screenreader ansteuerbar. - -- Die Toggle-Elemente, die Hilfeseiten und die Überschriften der Startseite - besitzen zurzeit noch keine Sprachausgabe. - -- Die AusweisApp ist aktuell nicht mit dem Screenreader unter iOS einwandfrei - bedienbar. - -- Beim angeschlossenen Kartenleser Ausweisvorgang wird im Ausweisvorgang direkt - auf Schritt 2 gesprungen, ohne dass eine entsprechende Sprachausgabe erfolgt. - -- Bei der PIN-Eingabe erfolgt auf Android und iOS keine Sprachausgabe bei der - Betätigung der Tasten. - -- Es kann vorkommen, dass der Screenreader in einigen Dialogen die Überschriften - nicht vorliest. - -- In Texten wird zum Teil auf grafische Elemente hingewiesen, die keine textuelle - Repräsentation desselben Inhalts besitzen. - - Die angeforderten Rechte während eines Ausweisvorgangs werden nicht optimal vom Screenreader ausgegeben. - Der Screenreader kann teilweise Informationen an einigen Stellen doppelt ausgeben. - -- Bewegte Inhalte können derzeit nicht ausgeschaltet werden. diff --git a/docs/releasenotes/support.rst b/docs/releasenotes/support.rst index 2f6b4eda3..96cfbb0f5 100644 --- a/docs/releasenotes/support.rst +++ b/docs/releasenotes/support.rst @@ -8,12 +8,14 @@ der |AppName| unterstützt. Betriebssysteme """"""""""""""" -- macOS 11.0 - - macOS 12.0 - macOS 13.0 +- macOS 14.0 + +- macOS 15.0 + - Windows 10 (64 Bit) ab Version 1809 - Windows 11 @@ -24,10 +26,12 @@ Betriebssysteme - Windows Server 2022 -- Android 8.0 und höher (armeabi-v7a, arm64-v8a) +- Android 9 und höher (armeabi-v7a, arm64-v8a, x86_64) - iOS 14 und höher +- ChromeOS 125 und höher + Karten """""" @@ -52,55 +56,73 @@ und sollte daher mit allen marktüblichen Browsern verwendet werden können. Im Rahmen der Qualitätssicherung werden die folgenden Browserversionen getestet. -- Chrome 119 +- Chrome 129 -- Firefox 119 +- Firefox 131 -- Safari 17.0 (macOS) +- Safari 18.0 (macOS) -- Edge 119 +- Edge 129 Kartenleser ~~~~~~~~~~~ Alle Kartenleser, die die Online-Ausweisfunktion unterstützen und nach -BSI TR-03119 zertifiziert sind. Details hierzu befinden sich auf der Homepage -des BSI unter "Nach Technischen Richtlinien zertifizierte Produkte". +BSI TR-03119 zertifiziert sind. Details hierzu befinden sich auf der Website +des BSI unter `Zertifizierte Produkte - Chipkartenleser mit PA-Unterstützung +`_. + + +- ACS ACR1281U-C1 + +- ACS ACR1581U-C1 + +- Cherry Secure Board 1.0 -Zusätzlich werden folgende nicht zertifizierte Kartenleser getestet. +- Cherry ST-1275 - Cherry TC-1200 - Cherry TC-1300 -- Identiv Cloud 4701 F +- HID OMNIKEY 5021 CL -- Identiv SCL3711 +- HID OMNIKEY 5022 CL + +- HID OMNIKEY 5421 + +- HID OMNIKEY 5422 + +- Identiv 3700 F -- Identiv Cloud 3700 F +- Identiv 3720 F -- Identiv CLOUD 4700 F +- Identiv 3721 F -- ACR1252U +- Identiv 4701 F -- OMNIKEY 5021 CL +- Identiv Cloud 4700 F + +- Identiv SCL01x + +- Identiv SCL3711 -- OMNIKEY 5421 +- REINER SCT cyberJack wave (via USB) -- cyberJack wave (via USB) +- Signotec Omega Pad -Aktuelle Informationen zu Kartenlesern finden Sie auf unserer Webseite: -https://www.ausweisapp.bund.de/aa2/cardreader +Aktuelle Informationen zu Kartenlesern finden Sie auf unserer Website unter +`USB-Kartenleser `_. Alle NFC-fähigen Smartphones bzw. Tablets, die die Online-Ausweisfunktion unterstützen, können als Kartenleser verwendet werden. Dabei ist es notwendig die mobile |AppName| auf dem jeweiligen Smartphone zu installieren und zu starten. -Details hierzu befinden sich auf der Homepage: -https://www.ausweisapp.bund.de/aa2/mobile-devices +Details hierzu befinden sich auf unserer Website unter +`Smartphones & Tablets `_. Android / iOS @@ -116,20 +138,20 @@ Im mobilen Umfeld ist die Funktionalität jedoch abhängig von der vom Anbieter umgesetzten Aktivierung. Daher empfehlen wir einen der folgenden Browser zu verwenden. -- Chrome 119 (iOS/Android) +- Chrome 126 (iOS/Android) -- Firefox 119 (iOS/Android) +- Firefox 131 (iOS/Android) -- Samsung Internet 23 (Android) +- Samsung Internet 26 (Android) -- Safari 17.0 (iOS) +- Safari 18.0 (iOS) Kartenleser ~~~~~~~~~~~ Alle NFC-fähigen Smartphones bzw. Tablets, die die Online-Ausweisfunktion -unterstützen. Details hierzu befinden sich auf der Homepage: -https://www.ausweisapp.bund.de/aa2/mobile-devices +unterstützen. Details hierzu befinden sich auf unserer Website unter +`Smartphones & Tablets `_. Ebenfalls ist es möglich ein weiteres Smartphone als Kartenleser zu verwenden. Dabei ist es notwendig die mobile |AppName| auf dem jeweiligen Smartphone zu diff --git a/docs/releasenotes/text.conf.py.in b/docs/releasenotes/text.conf.py.in index bff7a0c4f..5acb52079 100644 --- a/docs/releasenotes/text.conf.py.in +++ b/docs/releasenotes/text.conf.py.in @@ -5,3 +5,7 @@ exclude_patterns = ['appcast.rst', 'general.rst', 'support.rst', 'versions.rst', # Sphinx needs a master document even though we just want to convert # some .rst files to .txt, so supply a document that is required anyway. master_doc = 'announce' + +rst_epilog = """ +.. |AppName| replace:: @PROJECT_NAME@ +""" diff --git a/docs/releasenotes/versions.rst b/docs/releasenotes/versions.rst index 705e1fb90..e9ae92b2e 100644 --- a/docs/releasenotes/versions.rst +++ b/docs/releasenotes/versions.rst @@ -1,11 +1,32 @@ Versionen ========= +Versionszweig 2.2 +----------------- +.. toctree:: + :maxdepth: 1 + + 2.2.2 + 2.2.1 + 2.2.0 + + +Versionszweig 2.1 +----------------- +.. toctree:: + :maxdepth: 1 + + 2.1.1 + 2.1.0 + + Versionszweig 2.0 ----------------- .. toctree:: :maxdepth: 1 + 2.0.3 + 2.0.2 2.0.1 2.0.0 diff --git a/docs/sdk/AusweisApp_Logo.svg b/docs/sdk/AusweisApp_Logo.svg index 217c4aeb0..9812b51ea 100644 --- a/docs/sdk/AusweisApp_Logo.svg +++ b/docs/sdk/AusweisApp_Logo.svg @@ -1,845 +1,845 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AusweisApp - - - - - - - - - - - - - - - - - - - - - - - - - - -Anwendung eID-Client/App des Bundes - -AusweisApp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AusweisApp - - - - - - - - - - - - - - - - - - - - - - - - - - -AusweisApp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AusweisApp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -des Bundes - -Anwendung eID-Client - - - - - - - - - - - - - - - - - - - - - - - - - - -AusweisApp - -App des Bundes - -AusweisApp - -Anwendung eID-Client - -Anwendung eID-Client - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Ausweis - - - - - - -eID-Client - -CMYK - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +AusweisApp + + + + + + + + + + + + + + + + + + + + + + + + + + +Anwendung eID-Client/App des Bundes + +AusweisApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +AusweisApp + + + + + + + + + + + + + + + + + + + + + + + + + + +AusweisApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +AusweisApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +des Bundes + +Anwendung eID-Client + + + + + + + + + + + + + + + + + + + + + + + + + + +AusweisApp + +App des Bundes + +AusweisApp + +Anwendung eID-Client + +Anwendung eID-Client + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Ausweis + + + + + + +eID-Client + +CMYK + diff --git a/docs/sdk/android.rst b/docs/sdk/android.rst index 4877f5ce6..91739e523 100644 --- a/docs/sdk/android.rst +++ b/docs/sdk/android.rst @@ -12,6 +12,11 @@ communicate with the |AppName| SDK. The |AppName| is available as an AAR package that can automatically be fetched by Android's default build system **gradle**. +.. seealso:: + For Android there is also the + `AusweisApp SDK Wrapper `_ + which is a software library that offers a high-level interface to the |AppName| SDK. + .. important:: The AAR package is available in maven central for free. If you need enterprise support feel free to contact us. @@ -30,7 +35,7 @@ be fetched by Android's default build system **gradle**. SDK --- The |AppName| SDK is distributed as an AAR package that contains -native **arm64-v8a** libraries only. +native **arm64-v8a**, **x86_64** and **armeabi-v7a** libraries only. The AAR package is available in the default repository of Android. The following listing shows the required **mavenCentral** in **build.gradle**. @@ -50,7 +55,7 @@ It is recommended to always use the latest version (|version|) of |AppName|. .. code-block:: groovy dependencies { - implementation 'com.governikus:ausweisapp:1.x.y' + implementation 'com.governikus:ausweisapp:x.y.z' } @@ -130,21 +135,7 @@ once. To do so the following snippet may prove useful: private boolean isAA2Process() { - if (Build.VERSION.SDK_INT >= 28) - { - return Application.getProcessName().endsWith(AA2_PROCESS); - } - - final int pid = android.os.Process.myPid(); - ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); - for (ActivityManager.RunningAppProcessInfo appProcess : manager.getRunningAppProcesses()) - { - if (appProcess.pid == pid) - { - return appProcess.processName.endsWith(AA2_PROCESS); - } - } - return false; + return Application.getProcessName().endsWith(AA2_PROCESS); } } diff --git a/docs/sdk/changelog.rst b/docs/sdk/changelog.rst new file mode 100644 index 000000000..94b5618e2 --- /dev/null +++ b/docs/sdk/changelog.rst @@ -0,0 +1,93 @@ +Changelog +========= + +Version 2.2.2 +^^^^^^^^^^^^^ +* Added Android ABIs armeabi-v7a and x86_64 in addition to arm64-v8a. + + +Version 2.2.1 +^^^^^^^^^^^^^ +* Stabilized fast SDK restarts on iOS. +* Support 16 KB page sizes on Android. +* Updated Android NDK to r27b (27.1.12297006). + + +Version 2.2.0 +^^^^^^^^^^^^^ +* Introduced the following additions in :ref:`api_level` **3**: + + * The command :ref:`continue_cmd`. + + * The message :ref:`pause_message`. + + * Extended parameter **card** of the message :ref:`reader` to signal an unknown card. + +* Added parameter **content** to the :ref:`filesystem` of the Simulator. +* Declared parameter **private** of the Simulator's :ref:`filesystem` deprecated. + + +Version 1.26.4 +^^^^^^^^^^^^^^ +* Added parameter **keys** to the command :ref:`set_card`. +* Added parameter **reason** to the message :ref:`change_pin`. + + +Version 1.26.3 +^^^^^^^^^^^^^^ +* Added variable "AUSWEISAPP2_AUTOMATIC_DEVELOPERMODE" to the mode :ref:`automatic`. +* Added parameter **reason** to message :ref:`auth`. + + +Version 1.24.0 +^^^^^^^^^^^^^^ +* Introduced the following changes in :ref:`api_level` **2**: + + * The commands :ref:`get_status` and :ref:`set_card`. + + * Removed the parameter **handleInterrupt** of the commands :ref:`run_auth` and :ref:`run_change_pin`. + + * Added the parameter **status** to the commands :ref:`run_auth` and :ref:`run_change_pin`. + + * Renamed parameter **reader** to **readers** in message :ref:`reader` + + * Added message :ref:`status`. + +* Added mode :ref:`automatic` for Desktop Systems. +* Added parameter **insertable** to message :ref:`reader`. + + +Version 1.22.3 +^^^^^^^^^^^^^^ + * Added parameter **developerMode** to the command :ref:`run_auth`. + + +Version 1.22.1 +^^^^^^^^^^^^^^ +* Added parameter **handleInterrupt** and **messages** to the commands :ref:`run_auth` and :ref:`run_change_pin` + for :ref:`api_level` **1**. +* Added the command :ref:`interrupt`. + + +Version 1.22.0 +^^^^^^^^^^^^^^ +* Added the commands :ref:`run_change_pin` and :ref:`set_new_pin`. +* Extended the message :ref:`access_rights` for "CAN allowed right" and "PIN management right". +* Added messages :ref:`change_pin` and :ref:`enter_new_pin`. + + +Version 1.20.0 +^^^^^^^^^^^^^^ +* Extended :ref:`access_rights` for write access. + + +Version 1.16.0 +^^^^^^^^^^^^^^ +* Changed parameter **value** for the commands :ref:`set_pin`, :ref:`set_can`, and :ref:`set_puk` for readers with + a keypad. +* Added parameter **keypad** to message :ref:`reader`. + + +Version 1.14.2 +^^^^^^^^^^^^^^ +* The message :ref:`set_can` may now be used with the "CAN allowed right". diff --git a/docs/sdk/commands.rst b/docs/sdk/commands.rst index ef37759fa..16a0ba238 100644 --- a/docs/sdk/commands.rst +++ b/docs/sdk/commands.rst @@ -169,7 +169,7 @@ Command :ref:`interrupt` allows to stop the dialog manually, if needed. - **developerMode**: True to enable "Developer Mode" for test cards and disable some security checks according to BSI TR-03124-1, otherwise false. (optional, default: false) - - **handleInterrupt**: True to automatically handle system dialog on iOS, otherwise false. + - **handleInterrupt**: True to automatically handle system dialog on iOS to enter a password, otherwise false. :ref:`api_level` v1 only. (optional, default: false) - **status**: True to enable automatic :ref:`status` messages, otherwise false. @@ -391,6 +391,34 @@ in a :ref:`reader` message. +.. _continue_cmd: + +CONTINUE +^^^^^^^^ +Continues the workflow after a :ref:`pause_message` was sent. + +The |AppName| will send a :ref:`pause_message` message with an +appropriate :ref:`cause ` for the waiting condition. +After the issue was fixed you have to send CONTINUE to go on with +the workflow. + + +.. versionadded:: 2.2.0 + The command :ref:`continue_cmd` was introduced in :ref:`api_level` **3**. + +.. code-block:: json + + { + "cmd": "CONTINUE" + } + +.. note:: + This command is allowed only if the |AppName| sent a :ref:`pause_message`. + Otherwise you will get a :ref:`bad_state` message as an answer. + + + + .. _get_certificate: GET_CERTIFICATE diff --git a/docs/sdk/conf.py.in b/docs/sdk/conf.py.in index 4b1b1661a..89a162d27 100644 --- a/docs/sdk/conf.py.in +++ b/docs/sdk/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = '@PROJECT_NAME@ SDK' -copyright = '2016-2023, Governikus GmbH & Co. KG' +copyright = '2016-2024, Governikus GmbH & Co. KG' author = 'Governikus GmbH & Co. KG' # The version info for the project you're documenting, acts as replacement for @@ -169,4 +169,4 @@ latex_show_urls = 'footnote' rst_epilog = """ .. |AppName| replace:: @PROJECT_NAME@ -""" \ No newline at end of file +""" diff --git a/docs/sdk/container.rst b/docs/sdk/container.rst index e7bab0808..fbff5edba 100644 --- a/docs/sdk/container.rst +++ b/docs/sdk/container.rst @@ -22,7 +22,7 @@ If you need to restore the configuration you can add a .. code-block:: sh - docker run --rm -p 127.0.0.1:24727:24727 governikus/ausweisapp + docker run --rm -p 127.0.0.1:24727:24727 governikus/ausweisapp2 diff --git a/docs/sdk/desktop.rst b/docs/sdk/desktop.rst index cd07d4bc6..d9c1a531d 100644 --- a/docs/sdk/desktop.rst +++ b/docs/sdk/desktop.rst @@ -50,8 +50,7 @@ application uses the |AppName|. Integrated ^^^^^^^^^^ -You can deliver separate |AppName| binaries inside your own application or -start an already installed |AppName|. +You can start an already installed |AppName| for your application. If your application spawns a separate process you should provide the commandline parameter ``--port 0`` to avoid conflicts with a user started |AppName| and other processes that uses a specified port. @@ -65,6 +64,9 @@ Example: **$TMPDIR/AusweisApp.12345.port** Your application can avoid the graphical interface of |AppName| by providing the commandline parameter ``--ui websocket``. +.. important:: + If your application changes the used port the "smartphone as card reader" + is not possible. .. _automatic: @@ -122,13 +124,13 @@ the following information. .. code-block:: json { - "Implementation-Title": "AusweisApp", + "Name": "AusweisApp2", + "Implementation-Title": "AusweisApp2", "Implementation-Vendor": "Governikus GmbH & Co. KG", - "Implementation-Version": "1.16.0", - "Name": "AusweisApp", - "Specification-Title": "TR-03124", + "Implementation-Version": "2.0.0", + "Specification-Title": "TR-03124-1", "Specification-Vendor": "Federal Office for Information Security", - "Specification-Version": "1.3" + "Specification-Version": "1.4" } diff --git a/docs/sdk/index.rst b/docs/sdk/index.rst index 9122767af..9d2ce0d0f 100644 --- a/docs/sdk/index.rst +++ b/docs/sdk/index.rst @@ -15,9 +15,10 @@ Table of contents ----------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 intro + changelog .. raw:: latex diff --git a/docs/sdk/intro.rst b/docs/sdk/intro.rst index b198608d7..ed1692e3c 100644 --- a/docs/sdk/intro.rst +++ b/docs/sdk/intro.rst @@ -19,6 +19,10 @@ or will be sent as an event. Also this documentation provides some example workflows to show a possible communication. +.. seealso:: + For Android and iOS there is also the + `AusweisApp SDK Wrapper `_ + which is a software library that offers a high-level interface to the |AppName| SDK. .. important:: The |AppName| does **not** provide any personal data to diff --git a/docs/sdk/ios.rst b/docs/sdk/ios.rst index bf1e49d34..35a25d897 100644 --- a/docs/sdk/ios.rst +++ b/docs/sdk/ios.rst @@ -7,12 +7,15 @@ be linked into your application. Subsequent sections deal with the SDK interface itself and explain which steps are necessary in order to communicate with the |AppName| SDK. +.. seealso:: + For iOS there is also the + `AusweisApp SDK Wrapper `_ + which is a software library that offers a high-level interface to the |AppName| SDK. + .. important:: Apple released the necessary NFC API with iOS 13.0! Be aware that it is not possible to support older versions. - - Use XCFramework --------------- The interface ``AusweisApp2.h`` of the SDK for iOS is provided as **C-Header** diff --git a/docs/sdk/messages.rst b/docs/sdk/messages.rst index 4c95f3bd9..c2623e5d9 100644 --- a/docs/sdk/messages.rst +++ b/docs/sdk/messages.rst @@ -668,20 +668,6 @@ increased for **incompatible** changes. - **Specification-Version**: Version of specification. - - **AusweisApp**: Indicates the state of the connection to - the AusweisApp2 for integrated SDK (**Android only**). - The following states are possible. - - - **CONNECTED**: The SDK is connected. - - - **DISCONNECTED**: The SDK is not connected. - - - **INVALID_CERTIFICATE**: The certificate of LocalIfd is not valid. - - - **INCOMPATIBLE_VERSION**: The version of LocalIfd is not compatible. - - - **UNKNOWN**: The state could not be recognized. - .. code-block:: json { @@ -695,8 +681,7 @@ increased for **incompatible** changes. "Specification-Title": "TR-03124-1", "Specification-Vendor": "Federal Office for Information Security", "Specification-Version": "1.4" - }, - "AusweisApp": "CONNECTED" + } } @@ -802,6 +787,9 @@ If a workflow is in progress and a card with disabled eID function was inserted, this message will still be sent, but the workflow will be paused until a card with enabled eID function is inserted. +.. versionadded:: 2.2.0 + Parameter **card** signals an **unknown card** with an empty object (:ref:`api_level` 3). + .. versionadded:: 1.24.0 Parameter **insertable** added. @@ -818,7 +806,8 @@ until a card with enabled eID function is inserted. - **keypad**: Indicates whether a card reader has a keypad. The parameter is only shown when a reader is attached. - - **card**: Provides information about inserted card, otherwise null. + - **card**: Provides information about an inserted eID card. An empty object is + used for an unknown card. Otherwise null. - **inoperative**: True if PUK is inoperative and cannot unblock PIN, otherwise false. This can be recognized if user enters a correct @@ -832,6 +821,8 @@ until a card with enabled eID function is inserted. - **retryCounter**: Count of possible retries for the PIN. If you enter a PIN with command :ref:`set_pin` it will be decreased if PIN was incorrect. +**eID card:** + .. code-block:: json { @@ -848,7 +839,31 @@ until a card with enabled eID function is inserted. } } +**Unknown card (**:ref:`api_level` **3):** +.. code-block:: json + + { + "msg": "READER", + "name": "NFC", + "insertable": false, + "attached": true, + "keypad": false, + "card": {} + } + +**No card:** + +.. code-block:: json + + { + "msg": "READER", + "name": "NFC", + "insertable": false, + "attached": true, + "keypad": false, + "card": null + } .. _reader_list: @@ -934,6 +949,44 @@ or :ref:`run_change_pin`. +.. _pause_message: + +PAUSE +^^^^^ +This message will be sent by |AppName| to signal certain waiting conditions. +E.g. if a card connection cannot be established or maintained due to a bad +positioning of the card, this message will be send with :ref:`BadCardPosition ` +as the cause. +After the causing issue, denoted be the value of :ref:`cause `, +was fixed, the next command should be :ref:`continue_cmd`. + +.. versionadded:: 2.2.0 + The message :ref:`pause_message` was introduced in :ref:`api_level` **3**. The SDK will halt until + :ref:`continue_cmd` was sent to acknowledge the condition. + +.. _pause_cause: + + - **cause**: The cause for the waiting condition. + +.. code-block:: json + + { + "msg": "PAUSE", + "cause": "BadCardPosition" + } + + +The following list of :ref:`causes ` contains all conditions. Each condition is a stable and +unique string to safely distinguish each waiting condition. + +.. _bad_card_position: + + - **BadCardPosition**: Denotes an unstable or lost card connection. After fixing the issue you + have to call :ref:`continue_cmd` to go on with the workflow. + + + + .. _unknown_command: UNKNOWN_COMMAND diff --git a/docs/sdk/simulator.rst b/docs/sdk/simulator.rst index 8fcee9e75..052b39045 100644 --- a/docs/sdk/simulator.rst +++ b/docs/sdk/simulator.rst @@ -26,6 +26,12 @@ These are the default values if your application does not provide other values as **simulator** parameter in :ref:`set_card` or if you use the :ref:`automatic` mode of :doc:`desktop` or the :doc:`container` variant. +.. versionadded:: 2.2.0 + Parameter **content** in **keys** added. + +.. deprecated:: 2.2.0 + Parameter **private** in **keys** will be removed in 2.3.0. + .. code-block:: json "files": @@ -53,8 +59,8 @@ mode of :doc:`desktop` or the :doc:`container` variant. ], "keys": [ - {"id": 1, "private": "0353859c2ec67780ba39015de8c682af2326d43de9ce1e07737087bd1e17cb22"}, - {"id": 2, "private": "9ad0ad7f4dfaaa06988339fc31d3a111f4c7964ac7f377373a2454327c43e2ff"} + {"id": 1, "content": "308202050201003081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a70201010482010f3082010b02010104200353859c2ec67780ba39015de8c682af2326d43de9ce1e07737087bd1e17cb22a081e33081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7020101"}, + {"id": 2, "content": "308202050201003081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a70201010482010f3082010b02010104209ad0ad7f4dfaaa06988339fc31d3a111f4c7964ac7f377373a2454327c43e2ffa081e33081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7020101"} ] @@ -68,12 +74,11 @@ The keys are used to calculate the pseudonym. Key ``1`` is used to check the blacklist while key ``2`` is used to calculate the pseudonym for the service provider. -New keys can be generated with OpenSSL. +A new key can be generated with OpenSSL (convert base64 to hex after generation). .. code-block:: console - openssl ecparam -name brainpoolP256r1 -genkey -out riKey.pem - openssl ec -in riKey.pem -text -noout + openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:brainpoolP256r1 @@ -99,7 +104,7 @@ data and is only required for eID-Client or eID-Server development. ], "keys": [ - {"id": 41, "private": "a07eb62e891daa84643e0afcc1af006891b669b8f51e379477dbeab8c987a610"} + {"id": 41, "content": "308202050201003081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a70201010482010f3082010b0201010420a07eb62e891daa84643e0afcc1af006891b669b8f51e379477dbeab8c987a610a081e33081e0020101302c06072a8648ce3d0101022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7020101"} ] diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 201bcf8a3..9b4188642 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -20,6 +20,7 @@ project(AusweisApp2_Libs ${COMPILER_SEARCH}) option(INTEGRATED_SDK "Build integrated specific SDK" OFF) option(CONTAINER_SDK "Build container specific SDK" OFF) +option(DEVELOPER "Include modules/features for developer" OFF) if(CONTAINER_SDK) set(INTEGRATED_SDK ON) @@ -134,7 +135,7 @@ if("${OPENSSL}" MATCHES "SNAP") list(APPEND OPENSSL_URLS ${OPENSSL_SOURCE}/snapshot/${OPENSSL_FILE}) else() string(SUBSTRING ${OPENSSL} 0 5 OPENSSL_SUBVERSION) - list(APPEND OPENSSL_URLS ${OPENSSL_SOURCE}/${OPENSSL_FILE}) + list(APPEND OPENSSL_URLS https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL}/${OPENSSL_FILE}) list(APPEND OPENSSL_URLS ${OPENSSL_SOURCE}/old/${OPENSSL_SUBVERSION}/${OPENSSL_FILE}) endif() @@ -149,7 +150,7 @@ list(APPEND ENABLED_TARGETS openssl) set(OPENSSL_CONFIGURE_FLAGS no-camellia no-bf no-aria no-seed no-poly1305 no-srp no-gost no-idea no-mdc2 no-rc2 no-rc4 no-rc5 no-srtp no-sm2 no-sm3 no-sm4) set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-ct no-dgram no-cast no-chacha no-blake2 no-rmd160 no-scrypt no-siphash no-whirlpool no-md4 no-des no-ec2m) set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-tls1 no-tls1-method no-tls1_1 no-tls1_1-method no-tls1_3 no-ssl3 no-ssl3-method no-dtls no-dtls1-method no-dtls1_2-method) -set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-deprecated no-engine no-async no-dso no-comp no-ts no-makedepend no-tests no-legacy shared) +set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-deprecated no-engine no-async no-dso no-comp no-ts no-makedepend no-tests no-legacy) if(${CMAKE_BUILD_TYPE} STREQUAL "DEBUG") set(OPENSSL_CONFIGURE_FLAGS --debug ${OPENSSL_CONFIGURE_FLAGS}) @@ -174,16 +175,18 @@ else() endif() if(IOS) - set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-asm) + set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-asm no-shared) if(CMAKE_OSX_SYSROOT MATCHES "iphonesimulator") set(OPENSSL_ARCH iossimulator-xcrun) if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} "-arch arm64") endif() + set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -mios-simulator-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}) else() - set(OPENSSL_ARCH ios64-cross) + set(OPENSSL_ARCH ios64-xcrun) string(REGEX REPLACE "/SDKs/.*" "" CROSS_TOP_DEV_ROOT "${CMAKE_OSX_SYSROOT}") set(OPENSSL_ENV CROSS_TOP=${CROSS_TOP_DEV_ROOT} CROSS_SDK=iPhoneOS.sdk) + set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -mios-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}) endif() set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -fvisibility=hidden) elseif(APPLE) @@ -194,11 +197,11 @@ elseif(APPLE) if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-asm) set(OPENSSL_ARCH darwin64-arm64-cc) - set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -mmacosx-version-min=11.0) else() set(OPENSSL_ARCH darwin64-x86_64-cc) - set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -mmacosx-version-min=10.15) endif() + + set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} -mmacosx-version-min=12.0) elseif(MINGW OR CYGWIN) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(OPENSSL_ARCH mingw64) @@ -211,10 +214,14 @@ elseif(MINGW OR CYGWIN) endif() elseif(MSVC) set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-asm) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") set(OPENSSL_ARCH VC-WIN64A) - else() + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") set(OPENSSL_ARCH VC-WIN32) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + set(OPENSSL_ARCH VC-WIN64-ARM) + else() + message(FATAL_ERROR "CMAKE_SYSTEM_PROCESSOR not supported by openssl: ${CMAKE_SYSTEM_PROCESSOR}") endif() elseif(ANDROID) if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") @@ -225,14 +232,16 @@ elseif(ANDROID) elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") set(OPENSSL_ARCH android-x86_64) set(OPENSSL_NDK_PREFIX x86_64) + ADD_FLAG(-Wl,-z,max-page-size=16384 NOQUOTES VAR OPENSSL_COMPILER_FLAGS USE_SAME_FOR_LINKER USE_LINKER_ONLY) elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86") set(OPENSSL_ARCH android-x86) set(OPENSSL_NDK_PREFIX i686) elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") set(OPENSSL_ARCH android-arm64) set(OPENSSL_NDK_PREFIX aarch64) + ADD_FLAG(-Wl,-z,max-page-size=16384 NOQUOTES VAR OPENSSL_COMPILER_FLAGS USE_SAME_FOR_LINKER USE_LINKER_ONLY) else() - message(FATAL_ERROR "CMAKE_ANDROID_ARCH_ABI not supported by openssl") + message(FATAL_ERROR "CMAKE_ANDROID_ARCH_ABI not supported by openssl: ${CMAKE_ANDROID_ARCH_ABI}") endif() set(OPENSSL_CONFIGURE_FLAGS ${OPENSSL_CONFIGURE_FLAGS} no-stdio) @@ -244,12 +253,22 @@ elseif(ANDROID) endif() set(OPENSSL_COMPILER_FLAGS ${OPENSSL_COMPILER_FLAGS} --target=${OPENSSL_NDK_PREFIX}-linux-android${OPENSSL_NDK_INFIX}${CMAKE_SYSTEM_VERSION}) elseif(BSD) - set(OPENSSL_ARCH BSD-x86_64) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") + set(OPENSSL_ARCH BSD-x86_64) + else() + message(FATAL_ERROR "CMAKE_SYSTEM_PROCESSOR not supported by openssl: ${CMAKE_SYSTEM_PROCESSOR}") + endif() elseif(LINUX) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") set(OPENSSL_ARCH linux-x86_64) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + set(OPENSSL_ARCH linux-x86) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(OPENSSL_ARCH linux-aarch64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") + set(OPENSSL_ARCH linux-armv4) else() - set(OPENSSL_ARCH linux-generic32) + message(FATAL_ERROR "CMAKE_SYSTEM_PROCESSOR not supported by openssl: ${CMAKE_SYSTEM_PROCESSOR}") endif() else() message(FATAL_ERROR "Unsupported system") @@ -346,6 +365,12 @@ list(APPEND NO_FEATURES_SHARED imageformat_bmp imageformat_ppm imageformat_xbm) list(APPEND NO_FEATURES_SHARED sharedmemory textodfwriter) list(APPEND NO_FEATURES_SHARED undocommand undogroup undostack) list(APPEND NO_FEATURES_SHARED printsupport dtls dom sql xml pdf) +list(APPEND NO_FEATURES_SHARED brotli topleveldomain private_tests dnslookup sctp) +list(APPEND NO_FEATURES_SHARED localserver filesystemwatcher libresolv) +list(APPEND NO_FEATURES_SHARED quickcontrols2-imagine quickcontrols2-material quickcontrols2-universal) +if(NOT DEVELOPER) + list(APPEND NO_FEATURES_SHARED quickcontrols2-fusion) +endif() if(CONTAINER_SDK) list(APPEND NO_FEATURES_SHARED testlib androiddeployqt) endif() @@ -354,7 +379,7 @@ foreach(feature ${NO_FEATURES_SHARED}) endforeach() list(APPEND NO_FEATURES calendarwidget colordialog dial fontcombobox fontdialog lcdnumber) -list(APPEND NO_FEATURES splashscreen syntaxhighlighter undoview) +list(APPEND NO_FEATURES splashscreen syntaxhighlighter undoview securetransport schannel) if(NOT MAC) list(APPEND NO_FEATURES mdiarea) endif() @@ -423,14 +448,18 @@ elseif(ANDROID) set(QT_ENV OPENSSL_LIBS=-lcrypto_${CMAKE_ANDROID_ARCH_ABI}\ -lssl_${CMAKE_ANDROID_ARCH_ABI}) set(QT_CONFIGURE_FLAGS ${QT_CONFIGURE_FLAGS} ${QT_CONFIGURE_FLAGS_OTHER} - -android-sdk ${ANDROID_SDK} -android-ndk ${CMAKE_ANDROID_NDK} -android-ndk-platform android-${CMAKE_SYSTEM_VERSION} + -android-sdk ${ANDROID_SDK_ROOT} -android-ndk ${CMAKE_ANDROID_NDK} -android-ndk-platform android-${CMAKE_SYSTEM_VERSION} -android-abis ${CMAKE_ANDROID_ARCH_ABI} -xplatform android-clang) # ANDROID_TARGET_SDK_VERSION cannot be passed here as Qt has it's own variable and uses the latest in "${ANDROID_SDK_ROOT}/platforms". # https://code.qt.io/cgit/qt/qtbase.git/tree/cmake/QtPlatformAndroid.cmake?h=6.4#n36 + set(ANDROID_PAGE_SIZE_FLAGS "-Wl,-z,max-page-size=16384") if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") set(QT_CONFIGURE_FLAGS ${QT_CONFIGURE_FLAGS} -no-use-gold-linker) + set(ADDITIONAL_QT_DEFINES ${ADDITIONAL_QT_DEFINES} -DCMAKE_SHARED_LINKER_FLAGS=${ANDROID_PAGE_SIZE_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS=${ANDROID_PAGE_SIZE_FLAGS}) + elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") + set(ADDITIONAL_QT_DEFINES ${ADDITIONAL_QT_DEFINES} -DCMAKE_SHARED_LINKER_FLAGS=${ANDROID_PAGE_SIZE_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS=${ANDROID_PAGE_SIZE_FLAGS}) endif() elseif(BSD) set(QT_CONFIGURE_FLAGS ${QT_CONFIGURE_FLAGS} ${QT_CONFIGURE_FLAGS_OTHER} -no-libudev) @@ -548,7 +577,7 @@ if(WIN32) endif() endif() -if(CMAKE_VERSION VERSION_LESS "3.15" OR BSD) +if(CMAKE_VERSION VERSION_LESS "3.15") set(COMPRESSION cfJ) set(COMPRESSION_FILENDING tar.xz) else() diff --git a/libs/CMakePresets.json b/libs/CMakePresets.json index 06b1d2106..d41c4cba0 100644 --- a/libs/CMakePresets.json +++ b/libs/CMakePresets.json @@ -105,36 +105,6 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "DEBUG" } - }, - { - "name": "base", - "hidden": true, - "binaryDir": "${sourceParentDir}/../AusweisApp2-build/libs/${presetName}" - }, - { - "name": "default", - "inherits": "base", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "DEBUG" - } - }, - { - "name": "container", - "inherits": "default", - "cacheVariables": { - "CONTAINER_SDK": "ON" - } - }, - { - "name": "android", - "inherits": "default", - "toolchainFile": "${sourceParentDir}/cmake/android.toolchain.cmake" - } - ], - "buildPresets": [ - { - "name": "default", - "configurePreset": "default" } ] } diff --git a/libs/README.rst b/libs/README.rst index 720766ceb..3b9a6f6f1 100644 --- a/libs/README.rst +++ b/libs/README.rst @@ -6,7 +6,7 @@ Abhängigkeiten und die Compilertools beinhaltet. Unterstützte C++17 Compiler: -- MinGW / GCC >= 11.2 +- MinGW / GCC >= 13.1 - Clang >= 5.0 @@ -15,7 +15,7 @@ Unterstützte C++17 Compiler: Notwendige Bibliotheken: -- Qt >= 5.15 +- Qt >= 6.4 - http://www.qt.io/download/ @@ -30,7 +30,7 @@ Notwendige Bibliotheken: Notwendige Tools: -- CMake >= 3.13.0 (3.14.0 >= für iOS) +- CMake >= 3.19.0 - http://www.cmake.org @@ -122,7 +122,7 @@ CMake - https://cmake.org/download/ - - Getestet: 3.23.2 + - Getestet: 3.28.3 - Pfad zur CMake-Executable muss zur Path-Umgebungsvariable hinzugefügt werden @@ -145,7 +145,8 @@ MinGW - https://wiki.qt.io/MinGW -- Getestet: x86_64-11.2.0-release-posix-seh-rt_v9-rev3 +- Getestet: 13.1.0-202407240918mingw1310 + https://download.qt.io/online/qtsdkrepository/windows_x86/desktop/tools_mingw1310 - Pfad zu MinGW-bin-Verzeichnis muss zur Path-Umgebungsvariable hinzugefügt werden @@ -188,7 +189,7 @@ Python - https://www.python.org/downloads/ - - Getestet: 3.10.5 + - Getestet: 3.11.8 - Pfad zur Python-Executable muss zur Path-Umgebungsvariable hinzugefügt werden @@ -196,8 +197,8 @@ Python Perl """" -- Sowohl für Qt als auch für OpenSSL ist Perl erforderlich. Für OpenSSL ist - relevant, welche Art von Pfaden (Unix oder Windows) Perl verwendet. +- Für OpenSSL ist Perl erforderlich und relevant, + welche Art von Pfaden (Unix oder Windows) Perl verwendet. - Für Builds mit MinGW wird MSYS2 Perl benötigt. @@ -221,10 +222,9 @@ Perl - ActivePerl/StrawberryPerl - Es kann entweder ActivePerl(https://www.activestate.com/products/perl/) oder - StrawberryPerl(https://strawberryperl.com/, hierbei den QTBUG-102828[1] - beachten) verwendet werden. + StrawberryPerl(https://strawberryperl.com/) verwendet werden. - - Getestet: strawberry-perl-5.32.1.1-64bit.msi + - Getestet: strawberry-perl-5.38.0.1-64bit-portable.zip (Nur der "perl" Ordner) - Pfad zur Perl-Executable muss zur Path-Umgebungsvariable hinzugefügt werden. @@ -232,7 +232,6 @@ Perl vor andere Perl Installationen (z.B. MSYS2) aufgeführt wird, sodass diese Version anderen Perl Installationen vorgezogen wird. -[2] https://bugreports.qt.io/browse/QTBUG-102828 OpenSSL / Qt mit MinGW @@ -311,25 +310,19 @@ Komponenten vorhanden sein: - https://developer.android.com/tools/sdk/ndk/index.html - - Getestet: r21e (https://wiki.qt.io/Qt_for_Android_known_issues) + - Getestet: r26c (https://wiki.qt.io/Qt_for_Android_known_issues) - Android SDK (cmdline) mit gesetztem ANDROID_SDK_ROOT - - https://developer.android.com/studio#cmdline-tools + - https://developer.android.com/tools#tools-sdk - - Getestet: 26.1.1 / 3.0 + - Getestet: 12.0 - SDK build tools - https://developer.android.com/studio/releases/build-tools - - Getestet: 30.0.3 - -- SDK platform tools - - - https://developer.android.com/studio/releases/platform-tools - - - Getestet: 30.0.3 + - Getestet: 34.0.0 - Um Qt erfolgreich zu bauen, ist mindestens ein API-Levelpaket von Android notwendig. Dieses sollte mindestens Level 21 sein. Nähere Informationen dazu diff --git a/libs/Versions.cmake b/libs/Versions.cmake index 644bd3303..4a9f3e8d4 100644 --- a/libs/Versions.cmake +++ b/libs/Versions.cmake @@ -1,5 +1,5 @@ -set(QT 6.5.3) -set(QT_HASH 7cda4d119aad27a3887329cfc285f2aba5da85601212bcb0aea27bd6b7b544cb) +set(QT 6.7.2) +set(QT_HASH 0aaea247db870193c260e8453ae692ca12abc1bd841faa1a6e6c99459968ca8a) -set(OPENSSL 3.1.4) -set(OPENSSL_HASH 840af5366ab9b522bde525826be3ef0fb0af81c6a9ebd84caa600fea1731eee3) +set(OPENSSL 3.3.2) +set(OPENSSL_HASH 2e8a40b01979afe8be0bbfb3de5dc1c6709fedb46d6c89c10da114ab5fc3d281) diff --git a/libs/patch.cmake.in b/libs/patch.cmake.in index adec3a60a..a3b716d3e 100644 --- a/libs/patch.cmake.in +++ b/libs/patch.cmake.in @@ -31,6 +31,9 @@ macro(SEARCH_PATCH_CMD) if(PATCH_CMD) set(PATCH_OPTIONS -p1 -i) + if(WIN32) + set(PATCH_OPTIONS --verbose ${PATCH_OPTIONS}) + endif() message(STATUS "Using 'patch' command... ${PATCH_CMD}") else() message(STATUS "Cannot find 'patch' command... using patch.py") diff --git a/libs/patch.py b/libs/patch.py index 088fbbab3..e1114fb14 100644 --- a/libs/patch.py +++ b/libs/patch.py @@ -31,7 +31,7 @@ from __future__ import print_function __author__ = "Conan.io " -__version__ = "1.17.4" +__version__ = "1.18.0" __license__ = "MIT" __url__ = "https://github.com/conan-io/python-patch" @@ -424,7 +424,7 @@ def lineno(self): hunkparsed = False # state after successfully parsed hunk # regexp to match start of hunk, used groups - 1,3,4,6 - re_hunk_start = re.compile(b"^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@") + re_hunk_start = re.compile(br"^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@") self.errors = 0 # temp buffers for header and filenames info @@ -575,7 +575,7 @@ def lineno(self): # strptime function and %z support is patchy, so we drop # everything from the . onwards and group the year and time # separately. - re_filename_date_time = b"^--- ([^\t]+)(?:\s([0-9-]+)\s([0-9:]+)|.*)" + re_filename_date_time = br"^--- ([^\t]+)(?:\s([0-9-]+)\s([0-9:]+)|.*)" match = re.match(re_filename_date_time, line) # todo: support spaces in filenames if match: @@ -618,7 +618,7 @@ def lineno(self): filenames = False headscan = True else: - re_filename_date_time = b"^\+\+\+ ([^\t]+)(?:\s([0-9-]+)\s([0-9:]+)|.*)" + re_filename_date_time = br"^\+\+\+ ([^\t]+)(?:\s([0-9-]+)\s([0-9:]+)|.*)" match = re.match(re_filename_date_time, line) if not match: warning("skipping invalid patch - no target filename at line %d" % (lineno+1)) @@ -650,7 +650,7 @@ def lineno(self): continue if hunkhead: - match = re.match(b"^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@(.*)", line) + match = re.match(br"^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@(.*)", line) if not match: if not p.hunks: warning("skipping invalid patch with no hunks for file %s" % p.source) diff --git a/libs/patches.cmake b/libs/patches.cmake index 64dd98b24..cea5d1ff9 100644 --- a/libs/patches.cmake +++ b/libs/patches.cmake @@ -93,10 +93,11 @@ function(get_version_branch prefix _version _branch) set(tmp_branch ${tmp_branch}_${OPENSSL}) elseif(prefix MATCHES "qt") set(version v${QT}) + set(tmp_branch ${tmp_branch}_${QT}) if(version MATCHES "-rc$") set(version ${version}1) + set(tmp_branch ${tmp_branch}1) endif() - set(tmp_branch ${tmp_branch}_${QT}) endif() set(${_version} "${version}" PARENT_SCOPE) @@ -205,7 +206,7 @@ function(generate_patches) set(component "${dirname}/") endif() - execute_dir("${dirname}" format-patch --no-signature --no-renames --no-binary --src-prefix=x/${component} --dst-prefix=y/${component} -k ${latesttag}..HEAD -o "${patch_dir}") + execute_dir("${dirname}" format-patch --full-index --no-signature --no-renames --no-binary --src-prefix=x/${component} --dst-prefix=y/${component} -k ${latesttag}..HEAD -o "${patch_dir}") rename_patches(${dirname}) else() message(STATUS "Skip patches of ${dirname} and branch ${current_branch}") diff --git a/libs/patches/openssl-0001-Adjust-iOS-target.patch b/libs/patches/openssl-0001-Adjust-iOS-target.patch deleted file mode 100644 index b2ba7f1b0..000000000 --- a/libs/patches/openssl-0001-Adjust-iOS-target.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 89d4eab1163e8542e59c6c486a2546d20940663b Mon Sep 17 00:00:00 2001 -From: Lars Schmertmann -Date: Fri, 12 Feb 2021 13:15:00 +0100 -Subject: Adjust iOS target - ---- - Configurations/15-ios.conf | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git x/Configurations/15-ios.conf y/Configurations/15-ios.conf -index 54d37f63f4..7e411b2e3a 100644 ---- x/Configurations/15-ios.conf -+++ y/Configurations/15-ios.conf -@@ -25,7 +25,7 @@ my %targets = ( - "ios64-xcrun" => { - inherit_from => [ "ios-common" ], - CC => "xcrun -sdk iphoneos cc", -- cflags => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"), -+ cflags => add("-arch arm64 -mios-version-min=11.0 -fno-common"), - bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", - asm_arch => 'aarch64', - perlasm_scheme => "ios64", diff --git a/libs/patches/openssl-0002-android-shlib_variant.patch b/libs/patches/openssl-0001-android-shlib_variant.patch similarity index 82% rename from libs/patches/openssl-0002-android-shlib_variant.patch rename to libs/patches/openssl-0001-android-shlib_variant.patch index d92ed162e..8fb7511ca 100644 --- a/libs/patches/openssl-0002-android-shlib_variant.patch +++ b/libs/patches/openssl-0001-android-shlib_variant.patch @@ -1,4 +1,4 @@ -From 898564ac262e25b8b2aa67d541a819e6986fda62 Mon Sep 17 00:00:00 2001 +From fec417d3241ec474e90a8eba23f91864eb0c8860 Mon Sep 17 00:00:00 2001 From: Lars Schmertmann Date: Tue, 19 Jan 2021 17:07:51 +0100 Subject: android shlib_variant @@ -8,10 +8,10 @@ Subject: android shlib_variant 1 file changed, 4 insertions(+) diff --git x/Configurations/15-android.conf y/Configurations/15-android.conf -index 41ad9223e0..f804aeb11b 100644 +index 1de6b7a91571d7ec22f8549effc5867819663164..3aa2fcdf15ab6b41cdbdceca0778fbdce9c7de6b 100644 --- x/Configurations/15-android.conf +++ y/Configurations/15-android.conf -@@ -225,12 +225,14 @@ my %targets = ( +@@ -226,12 +226,14 @@ my %targets = ( bn_ops => add("RC4_CHAR"), asm_arch => 'armv4', perlasm_scheme => "void", @@ -26,7 +26,7 @@ index 41ad9223e0..f804aeb11b 100644 }, "android-mips" => { -@@ -262,12 +264,14 @@ my %targets = ( +@@ -263,12 +265,14 @@ my %targets = ( asm_arch => 'x86', perlasm_scheme => "android", ex_libs => add(threads("-latomic")), @@ -40,4 +40,4 @@ index 41ad9223e0..f804aeb11b 100644 + shlib_variant => '_x86_64', }, - #################################################################### + "android-riscv64" => { diff --git a/libs/patches/openssl-0002-Harden-BN_GF2m_poly2arr-against-misuse.patch b/libs/patches/openssl-0002-Harden-BN_GF2m_poly2arr-against-misuse.patch new file mode 100644 index 000000000..5c45e147b --- /dev/null +++ b/libs/patches/openssl-0002-Harden-BN_GF2m_poly2arr-against-misuse.patch @@ -0,0 +1,199 @@ +From 080b220bd1cacb498a65b07d937a2fbc26c30f94 Mon Sep 17 00:00:00 2001 +From: Viktor Dukhovni +Date: Thu, 19 Sep 2024 01:02:40 +1000 +Subject: Harden BN_GF2m_poly2arr against misuse. + +The BN_GF2m_poly2arr() function converts characteristic-2 field +(GF_{2^m}) Galois polynomials from a representation as a BIGNUM bitmask, +to a compact array with just the exponents of the non-zero terms. + +These polynomials are then used in BN_GF2m_mod_arr() to perform modular +reduction. A precondition of calling BN_GF2m_mod_arr() is that the +polynomial must have a non-zero constant term (i.e. the array has `0` as +its final element). + +Internally, callers of BN_GF2m_poly2arr() did not verify that +precondition, and binary EC curve parameters with an invalid polynomial +could lead to out of bounds memory reads and writes in BN_GF2m_mod_arr(). + +The precondition is always true for polynomials that arise from the +standard form of EC parameters for characteristic-two fields (X9.62). +See the "Finite Field Identification" section of: + + https://www.itu.int/ITU-T/formal-language/itu-t/x/x894/2018-cor1/ANSI-X9-62.html + +The OpenSSL GF(2^m) code supports only the trinomial and pentanomial +basis X9.62 forms. + +This commit updates BN_GF2m_poly2arr() to return `0` (failure) when +the constant term is zero (i.e. the input bitmask BIGNUM is not odd). + +Additionally, the return value is made unambiguous when there is not +enough space to also pad the array with a final `-1` sentinel value. +The return value is now always the number of elements (including the +final `-1`) that would be filled when the output array is sufficiently +large. Previously the same count was returned both when the array has +just enough room for the final `-1` and when it had only enough space +for non-sentinel values. + +Finally, BN_GF2m_poly2arr() is updated to reject polynomials whose +degree exceeds `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against +CPU exhausition attacks via excessively large inputs. + +The above issues do not arise in processing X.509 certificates. These +generally have EC keys from "named curves", and RFC5840 (Section 2.1.1) +disallows explicit EC parameters. The TLS code in OpenSSL enforces this +constraint only after the certificate is decoded, but, even if explicit +parameters are specified, they are in X9.62 form, which cannot represent +problem values as noted above. + +Initially reported as oss-fuzz issue 71623. + +A closely related issue was earlier reported in +. + +Severity: Low, CVE-2024-9143 + +Reviewed-by: Matt Caswell +Reviewed-by: Bernd Edlinger +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/25639) + +(cherry picked from commit 8e008cb8b23ec7dc75c45a66eeed09c815b11cd2) +(cherry picked from commit c0d3e4d32d2805f49bec30547f225bc4d092e1f4) +--- + crypto/bn/bn_gf2m.c | 28 +++++++++++++++------- + test/ec_internal_test.c | 51 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 71 insertions(+), 8 deletions(-) + +diff --git x/crypto/bn/bn_gf2m.c y/crypto/bn/bn_gf2m.c +index 444c5ca7a37554f24b3d9cca83a330c7b5e1757e..ae7e9d751c29cefa3703b380edbfc0303eca5623 100644 +--- x/crypto/bn/bn_gf2m.c ++++ y/crypto/bn/bn_gf2m.c +@@ -15,6 +15,7 @@ + #include "bn_local.h" + + #ifndef OPENSSL_NO_EC2M ++# include + + /* + * Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should +@@ -1130,16 +1131,26 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + /* + * Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i * + * x^i) into an array of integers corresponding to the bits with non-zero +- * coefficient. Array is terminated with -1. Up to max elements of the array +- * will be filled. Return value is total number of array elements that would +- * be filled if array was large enough. ++ * coefficient. The array is intended to be suitable for use with ++ * `BN_GF2m_mod_arr()`, and so the constant term of the polynomial must not be ++ * zero. This translates to a requirement that the input BIGNUM `a` is odd. ++ * ++ * Given sufficient room, the array is terminated with -1. Up to max elements ++ * of the array will be filled. ++ * ++ * The return value is total number of array elements that would be filled if ++ * array was large enough, including the terminating `-1`. It is `0` when `a` ++ * is not odd or the constant term is zero contrary to requirement. ++ * ++ * The return value is also `0` when the leading exponent exceeds ++ * `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against CPU exhaustion attacks, + */ + int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) + { + int i, j, k = 0; + BN_ULONG mask; + +- if (BN_is_zero(a)) ++ if (!BN_is_odd(a)) + return 0; + + for (i = a->top - 1; i >= 0; i--) { +@@ -1157,12 +1168,13 @@ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) + } + } + +- if (k < max) { ++ if (k > 0 && p[0] > OPENSSL_ECC_MAX_FIELD_BITS) ++ return 0; ++ ++ if (k < max) + p[k] = -1; +- k++; +- } + +- return k; ++ return k + 1; + } + + /* +diff --git x/test/ec_internal_test.c y/test/ec_internal_test.c +index 5076f9894d5b8ab76bdc8311d6bfc326394d0202..92904cfc42b20a28592d661a856dffc4bfe9969b 100644 +--- x/test/ec_internal_test.c ++++ y/test/ec_internal_test.c +@@ -155,6 +155,56 @@ static int field_tests_ecp_mont(void) + } + + #ifndef OPENSSL_NO_EC2M ++/* Test that decoding of invalid GF2m field parameters fails. */ ++static int ec2m_field_sanity(void) ++{ ++ int ret = 0; ++ BN_CTX *ctx = BN_CTX_new(); ++ BIGNUM *p, *a, *b; ++ EC_GROUP *group1 = NULL, *group2 = NULL, *group3 = NULL; ++ ++ TEST_info("Testing GF2m hardening\n"); ++ ++ BN_CTX_start(ctx); ++ p = BN_CTX_get(ctx); ++ a = BN_CTX_get(ctx); ++ if (!TEST_ptr(b = BN_CTX_get(ctx)) ++ || !TEST_true(BN_one(a)) ++ || !TEST_true(BN_one(b))) ++ goto out; ++ ++ /* Even pentanomial value should be rejected */ ++ if (!TEST_true(BN_set_word(p, 0xf2))) ++ goto out; ++ if (!TEST_ptr_null(group1 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) ++ TEST_error("Zero constant term accepted in GF2m polynomial"); ++ ++ /* Odd hexanomial should also be rejected */ ++ if (!TEST_true(BN_set_word(p, 0xf3))) ++ goto out; ++ if (!TEST_ptr_null(group2 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) ++ TEST_error("Hexanomial accepted as GF2m polynomial"); ++ ++ /* Excessive polynomial degree should also be rejected */ ++ if (!TEST_true(BN_set_word(p, 0x71)) ++ || !TEST_true(BN_set_bit(p, OPENSSL_ECC_MAX_FIELD_BITS + 1))) ++ goto out; ++ if (!TEST_ptr_null(group3 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) ++ TEST_error("GF2m polynomial degree > %d accepted", ++ OPENSSL_ECC_MAX_FIELD_BITS); ++ ++ ret = group1 == NULL && group2 == NULL && group3 == NULL; ++ ++ out: ++ EC_GROUP_free(group1); ++ EC_GROUP_free(group2); ++ EC_GROUP_free(group3); ++ BN_CTX_end(ctx); ++ BN_CTX_free(ctx); ++ ++ return ret; ++} ++ + /* test EC_GF2m_simple_method directly */ + static int field_tests_ec2_simple(void) + { +@@ -443,6 +493,7 @@ int setup_tests(void) + ADD_TEST(field_tests_ecp_simple); + ADD_TEST(field_tests_ecp_mont); + #ifndef OPENSSL_NO_EC2M ++ ADD_TEST(ec2m_field_sanity); + ADD_TEST(field_tests_ec2_simple); + #endif + ADD_ALL_TESTS(field_tests_default, crv_len); diff --git a/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch b/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch index a4b9447bb..996f6b7f9 100644 --- a/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch +++ b/libs/patches/qtbase-0001-Revert-Fix-usage-of-logging-category-on-Android.patch @@ -1,4 +1,4 @@ -From 40410b9e2ba5d02b457bb37fc90663585573ca53 Mon Sep 17 00:00:00 2001 +From 3d84a5d1671aa3b7143c445ef7c8f6e62569c7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Mon, 25 Jul 2022 17:08:54 +0200 Subject: Revert "Fix usage of logging category on Android" @@ -11,10 +11,10 @@ Change-Id: If19a9d615e01d61c79955cda4789ba1646520ee1 1 file changed, 1 insertion(+), 8 deletions(-) diff --git x/qtbase/src/corelib/global/qlogging.cpp y/qtbase/src/corelib/global/qlogging.cpp -index 7e708c9c41..96c3bc5dc6 100644 +index a511af32ee36dcbaadc902f19c12f07e4f928c39..f94d1cd72857e02b9aa02f69ee5973f386a256e8 100644 --- x/qtbase/src/corelib/global/qlogging.cpp +++ y/qtbase/src/corelib/global/qlogging.cpp -@@ -1593,10 +1593,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con +@@ -1562,10 +1562,7 @@ static QString formatLogMessage(QtMsgType type, const QMessageLogContext &contex } else if (token == messageTokenC) { message.append(str); } else if (token == categoryTokenC) { @@ -25,7 +25,7 @@ index 7e708c9c41..96c3bc5dc6 100644 } else if (token == typeTokenC) { switch (type) { case QtDebugMsg: message.append("debug"_L1); break; -@@ -1844,11 +1841,7 @@ static bool android_default_message_handler(QtMsgType type, +@@ -1815,11 +1812,7 @@ static bool android_default_message_handler(QtMsgType type, break; }; diff --git a/libs/patches/qtbase-0005-Do-not-override-OPENSSL_API_COMPAT.patch b/libs/patches/qtbase-0002-Do-not-override-OPENSSL_API_COMPAT.patch similarity index 82% rename from libs/patches/qtbase-0005-Do-not-override-OPENSSL_API_COMPAT.patch rename to libs/patches/qtbase-0002-Do-not-override-OPENSSL_API_COMPAT.patch index c43c406dc..583147b6d 100644 --- a/libs/patches/qtbase-0005-Do-not-override-OPENSSL_API_COMPAT.patch +++ b/libs/patches/qtbase-0002-Do-not-override-OPENSSL_API_COMPAT.patch @@ -1,4 +1,4 @@ -From 1d935cfe1de1a015561ee8755c67ec9c8a1bd121 Mon Sep 17 00:00:00 2001 +From bae9825a4ca2c021e75adc9c82f821c37eb50ad5 Mon Sep 17 00:00:00 2001 From: Klitzing Date: Thu, 31 Aug 2023 13:19:55 +0200 Subject: Do not override OPENSSL_API_COMPAT @@ -11,7 +11,7 @@ Change-Id: Ied55e3d6ebd90fbbecb8c4d8d1638b1de3ba6969 1 file changed, 2 deletions(-) diff --git x/qtbase/src/plugins/tls/openssl/CMakeLists.txt y/qtbase/src/plugins/tls/openssl/CMakeLists.txt -index 0e0a7a1552..e176bbf9d5 100644 +index 0e0a7a1552dc6ef7e1b5847d5685e8b653806364..e176bbf9d5471ffc977d3a6344998f5c3274de5a 100644 --- x/qtbase/src/plugins/tls/openssl/CMakeLists.txt +++ y/qtbase/src/plugins/tls/openssl/CMakeLists.txt @@ -20,8 +20,6 @@ qt_internal_add_plugin(QTlsBackendOpenSSLPlugin diff --git a/libs/patches/qtbase-0002-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch b/libs/patches/qtbase-0002-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch deleted file mode 100644 index 26a28e62b..000000000 --- a/libs/patches/qtbase-0002-Fix-warning-in-q20algorithm.h-when-xcodebuild-is-use.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0fa22a4be5abda44d34cf7c5d0352378c2f9fd54 Mon Sep 17 00:00:00 2001 -From: Lars Schmertmann -Date: Mon, 9 Jan 2023 06:54:53 +0100 -Subject: Fix warning in q20algorithm.h when xcodebuild is used - -q20algorithm.h:150:20: error: unused function template 'operator()' -q20algorithm.h:163:20: error: unused function template 'operator()' -q20algorithm.h:176:20: error: unused function template 'operator()' - -Fixes: QTBUG-109874 -Change-Id: If5ccbfffd0b6a53f73f221b45033dab7e4775d89 ---- - src/corelib/global/q20algorithm.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git x/qtbase/src/corelib/global/q20algorithm.h y/qtbase/src/corelib/global/q20algorithm.h -index f670a5dbee..24d801b2cd 100644 ---- x/qtbase/src/corelib/global/q20algorithm.h -+++ y/qtbase/src/corelib/global/q20algorithm.h -@@ -147,7 +147,7 @@ using std::ranges::none_of; - [[maybe_unused]] inline constexpr struct { // Niebloid - template -- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const -+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const - { - while (first != last) { - if (std::invoke(pred, std::invoke(proj, *first))) -@@ -160,7 +160,7 @@ using std::ranges::none_of; - [[maybe_unused]] inline constexpr struct { // Niebloid - template -- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const -+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const - { - while (first != last) { - if (!std::invoke(pred, std::invoke(proj, *first))) -@@ -173,7 +173,7 @@ using std::ranges::none_of; - [[maybe_unused]] inline constexpr struct { // Niebloid - template -- constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const -+ [[maybe_unused]] constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const - { - while (first != last) { - if (std::invoke(pred, std::invoke(proj, *first))) diff --git a/libs/patches/qtbase-0003-Enable-frameworks-by-default-for-shared-library-buil.patch b/libs/patches/qtbase-0003-Enable-frameworks-by-default-for-shared-library-buil.patch new file mode 100644 index 000000000..359377221 --- /dev/null +++ b/libs/patches/qtbase-0003-Enable-frameworks-by-default-for-shared-library-buil.patch @@ -0,0 +1,52 @@ +From 6d8445072c9223f721c34031233e0404c283f2a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= +Date: Mon, 12 Feb 2024 11:57:34 +0100 +Subject: Enable frameworks by default for shared library builds on Apple + platforms + +Many modern features of the Apple application build and packaging pipeline +require that the libraries are shipped as frameworks, so that they can +embed resources (privacy manifest e.g.), be signed, and have their own +Info.plist. + +We build and ship our binary packages already as frameworks, and it has +been the default for release builds for a while. Let's enable it for +debug builds as well, so that developers are testing what we ship +(debug is the default for -developer-build). + +The error about debug builds not being compatible with frameworks has +been removed, as this works fine in practice. With CMake we don't add +a '_debug' suffix to the libraries unconditionally for debug builds. + +Change-Id: I373b982affd8cf70b215d4a92225467ff1037fe8 +Reviewed-by: Alexandru Croitor +(cherry picked from commit fee15182949e88682131399c50b679be83a75385) +--- + configure.cmake | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git x/qtbase/configure.cmake y/qtbase/configure.cmake +index 08766d94d0a43b5443bd2549bc3f630c1f6bed55..f84254e0dc72ec269f6b70e81078d5eb8a55a906 100644 +--- x/qtbase/configure.cmake ++++ y/qtbase/configure.cmake +@@ -577,7 +577,7 @@ qt_feature("headersclean" + qt_feature_config("headersclean" QMAKE_PRIVATE_CONFIG) + qt_feature("framework" PUBLIC + LABEL "Build Apple Frameworks" +- CONDITION APPLE AND BUILD_SHARED_LIBS AND NOT CMAKE_BUILD_TYPE STREQUAL Debug ++ CONDITION APPLE AND BUILD_SHARED_LIBS + ) + qt_feature_definition("framework" "QT_MAC_FRAMEWORK_BUILD") + qt_feature_config("framework" QMAKE_PUBLIC_QT_CONFIG +@@ -1241,11 +1241,6 @@ qt_configure_add_report_entry( + MESSAGE "-debug-and-release is only supported on Darwin and Windows platforms. Qt can be built in release mode with separate debug information, so -debug-and-release is no longer necessary." + CONDITION INPUT_debug_and_release STREQUAL 'yes' AND NOT APPLE AND NOT WIN32 + ) +-qt_configure_add_report_entry( +- TYPE ERROR +- MESSAGE "debug-only framework builds are not supported. Configure with -no-framework if you want a pure debug build." +- CONDITION QT_FEATURE_framework AND QT_FEATURE_debug AND NOT QT_FEATURE_debug_and_release +-) + qt_configure_add_report_entry( + TYPE ERROR + MESSAGE "Static builds don't support RPATH" diff --git a/libs/patches/qtbase-0003-Revert-iOS-Don-t-invalidate-a11y-whenever-UI-element.patch b/libs/patches/qtbase-0003-Revert-iOS-Don-t-invalidate-a11y-whenever-UI-element.patch deleted file mode 100644 index 988fe5d38..000000000 --- a/libs/patches/qtbase-0003-Revert-iOS-Don-t-invalidate-a11y-whenever-UI-element.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 525b1bd08f9805685134f6f2272edff80fe4b023 Mon Sep 17 00:00:00 2001 -From: Andre Klitzing -Date: Mon, 24 Jul 2023 16:13:12 +0200 -Subject: Revert "iOS: Don't invalidate a11y whenever UI elements are added or - removed" - -This reverts commit 6eefbf74149164eac316cea59a00b45f70976ad2. ---- - .../platforms/ios/qiosplatformaccessibility.mm | 17 ++++------------- - src/plugins/platforms/ios/qioswindow.mm | 1 - - .../platforms/ios/quiview_accessibility.mm | 1 + - 3 files changed, 5 insertions(+), 14 deletions(-) - -diff --git x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm -index f22782fb04..d54b7db57a 100644 ---- x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm -+++ y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm -@@ -25,6 +25,8 @@ void invalidateCache(QAccessibleInterface *iface) - // This will invalidate everything regardless of what window the - // interface belonged to. We might want to revisit this strategy later. - // (Therefore this function still takes the interface as argument) -+ // It is also responsible for the bug that focus gets temporary lost -+ // when items get added or removed from the screen - foreach (QWindow *win, QGuiApplication::topLevelWindows()) { - if (win && win->handle()) { - QT_PREPEND_NAMESPACE(QIOSWindow) *window = static_cast(win->handle()); -@@ -36,25 +38,14 @@ void invalidateCache(QAccessibleInterface *iface) - - void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) - { -- auto *accessibleInterface = event->accessibleInterface(); -- if (!isActive() || !accessibleInterface) -+ if (!isActive() || !event->accessibleInterface()) - return; - switch (event->type()) { - case QAccessible::ObjectCreated: - case QAccessible::ObjectShow: - case QAccessible::ObjectHide: - case QAccessible::ObjectDestroyed: -- invalidateCache(accessibleInterface); -- switch (accessibleInterface->role()) { -- case QAccessible::Window: -- case QAccessible::Dialog: -- // Bigger changes to the UI require a full reset of VoiceOver -- UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); -- break; -- default: -- // While smaller changes can be handled by re-reading the layout -- UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); -- } -+ invalidateCache(event->accessibleInterface()); - break; - default: - break; -diff --git x/qtbase/src/plugins/platforms/ios/qioswindow.mm y/qtbase/src/plugins/platforms/ios/qioswindow.mm -index 8de094533b..99f9e38846 100644 ---- x/qtbase/src/plugins/platforms/ios/qioswindow.mm -+++ y/qtbase/src/plugins/platforms/ios/qioswindow.mm -@@ -75,7 +75,6 @@ QIOSWindow::~QIOSWindow() - [m_view touchesCancelled:[NSSet set] withEvent:0]; - - clearAccessibleCache(); -- - m_view.platformWindow = 0; - [m_view removeFromSuperview]; - [m_view release]; -diff --git x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm -index 04e1f8cfb3..366141ef81 100644 ---- x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm -+++ y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm -@@ -54,6 +54,7 @@ - - (void)clearAccessibleCache - { - [m_accessibleElements removeAllObjects]; -+ UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @""); - } - - // this is a container, returning yes here means the functions below will never be called diff --git a/libs/patches/qtbase-0004-Fix-living-QLibProxyWrapper-after-shutdown-of-QCoreA.patch b/libs/patches/qtbase-0004-Fix-living-QLibProxyWrapper-after-shutdown-of-QCoreA.patch deleted file mode 100644 index 3586ddbcc..000000000 --- a/libs/patches/qtbase-0004-Fix-living-QLibProxyWrapper-after-shutdown-of-QCoreA.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 496b958b6c0026a681a9ee8871894a079dc2ea5c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= -Date: Fri, 18 Aug 2023 14:32:57 +0200 -Subject: Fix living QLibProxyWrapper after shutdown of QCoreApplication - -Pick-to: 6.6 6.5 -Task-number: QTBUG-84234 -Change-Id: I8f5e2947b6529a0a8871d040050205934ee60354 ---- - src/network/kernel/qnetworkproxy_libproxy.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git x/qtbase/src/network/kernel/qnetworkproxy_libproxy.cpp y/qtbase/src/network/kernel/qnetworkproxy_libproxy.cpp -index 46066b86f7..6de7a7fb76 100644 ---- x/qtbase/src/network/kernel/qnetworkproxy_libproxy.cpp -+++ y/qtbase/src/network/kernel/qnetworkproxy_libproxy.cpp -@@ -72,7 +72,7 @@ private: - Data *request; - }; - --Q_GLOBAL_STATIC(QLibProxyWrapper, libProxyWrapper); -+Q_APPLICATION_STATIC(QLibProxyWrapper, libProxyWrapper) - - QLibProxyWrapper::QLibProxyWrapper() - { diff --git a/libs/patches/qtbase-0004-cmake-Allow-static-library-framework-builds-for-macO.patch b/libs/patches/qtbase-0004-cmake-Allow-static-library-framework-builds-for-macO.patch new file mode 100644 index 000000000..0def38440 --- /dev/null +++ b/libs/patches/qtbase-0004-cmake-Allow-static-library-framework-builds-for-macO.patch @@ -0,0 +1,44 @@ +From f5ecf2b064c0d71cbec385a3322ecdaa7dd12cf2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= +Date: Mon, 12 Feb 2024 18:26:16 +0100 +Subject: cmake: Allow static library framework builds for macOS and iOS + +Frameworks on Apple systems have traditionally been wrappers around +dynamic libraries (with headers and other resources bundled alongside +the library), but nowadays it's fully supported to have frameworks +with static libraries inside them. + +Enabling this allows us to build Qt for iOS statically, but as +frameworks, which allows us to include privacy manifests for the +Qt libraries in the frameworks. + +At build time Xcode will link the static library into the application, +as normal, so nothing changes there. If the user then chooses to +embed the Qt frameworks via the Xcode UI, the build system will +not copy the static libraries inside the frameworks, but will +copy the privacy manifest and other resources, which in turn +allows Xcode to generate a privacy report for the application +as a whole. + +Task-number: QTBUG-114319 +Change-Id: Ibc8c70a97d288e27811eaedd242613fa206617e5 +Reviewed-by: Alexandru Croitor +(cherry picked from commit 291817b0bf3f351843b0c1d0de237dc8df5c0fa5) +--- + configure.cmake | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git x/qtbase/configure.cmake y/qtbase/configure.cmake +index f84254e0dc72ec269f6b70e81078d5eb8a55a906..cc0718448980566fd39f9287ea6267e82c24f3fa 100644 +--- x/qtbase/configure.cmake ++++ y/qtbase/configure.cmake +@@ -577,7 +577,8 @@ qt_feature("headersclean" + qt_feature_config("headersclean" QMAKE_PRIVATE_CONFIG) + qt_feature("framework" PUBLIC + LABEL "Build Apple Frameworks" +- CONDITION APPLE AND BUILD_SHARED_LIBS ++ AUTODETECT BUILD_SHARED_LIBS ++ CONDITION APPLE + ) + qt_feature_definition("framework" "QT_MAC_FRAMEWORK_BUILD") + qt_feature_config("framework" QMAKE_PUBLIC_QT_CONFIG diff --git a/libs/patches/qtbase-0005-cmake-Generate-Apple-privacy-manifest-files-for-Qt-m.patch b/libs/patches/qtbase-0005-cmake-Generate-Apple-privacy-manifest-files-for-Qt-m.patch new file mode 100644 index 000000000..1ef140a93 --- /dev/null +++ b/libs/patches/qtbase-0005-cmake-Generate-Apple-privacy-manifest-files-for-Qt-m.patch @@ -0,0 +1,300 @@ +From 00bc861d4a715afb5348a04463c58ef4d9d1f111 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= +Date: Mon, 12 Feb 2024 15:19:56 +0100 +Subject: cmake: Generate Apple privacy manifest files for Qt modules + +The default manifest is a minimal file that claims NSPrivacyTracking +false, along with an empty list of NSPrivacyTrackingDomains and +NSPrivacyCollectedDataTypes, as Qt does not generally do user tracking. + +Modules can override the default manifest by setting the +PRIVACY_MANIFEST target property, specifying a custom privacy +manifest. + +The NSPrivacyAccessedAPITypes key is only required for iOS for now. +Even though we don't build Qt for iOS as frameworks yet, which is +required to embed a privacy manifest, we include the keys for the +APIs we known we use. + +Task-number: QTBUG-114319 +Change-Id: I654bb52b98ee963adeeb744b35f3a1c2a1270969 +Reviewed-by: Alexandru Croitor +(cherry picked from commit 9cca899574ea44cd9c4f2be096e8b7a70f6280f2) +--- + cmake/QtBaseGlobalTargets.cmake | 10 ++++++ + cmake/QtBuildHelpers.cmake | 4 +++ + cmake/QtModuleHelpers.cmake | 17 ++++++++++ + cmake/ios/PrivacyInfo.xcprivacy | 14 +++++++++ + cmake/macos/PrivacyInfo.xcprivacy | 12 +++++++ + src/corelib/CMakeLists.txt | 5 +++ + .../platform/ios/PrivacyInfo.xcprivacy | 31 +++++++++++++++++++ + src/gui/CMakeLists.txt | 5 +++ + src/gui/platform/ios/PrivacyInfo.xcprivacy | 23 ++++++++++++++ + src/widgets/CMakeLists.txt | 5 +++ + .../platform/ios/PrivacyInfo.xcprivacy | 25 +++++++++++++++ + 11 files changed, 151 insertions(+) + create mode 100644 cmake/ios/PrivacyInfo.xcprivacy + create mode 100644 cmake/macos/PrivacyInfo.xcprivacy + create mode 100644 src/corelib/platform/ios/PrivacyInfo.xcprivacy + create mode 100644 src/gui/platform/ios/PrivacyInfo.xcprivacy + create mode 100644 src/widgets/platform/ios/PrivacyInfo.xcprivacy + +diff --git x/qtbase/cmake/QtBaseGlobalTargets.cmake y/qtbase/cmake/QtBaseGlobalTargets.cmake +index 9a18cdd8a2b0aecd087be129ea469cba1a29d7f1..e6f6b474df3f851db27db3d99dc7527f07c34c45 100644 +--- x/qtbase/cmake/QtBaseGlobalTargets.cmake ++++ y/qtbase/cmake/QtBaseGlobalTargets.cmake +@@ -328,6 +328,7 @@ if(APPLE) + set(platform_shortname "ios") + endif() + ++ # Info.plist + qt_copy_or_install(FILES "cmake/${platform_shortname}/Info.plist.app.in" + DESTINATION "${__GlobalConfig_install_dir}/${platform_shortname}" + ) +@@ -336,6 +337,15 @@ if(APPLE) + DESTINATION "${__GlobalConfig_build_dir}/${platform_shortname}" + ) + ++ # Privacy manifest ++ qt_copy_or_install(FILES "cmake/${platform_shortname}/PrivacyInfo.xcprivacy" ++ DESTINATION "${__GlobalConfig_install_dir}/${platform_shortname}" ++ ) ++ # For examples built as part of prefix build before install ++ file(COPY "cmake/${platform_shortname}/PrivacyInfo.xcprivacy" ++ DESTINATION "${__GlobalConfig_build_dir}/${platform_shortname}" ++ ) ++ + if(IOS) + qt_copy_or_install(FILES "cmake/ios/LaunchScreen.storyboard" + DESTINATION "${__GlobalConfig_install_dir}/ios" +diff --git x/qtbase/cmake/QtBuildHelpers.cmake y/qtbase/cmake/QtBuildHelpers.cmake +index 2c1b13486735093178691e31ec804882c19d3474..48adc617121511baba16f50d3c3439d046754ce0 100644 +--- x/qtbase/cmake/QtBuildHelpers.cmake ++++ y/qtbase/cmake/QtBuildHelpers.cmake +@@ -132,6 +132,10 @@ macro(qt_internal_set_apple_archiver_flags) + endif() + endmacro() + ++macro(qt_internal_set_apple_privacy_manifest target manifest_file) ++ set_target_properties(${target} PROPERTIES _qt_privacy_manifest "${manifest_file}") ++endmacro() ++ + macro(qt_internal_set_debug_extend_target) + option(QT_CMAKE_DEBUG_EXTEND_TARGET "Debug extend_target calls in Qt's build system" OFF) + endmacro() +diff --git x/qtbase/cmake/QtModuleHelpers.cmake y/qtbase/cmake/QtModuleHelpers.cmake +index 45e59cf642319fa84f5eccbb2eeb81e2f3a83740..9eaf058865134dad81f2005c1eab64bb16b03562 100644 +--- x/qtbase/cmake/QtModuleHelpers.cmake ++++ y/qtbase/cmake/QtModuleHelpers.cmake +@@ -904,6 +904,22 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") + qt_add_list_file_finalizer(qt_finalize_module ${target} ${arg_INTERNAL_MODULE} ${arg_NO_PRIVATE_MODULE}) + endfunction() + ++function(qt_internal_apply_apple_privacy_manifest target) ++ if(APPLE) ++ # Privacy manifest ++ get_target_property(is_framework ${target} FRAMEWORK) ++ if(is_framework) ++ get_target_property(privacy_manifest ${target} _qt_privacy_manifest) ++ if(NOT privacy_manifest) ++ set(privacy_manifest ++ "${__qt_internal_cmake_apple_support_files_path}/PrivacyInfo.xcprivacy") ++ endif() ++ target_sources("${target}" PRIVATE "${privacy_manifest}") ++ set_property(TARGET "${target}" APPEND PROPERTY RESOURCE "${privacy_manifest}") ++ endif() ++ endif() ++endfunction() ++ + function(qt_finalize_module target) + qt_internal_collect_module_headers(module_headers ${target}) + +@@ -927,6 +943,7 @@ function(qt_finalize_module target) + qt_generate_prl_file(${target} "${INSTALL_LIBDIR}") + qt_generate_module_pri_file("${target}" ${ARGN}) + qt_internal_generate_pkg_config_file(${target}) ++ qt_internal_apply_apple_privacy_manifest(${target}) + endfunction() + + # Get a set of Qt module related values based on the target. +diff --git x/qtbase/cmake/ios/PrivacyInfo.xcprivacy y/qtbase/cmake/ios/PrivacyInfo.xcprivacy +new file mode 100644 +index 0000000000000000000000000000000000000000..d75908da05846c6174fc8c39836b76669724e4da +--- /dev/null ++++ y/qtbase/cmake/ios/PrivacyInfo.xcprivacy +@@ -0,0 +1,14 @@ ++ ++ ++ ++ ++ NSPrivacyTracking ++ ++ NSPrivacyCollectedDataTypes ++ ++ NSPrivacyTrackingDomains ++ ++ NSPrivacyAccessedAPITypes ++ ++ ++ +diff --git x/qtbase/cmake/macos/PrivacyInfo.xcprivacy y/qtbase/cmake/macos/PrivacyInfo.xcprivacy +new file mode 100644 +index 0000000000000000000000000000000000000000..96aff954eaa2799537b124df20d16e2752dbb56b +--- /dev/null ++++ y/qtbase/cmake/macos/PrivacyInfo.xcprivacy +@@ -0,0 +1,12 @@ ++ ++ ++ ++ ++ NSPrivacyTracking ++ ++ NSPrivacyCollectedDataTypes ++ ++ NSPrivacyTrackingDomains ++ ++ ++ +diff --git x/qtbase/src/corelib/CMakeLists.txt y/qtbase/src/corelib/CMakeLists.txt +index bbe8ba8489044b18210265227cde1a1cfe3efb1e..19da4f75f4284837416980a742496ee6d335db64 100644 +--- x/qtbase/src/corelib/CMakeLists.txt ++++ y/qtbase/src/corelib/CMakeLists.txt +@@ -1446,6 +1446,11 @@ if(APPLE AND QT_FEATURE_framework AND QT_FEATURE_separate_debug_info) + ) + endif() + ++if(IOS) ++ qt_internal_set_apple_privacy_manifest(Core ++ "${CMAKE_CURRENT_SOURCE_DIR}/platform/ios/PrivacyInfo.xcprivacy") ++endif() ++ + set(linker_script_contents "") + if (QT_NAMESPACE STREQUAL "") + set(tag_symbol "qt_version_tag") +diff --git x/qtbase/src/corelib/platform/ios/PrivacyInfo.xcprivacy y/qtbase/src/corelib/platform/ios/PrivacyInfo.xcprivacy +new file mode 100644 +index 0000000000000000000000000000000000000000..5f84a229a57f8c48be787d148d2266e7f1abe20a +--- /dev/null ++++ y/qtbase/src/corelib/platform/ios/PrivacyInfo.xcprivacy +@@ -0,0 +1,31 @@ ++ ++ ++ ++ ++ NSPrivacyTracking ++ ++ NSPrivacyCollectedDataTypes ++ ++ NSPrivacyTrackingDomains ++ ++ NSPrivacyAccessedAPITypes ++ ++ ++ NSPrivacyAccessedAPIType ++ NSPrivacyAccessedAPICategoryFileTimestamp ++ NSPrivacyAccessedAPITypeReasons ++ ++ 0A2A.1 ++ ++ ++ ++ NSPrivacyAccessedAPIType ++ NSPrivacyAccessedAPICategoryDiskSpace ++ NSPrivacyAccessedAPITypeReasons ++ ++ 85F4.1 ++ ++ ++ ++ ++ +diff --git x/qtbase/src/gui/CMakeLists.txt y/qtbase/src/gui/CMakeLists.txt +index b6f74369ae5f4f7f71cc24c2f4bf938613a422ec..e876d351d12ac512a38695a5ac250426a1420352 100644 +--- x/qtbase/src/gui/CMakeLists.txt ++++ y/qtbase/src/gui/CMakeLists.txt +@@ -1039,4 +1039,9 @@ qt_internal_add_docs(Gui + doc/qtgui.qdocconf + ) + ++if(IOS) ++ qt_internal_set_apple_privacy_manifest(Gui ++ "${CMAKE_CURRENT_SOURCE_DIR}/platform/ios/PrivacyInfo.xcprivacy") ++endif() ++ + qt_internal_add_optimize_full_flags() +diff --git x/qtbase/src/gui/platform/ios/PrivacyInfo.xcprivacy y/qtbase/src/gui/platform/ios/PrivacyInfo.xcprivacy +new file mode 100644 +index 0000000000000000000000000000000000000000..bde2b167c75a82d933f75194bc0fbae8e9b840bc +--- /dev/null ++++ y/qtbase/src/gui/platform/ios/PrivacyInfo.xcprivacy +@@ -0,0 +1,23 @@ ++ ++ ++ ++ ++ NSPrivacyTracking ++ ++ NSPrivacyCollectedDataTypes ++ ++ NSPrivacyTrackingDomains ++ ++ NSPrivacyAccessedAPITypes ++ ++ ++ NSPrivacyAccessedAPIType ++ NSPrivacyAccessedAPICategorySystemBootTime ++ NSPrivacyAccessedAPITypeReasons ++ ++ 35F9.1 ++ ++ ++ ++ ++ +diff --git x/qtbase/src/widgets/CMakeLists.txt y/qtbase/src/widgets/CMakeLists.txt +index f77117dc563205c7faae5fa57fc9845ec07c5baa..2ba8e4719a7bdf4bb9de636bb591b1d5abcfd286 100644 +--- x/qtbase/src/widgets/CMakeLists.txt ++++ y/qtbase/src/widgets/CMakeLists.txt +@@ -911,6 +911,11 @@ qt_internal_add_docs(Widgets + doc/qtwidgets.qdocconf + ) + ++if(IOS) ++ qt_internal_set_apple_privacy_manifest(Widgets ++ "${CMAKE_CURRENT_SOURCE_DIR}/platform/ios/PrivacyInfo.xcprivacy") ++endif() ++ + # include the snippet projects for developer-builds + if(QT_FEATURE_private_tests) + add_subdirectory(doc/snippets/customviewstyle) +diff --git x/qtbase/src/widgets/platform/ios/PrivacyInfo.xcprivacy y/qtbase/src/widgets/platform/ios/PrivacyInfo.xcprivacy +new file mode 100644 +index 0000000000000000000000000000000000000000..819b868e1a739c85fff02d4a42817d035580497d +--- /dev/null ++++ y/qtbase/src/widgets/platform/ios/PrivacyInfo.xcprivacy +@@ -0,0 +1,25 @@ ++ ++ ++ ++ ++ NSPrivacyTracking ++ ++ NSPrivacyCollectedDataTypes ++ ++ NSPrivacyTrackingDomains ++ ++ NSPrivacyAccessedAPITypes ++ ++ ++ NSPrivacyAccessedAPIType ++ NSPrivacyAccessedAPICategoryFileTimestamp ++ NSPrivacyAccessedAPITypeReasons ++ ++ DDA9.1 ++ C617.1 ++ 3B52.1 ++ ++ ++ ++ ++ diff --git a/libs/patches/qtbase-0006-Android-Remove-check-for-screen-window-ascpect-ratio.patch b/libs/patches/qtbase-0006-Android-Remove-check-for-screen-window-ascpect-ratio.patch new file mode 100644 index 000000000..1f52ab7f1 --- /dev/null +++ b/libs/patches/qtbase-0006-Android-Remove-check-for-screen-window-ascpect-ratio.patch @@ -0,0 +1,54 @@ +From 4f855a2b7b7d779a8a81ba4723bd238620f49386 Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Thu, 6 Jun 2024 11:30:27 +0200 +Subject: Android: Remove check for screen/window ascpect ratio mismatch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The check was re-introduced in 7a9bc220c70745cd3689d51cd131efde86f078d7 +and moved to QtRootLayout in 6ff88f97a6d24d1098583421161f8f903f9dafde. +It introduces an issue where the resizing of the application window does +not work if the its aspect ratio is different from the screen's aspect +ratio. + +Fixes: QTBUG-126122 +Pick-to: 6.7.2 6.7 6.8 +Change-Id: Id6d26b247b9ca7a8d0e89e1fdea2d77db12a6cfe +Reviewed-by: Tinja Paavoseppä +Reviewed-by: Assam Boudjelthia +(cherry picked from commit a6b78e6f4dbbf688fc0b1d1487b86890b149d323) +--- + .../qtproject/qt/android/QtRootLayout.java | 19 ------------------- + 1 file changed, 19 deletions(-) + +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java +index 3dae587a7102108fc50d09840a3887ee3df14c94..ed0f64cca9c81aa1072dee451daa150c345e31f2 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java +@@ -50,25 +50,6 @@ public class QtRootLayout extends QtLayout + if (activity == null) + return; + +- DisplayMetrics realMetrics = new DisplayMetrics(); +- Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) +- ? activity.getWindowManager().getDefaultDisplay() +- : activity.getDisplay(); +- +- if (display == null) +- return; +- +- display.getRealMetrics(realMetrics); +- if ((realMetrics.widthPixels > realMetrics.heightPixels) != (w > h)) { +- // This is an intermediate state during display rotation. +- // The new size is still reported for old orientation, while +- // realMetrics contain sizes for new orientation. Setting +- // such parameters will produce inconsistent results, so +- // we just skip them. +- // We will have another onSizeChanged() with normal values +- // a bit later. +- return; +- } + QtDisplayManager.setApplicationDisplayMetrics(activity, w, h); + QtDisplayManager.handleOrientationChanges(activity); + } diff --git a/libs/patches/qtbase-0006-xkb-fix-build-with-libxkbcommon-1.6.0-and-later.patch b/libs/patches/qtbase-0006-xkb-fix-build-with-libxkbcommon-1.6.0-and-later.patch deleted file mode 100644 index eb4425f18..000000000 --- a/libs/patches/qtbase-0006-xkb-fix-build-with-libxkbcommon-1.6.0-and-later.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 62ae219de264975c0f7e7546b702471d70af4b40 Mon Sep 17 00:00:00 2001 -From: Liang Qi -Date: Tue, 10 Oct 2023 14:08:48 +0200 -Subject: xkb: fix build with libxkbcommon 1.6.0 and later -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A few XKB_KEY_dead_* defines got removed from 1.6.0. See also -https://github.com/xkbcommon/libxkbcommon/blob/6073565903488cb5b9a8d37fdc4a7c2f9d7ad04d/NEWS#L9-L14 -https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/70/diffs?commit_id=cb44799b72f611eb4c9d7cc185bc3b09e070be08 - -Pick-to: 6.6 6.5 6.2 5.15 -Fixes: QTBUG-117950 -Change-Id: I55861868f2bb29c553d68365fa9b9b6ed01c9aea -Reviewed-by: Tor Arne Vestbø -(cherry picked from commit 8af35d27e8f02bbb99aef4ac495ed406e50e3cca) ---- - src/gui/platform/unix/qxkbcommon.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git x/qtbase/src/gui/platform/unix/qxkbcommon.cpp y/qtbase/src/gui/platform/unix/qxkbcommon.cpp -index fc014b38e2..0de9e98fc7 100644 ---- x/qtbase/src/gui/platform/unix/qxkbcommon.cpp -+++ y/qtbase/src/gui/platform/unix/qxkbcommon.cpp -@@ -239,10 +239,14 @@ static constexpr const auto KeyTbl = qMakeArray( - Xkb2Qt, - Xkb2Qt, - Xkb2Qt, -+/* The following four XKB_KEY_dead keys got removed in libxkbcommon 1.6.0 -+ The define check is kind of version check here. */ -+#ifdef XKB_KEY_dead_lowline - Xkb2Qt, - Xkb2Qt, - Xkb2Qt, - Xkb2Qt, -+#endif - - // Special keys from X.org - This include multimedia keys, - // wireless/bluetooth/uwb keys, special launcher keys, etc. diff --git a/libs/patches/qtbase-0007-Android-restart-whole-app-if-the-activity-was-restar.patch b/libs/patches/qtbase-0007-Android-restart-whole-app-if-the-activity-was-restar.patch new file mode 100644 index 000000000..cd61f29af --- /dev/null +++ b/libs/patches/qtbase-0007-Android-restart-whole-app-if-the-activity-was-restar.patch @@ -0,0 +1,139 @@ +From 3d335f3c8e554512c04c5e727c2d04a93efa678a Mon Sep 17 00:00:00 2001 +From: Assam Boudjelthia +Date: Wed, 12 Jun 2024 13:05:16 +0300 +Subject: Android: restart whole app if the activity was restarted +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the Activity restart path is run while m_layout is null, +it would lead to a NullPointerException when trying to +access m_layout. Moreover, the code here doesn't make sense, +as m_layout.getParent() should probably be only done when +super.updateActivityAfterRestart() returns true because if +it returns false, the app will be restarted anyway. + +Testing the restarting behavior of the Activity, it seems +that the code code doesn't really work in bringing the app +to a usable state after an activity restart, and this code +path should be re-evaluated. Thus, I'm simplifying the logic +to only restart the whole app, and later figure out a way to +do a proper smooth transition instead. + +Fixes: QTBUG-124786 +Pick-to: 6.8 6.7 +Change-Id: I79f0c53c815bf71c831d0b930f358c9fd820a2d4 +Reviewed-by: Tinja Paavoseppä +(cherry picked from commit 7602f71aa6cd10ff1b16d154fa967c8fce8e8d0a) +--- + .../qtproject/qt/android/QtActivityBase.java | 28 +++++++++---------- + .../qt/android/QtActivityDelegate.java | 15 ---------- + .../qt/android/QtActivityDelegateBase.java | 15 ---------- + 3 files changed, 14 insertions(+), 44 deletions(-) + +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +index 7b13331d9d293ebaecd29fd5a2f1b4cce98bcf17..04e7d6fd50acda89b3d92167c9aa9db97991a002 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +@@ -63,25 +63,19 @@ public class QtActivityBase extends Activity + m_applicationParams += params; + } + +- private void handleActivityRestart() { +- if (QtNative.getStateDetails().isStarted) { +- boolean updated = m_delegate.updateActivityAfterRestart(this); +- if (!updated) { +- // could not update the activity so restart the application +- Intent intent = Intent.makeRestartActivityTask(getComponentName()); +- startActivity(intent); +- QtNative.quitApp(); +- Runtime.getRuntime().exit(0); +- } +- } +- } +- + @Override + public void setTheme(int resId) { + super.setTheme(resId); + m_isCustomThemeSet = true; + } + ++ private void restartApplication() { ++ Intent intent = Intent.makeRestartActivityTask(getComponentName()); ++ startActivity(intent); ++ QtNative.quitApp(); ++ Runtime.getRuntime().exit(0); ++ } ++ + @Override + protected void onCreate(Bundle savedInstanceState) + { +@@ -94,9 +88,15 @@ public class QtActivityBase extends Activity + android.R.style.Theme_Holo_Light); + } + ++ if (QtNative.getStateDetails().isStarted) { ++ // We don't yet have a reliable way to keep the app ++ // running properly in case of an Activity only restart, ++ // so for now restart the whole app. ++ restartApplication(); ++ } ++ + m_delegate = new QtActivityDelegate(this); + +- handleActivityRestart(); + addReferrer(getIntent()); + + QtActivityLoader loader = new QtActivityLoader(this); +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +index e385432dd86b6861faec2cb206f869e17a3b2ff2..e517eea9810b29044163b164e3839713c9a2140b 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +@@ -74,21 +74,6 @@ public class QtActivityDelegate extends QtActivityDelegateBase + }); + } + +- @Override +- public boolean updateActivityAfterRestart(Activity activity) { +- boolean updated = super.updateActivityAfterRestart(activity); +- // TODO verify whether this is even needed, the last I checked the initMembers +- // recreates the layout anyway +- // update the new activity content view to old layout +- ViewGroup layoutParent = (ViewGroup)m_layout.getParent(); +- if (layoutParent != null) +- layoutParent.removeView(m_layout); +- +- m_activity.setContentView(m_layout); +- +- return updated; +- } +- + @Override + void startNativeApplicationImpl(String appParams, String mainLib) + { +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java +index b73fe363c3768f9ee5840d35bb1650dc0585ad6c..8603f0f69800f1aa1c5daf6a4d21b550b2e0c887 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java +@@ -89,21 +89,6 @@ abstract class QtActivityDelegateBase + return m_contextMenuVisible; + } + +- public boolean updateActivityAfterRestart(Activity activity) { +- try { +- // set new activity +- m_activity = activity; +- QtNative.setActivity(m_activity); +- +- // force c++ native activity object to update +- return QtNative.updateNativeActivity(); +- } catch (Exception e) { +- Log.w(QtNative.QtTAG, "Failed to update the activity."); +- e.printStackTrace(); +- return false; +- } +- } +- + public void startNativeApplication(String appParams, String mainLib) + { + if (m_membersInitialized) diff --git a/libs/patches/qtbase-0007-Use-SSL_CTX_set_dh_auto-if-DHparam-is-empty.patch b/libs/patches/qtbase-0007-Use-SSL_CTX_set_dh_auto-if-DHparam-is-empty.patch deleted file mode 100644 index 37aa8776a..000000000 --- a/libs/patches/qtbase-0007-Use-SSL_CTX_set_dh_auto-if-DHparam-is-empty.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 3d86ffeac0beaab4ab183cf1c184a09313425efc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= -Date: Fri, 29 Sep 2023 08:21:21 +0200 -Subject: Use SSL_CTX_set_dh_auto if DHparam is empty -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -[ChangeLog][QtNetwork][QSslDiffieHellmanParameters] An empty -Diffie-Hellmann parameter enables auto selection of openssl -backend. - -Fixes: QTBUG-117666 -Change-Id: Ic2e0529d48542752ca801bcb4d609988e5ddff25 -Reviewed-by: Mårten Nordheim -(cherry picked from commit fd9c567156830a21da3cd9e127a998ae90a8e564) ---- - src/network/ssl/qsslconfiguration.cpp | 3 +++ - src/plugins/tls/openssl/qsslcontext_openssl.cpp | 4 +++- - .../tls/openssl/qsslsocket_openssl_symbols_p.h | 1 + - .../network/ssl/qsslsocket/tst_qsslsocket.cpp | 16 ++++++++++------ - 4 files changed, 17 insertions(+), 7 deletions(-) - -diff --git x/qtbase/src/network/ssl/qsslconfiguration.cpp y/qtbase/src/network/ssl/qsslconfiguration.cpp -index 04a9db8521..c8be1ca202 100644 ---- x/qtbase/src/network/ssl/qsslconfiguration.cpp -+++ y/qtbase/src/network/ssl/qsslconfiguration.cpp -@@ -942,6 +942,9 @@ QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const - If no Diffie-Hellman parameters have been set, the QSslConfiguration object - defaults to using the 2048-bit MODP group from RFC 3526. - -+ Since 6.7 you can provide an empty Diffie-Hellman parameter to use auto selection -+ (see SSL_CTX_set_dh_auto of openssl) if the tls backend supports it. -+ - \note The default parameters may change in future Qt versions. - Please check the documentation of the \e{exact Qt version} that you - are using in order to know what defaults that version uses. -diff --git x/qtbase/src/plugins/tls/openssl/qsslcontext_openssl.cpp y/qtbase/src/plugins/tls/openssl/qsslcontext_openssl.cpp -index ef0e63911a..75c192bd01 100644 ---- x/qtbase/src/plugins/tls/openssl/qsslcontext_openssl.cpp -+++ y/qtbase/src/plugins/tls/openssl/qsslcontext_openssl.cpp -@@ -697,7 +697,9 @@ QT_WARNING_POP - return; - } - -- if (!dhparams.isEmpty()) { -+ if (dhparams.isEmpty()) { -+ q_SSL_CTX_set_dh_auto(sslContext->ctx, 1); -+ } else { - #ifndef OPENSSL_NO_DEPRECATED_3_0 - const QByteArray ¶ms = dhparams.d->derData; - const char *ptr = params.constData(); -diff --git x/qtbase/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h y/qtbase/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h -index 1f0d739210..1531564226 100644 ---- x/qtbase/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h -+++ y/qtbase/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h -@@ -516,6 +516,7 @@ DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); - - BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); - #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) -+#define q_SSL_CTX_set_dh_auto(ctx, onoff) q_SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) - - #ifndef OPENSSL_NO_EC - // EC Diffie-Hellman support -diff --git x/qtbase/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp y/qtbase/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp -index cfcff44a4d..2f3ad0547a 100644 ---- x/qtbase/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp -+++ y/qtbase/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp -@@ -3501,9 +3501,10 @@ void tst_QSslSocket::dhServerCustomParamsNull() - if (setProxy) - return; - -+ const QSslCipher cipherWithDH("DHE-RSA-AES256-SHA256"); - SslServer server; -- server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")}; -- server.protocol = Test::TlsV1_0; -+ server.ciphers = {cipherWithDH}; -+ server.protocol = QSsl::TlsV1_2; - - QSslConfiguration cfg = server.config; - cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters()); -@@ -3516,7 +3517,6 @@ void tst_QSslSocket::dhServerCustomParamsNull() - - QSslSocket client; - QSslConfiguration config = client.sslConfiguration(); -- config.setProtocol(Test::TlsV1_0); - client.setSslConfiguration(config); - socket = &client; - connect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), &loop, SLOT(quit())); -@@ -3527,7 +3527,8 @@ void tst_QSslSocket::dhServerCustomParamsNull() - - loop.exec(); - -- QVERIFY(client.state() != QAbstractSocket::ConnectedState); -+ QCOMPARE(client.state(), QAbstractSocket::ConnectedState); -+ QCOMPARE(client.sessionCipher(), cipherWithDH); - } - - void tst_QSslSocket::dhServerCustomParams() -@@ -3542,7 +3543,9 @@ void tst_QSslSocket::dhServerCustomParams() - return; - - SslServer server; -- server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")}; -+ const QSslCipher cipherWithDH("DHE-RSA-AES256-SHA256"); -+ server.ciphers = {cipherWithDH}; -+ server.protocol = QSsl::TlsV1_2; - - QSslConfiguration cfg = server.config; - -@@ -3572,7 +3575,8 @@ void tst_QSslSocket::dhServerCustomParams() - - loop.exec(); - -- QVERIFY(client.state() == QAbstractSocket::ConnectedState); -+ QCOMPARE(client.state(), QAbstractSocket::ConnectedState); -+ QCOMPARE(client.sessionCipher(), cipherWithDH); - } - #endif // QT_CONFIG(openssl) - diff --git a/libs/patches/qtbase-0008-Ask-to-scroll-to-on-focus-changes-in-iOS-VoiceOver.patch b/libs/patches/qtbase-0008-Ask-to-scroll-to-on-focus-changes-in-iOS-VoiceOver.patch new file mode 100644 index 000000000..eb66d1440 --- /dev/null +++ b/libs/patches/qtbase-0008-Ask-to-scroll-to-on-focus-changes-in-iOS-VoiceOver.patch @@ -0,0 +1,249 @@ +From 8fd4ba03ebb607a217794c1ce866cf312f7d0363 Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Mon, 4 Dec 2023 13:06:12 +0100 +Subject: Ask to scroll-to on focus changes in iOS VoiceOver + +By adding the UIAccessibilityElementFocusedObserver, the QML Item that +received the focus from VoiceOver is tracked. In turn, the QUIView +will try to scroll the view to bring the newly focused Item into view. +This will enhance the a11y of Flickable/ListView based UI components. +The approach tries to find the first Item with the ScrollBar role and +calls the corresponding scroll action on it, assuming the Item will be +the most useful Item to have a proper attached a11y property. + +Task-number: QTBUG-119724 +Pick-to: 6.2 6.5 6.6 6.7 +Change-Id: I7632a8dd320af7547b9d36e39f5dce7e266023a4 +--- + .../platforms/ios/qiosplatformaccessibility.h | 6 ++ + .../ios/qiosplatformaccessibility.mm | 38 +++++++ + src/plugins/platforms/ios/qioswindow.h | 1 + + src/plugins/platforms/ios/qioswindow.mm | 5 + + src/plugins/platforms/ios/quiview.h | 1 + + .../platforms/ios/quiview_accessibility.mm | 99 +++++++++++++++++++ + 6 files changed, 150 insertions(+) + +diff --git x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.h y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.h +index 96efc663bac896adb44a80eb5953a57ec7d92381..b8e14c14d19a807824384d4b32cce0554752506f 100644 +--- x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.h ++++ y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.h +@@ -10,6 +10,8 @@ + + QT_BEGIN_NAMESPACE + ++@class UIAccessibilityElementFocusedObserver; ++ + class QIOSPlatformAccessibility: public QPlatformAccessibility + { + public: +@@ -17,6 +19,10 @@ public: + ~QIOSPlatformAccessibility(); + + virtual void notifyAccessibilityUpdate(QAccessibleEvent *event); ++ ++private: ++ UIAccessibilityElementFocusedObserver* const m_FocusObserver; ++ + }; + + QT_END_NAMESPACE +diff --git x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm +index eb18ee637eef978e8574593644652271896a2035..d79eb8203091c6b684758803c0d03b5a69e4bed7 100644 +--- x/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm ++++ y/qtbase/src/plugins/platforms/ios/qiosplatformaccessibility.mm +@@ -11,7 +11,45 @@ + #include "qioswindow.h" + #include "quiaccessibilityelement.h" + ++@interface UIAccessibilityElementFocusedObserver : NSObject ++ - (instancetype) init; ++ - (void) receiveNotification: (NSNotification*) notification; ++@end ++ ++@implementation UIAccessibilityElementFocusedObserver ++- (instancetype) init { ++ self = [super init]; ++ if (!self) ++ { ++ return nil; ++ } ++ ++ [[NSNotificationCenter defaultCenter] ++ addObserver:self ++ selector:@selector(receiveNotification:) ++ name:UIAccessibilityElementFocusedNotification ++ object:nil]; ++ ++ return self; ++} ++ ++- (void)receiveNotification:(NSNotification*)notification { ++ const auto element = notification.userInfo[UIAccessibilityFocusedElementKey]; ++ if (!element) ++ return; ++ ++ foreach (QWindow *win, QGuiApplication::topLevelWindows()) { ++ if (win && win->handle()) { ++ QT_PREPEND_NAMESPACE(QIOSWindow) *window = static_cast(win->handle()); ++ if (window->bringIntoView(element)) ++ return; ++ } ++ } ++} ++@end ++ + QIOSPlatformAccessibility::QIOSPlatformAccessibility() ++ : m_FocusObserver([[UIAccessibilityElementFocusedObserver alloc] init]) + {} + + QIOSPlatformAccessibility::~QIOSPlatformAccessibility() +diff --git x/qtbase/src/plugins/platforms/ios/qioswindow.h y/qtbase/src/plugins/platforms/ios/qioswindow.h +index 02b21612023427a10fa5ad9333171108a7f7507e..366179bbccbcaa2188343b017ff2fe82e26c6002 100644 +--- x/qtbase/src/plugins/platforms/ios/qioswindow.h ++++ y/qtbase/src/plugins/platforms/ios/qioswindow.h +@@ -51,6 +51,7 @@ public: + WId winId() const override { return WId(m_view); } + + void clearAccessibleCache(); ++ bool bringIntoView(id element); + + QSurfaceFormat format() const override; + +diff --git x/qtbase/src/plugins/platforms/ios/qioswindow.mm y/qtbase/src/plugins/platforms/ios/qioswindow.mm +index 027752248c8f1f5127245cb24173e0ce30c91583..d265af21b6dc22b5c2410ab4dde49ee50b065407 100644 +--- x/qtbase/src/plugins/platforms/ios/qioswindow.mm ++++ y/qtbase/src/plugins/platforms/ios/qioswindow.mm +@@ -405,6 +405,11 @@ void QIOSWindow::clearAccessibleCache() + [quiview_cast(m_view) clearAccessibleCache]; + } + ++bool QIOSWindow::bringIntoView(id element) ++{ ++ return [quiview_cast(m_view) bringIntoView:element]; ++} ++ + void QIOSWindow::requestUpdate() + { + static_cast(screen())->setUpdatesPaused(false); +diff --git x/qtbase/src/plugins/platforms/ios/quiview.h y/qtbase/src/plugins/platforms/ios/quiview.h +index 517258517295b0c08eade4e2246438c48541277c..bd4ea3875bfcc0034aa1fee279b02610df3351b8 100644 +--- x/qtbase/src/plugins/platforms/ios/quiview.h ++++ y/qtbase/src/plugins/platforms/ios/quiview.h +@@ -26,6 +26,7 @@ QT_END_NAMESPACE + + @interface QUIView (Accessibility) + - (void)clearAccessibleCache; ++- (bool)bringIntoView:(id) element; + @end + + @interface UIView (QtHelpers) +diff --git x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm +index 04e1f8cfb3098b9135703bc5e24e025288643111..8494ee893680a544d91138a3c9bad14bdcca388e 100644 +--- x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm ++++ y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm +@@ -56,6 +56,105 @@ + [m_accessibleElements removeAllObjects]; + } + ++bool performAction(QAccessibleInterface* iface, const QString& actionName) ++{ ++ if (!iface || actionName.isEmpty()) ++ return NO; ++ ++ QAccessibleActionInterface *action = iface->actionInterface(); ++ if (!action) ++ return NO; ++ ++ const auto actionNames = action->actionNames(); ++ if (actionNames.contains(actionName)) { ++ action->doAction(actionName); ++ return YES; ++ } ++ ++ return NO; ++} ++ ++bool performActionUpstream(QAccessibleInterface* iface, const QString& actionName) ++{ ++ if (!iface) ++ return NO; ++ ++ if (performAction(iface, actionName)) ++ return YES; ++ ++ return performActionUpstream(iface->parent(), actionName); ++} ++ ++QAccessibleInterface* findScrollable(QAccessibleInterface* iface) ++{ ++ if (!iface) ++ return nil; ++ ++ if (iface->role() == QAccessible::ScrollBar) ++ return iface; ++ ++ return nil; ++} ++ ++QAccessibleInterface* findScrollableUpstream(QAccessibleInterface* iface) ++{ ++ if (!iface) ++ return nil; ++ ++ for (int i = 0; i < iface->childCount(); ++i) { ++ QAccessibleInterface* scrollable = findScrollable(iface->child(i)); ++ if (scrollable) ++ return scrollable; ++ } ++ ++ return findScrollableUpstream(iface->parent()); ++} ++ ++QString findMoveAction(const QRect& rect, const QRect& boundingRect) ++{ ++ if (rect.x() + rect.width() > boundingRect.x() + boundingRect.width()) ++ return QAccessibleActionInterface::scrollRightAction(); ++ if (rect.x() < boundingRect.x()) ++ return QAccessibleActionInterface::scrollLeftAction(); ++ if (rect.y() + rect.height() > boundingRect.y() + boundingRect.height()) ++ return QAccessibleActionInterface::scrollDownAction(); ++ if (rect.y() < boundingRect.y()) ++ return QAccessibleActionInterface::scrollUpAction(); ++ ++ return QString(); ++} ++ ++- (bool)bringIntoView:(id) element ++{ ++ QMacAccessibilityElement* a11yElement = element; ++ if (!a11yElement) ++ return NO; ++ ++ QAccessibleInterface* iface = QAccessible::accessibleInterface(a11yElement.axid); ++ if (!iface || iface->state().invisible) ++ return NO; ++ ++ QAccessibleInterface* scrollable = findScrollable(iface); ++ if (!scrollable) ++ scrollable = findScrollableUpstream(iface->parent()); ++ ++ const QRect elementRect = iface->rect(); ++ ++ if (scrollable) { ++ const QString action = findMoveAction(elementRect, scrollable->rect()); ++ return performAction(scrollable, action); ++ } ++ ++ // Fallback to window to do SOMETHING ++ QWindow* window = iface->window(); ++ if (!window) ++ return NO; ++ ++ const QRect boundingRect = {window->x(), window->y(), window->width(), window->height()}; ++ const QString action = findMoveAction(elementRect, boundingRect); ++ return performActionUpstream(iface, action); ++} ++ + // this is a container, returning yes here means the functions below will never be called + - (BOOL)isAccessibilityElement + { diff --git a/libs/patches/qtbase-0009-iOS-Always-insert-created-a11y-elements-to-the-cache.patch b/libs/patches/qtbase-0009-iOS-Always-insert-created-a11y-elements-to-the-cache.patch new file mode 100644 index 000000000..32b537752 --- /dev/null +++ b/libs/patches/qtbase-0009-iOS-Always-insert-created-a11y-elements-to-the-cache.patch @@ -0,0 +1,49 @@ +From 414c483866eeeebcc6b1718b082d7b8dc6b61cab Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Mon, 24 Jun 2024 12:29:28 +0200 +Subject: iOS: Always insert created a11y elements to the cache +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +By having all known a11y elements in the cache, the iOS Screen Reader will +stay up-to-date with the UI elements that are currently present. +Do ensure this behavior, the ctor is made private. + +Fixes: QTBUG-126622 +Pick-to: 6.8 6.7 +Change-Id: I23452ffd60128889a49e5844a6fc17d45683cee5 +Reviewed-by: Tor Arne Vestbø +(cherry picked from 9a6c32bed15ed3aa13ff82e15ac6834d6e7bdc3b) +--- + src/plugins/platforms/ios/quiaccessibilityelement.h | 1 - + src/plugins/platforms/ios/quiview_accessibility.mm | 3 +-- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git x/qtbase/src/plugins/platforms/ios/quiaccessibilityelement.h y/qtbase/src/plugins/platforms/ios/quiaccessibilityelement.h +index 858032543640dd38abc707c2332719c9bc6fb8db..fa96ccbcf9f752123060855c7915019e5a1ed249 100644 +--- x/qtbase/src/plugins/platforms/ios/quiaccessibilityelement.h ++++ y/qtbase/src/plugins/platforms/ios/quiaccessibilityelement.h +@@ -13,7 +13,6 @@ + + @property (readonly) QAccessible::Id axid; + +-- (instancetype)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view; + + (instancetype)elementWithId:(QAccessible::Id)anId; + + @end +diff --git x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm +index 8494ee893680a544d91138a3c9bad14bdcca388e..5a41faaf31032ae08703a239474fd8df2cd2d0eb 100644 +--- x/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm ++++ y/qtbase/src/plugins/platforms/ios/quiview_accessibility.mm +@@ -13,9 +13,8 @@ + if (!iface || iface->state().invisible || (iface->text(QAccessible::Name).isEmpty() && iface->text(QAccessible::Value).isEmpty() && iface->text(QAccessible::Description).isEmpty())) + return; + QAccessible::Id accessibleId = QAccessible::uniqueId(iface); +- UIAccessibilityElement *elem = [[QT_MANGLE_NAMESPACE(QMacAccessibilityElement) alloc] initWithId:accessibleId withAccessibilityContainer:self]; ++ UIAccessibilityElement *elem = [QT_MANGLE_NAMESPACE(QMacAccessibilityElement) elementWithId:accessibleId]; + [m_accessibleElements addObject:elem]; +- [elem release]; + } + + - (void)createAccessibleContainer:(QAccessibleInterface *)iface diff --git a/libs/patches/qtbase-0010-Revert-Android-Detect-mouse-buttons.patch b/libs/patches/qtbase-0010-Revert-Android-Detect-mouse-buttons.patch new file mode 100644 index 000000000..8a7e9e128 --- /dev/null +++ b/libs/patches/qtbase-0010-Revert-Android-Detect-mouse-buttons.patch @@ -0,0 +1,167 @@ +From 55c028daaba60fd0cca52be42986014385b3e7f6 Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Wed, 26 Jun 2024 15:26:09 +0200 +Subject: Revert "Android: Detect mouse buttons" + +This reverts commit 8d8cbe87e21f05b7d611ed4be47299977288b267. +--- + .../qtproject/qt/android/QtInputDelegate.java | 8 +- + .../platforms/android/androidjniinput.cpp | 86 +++---------------- + 2 files changed, 15 insertions(+), 79 deletions(-) + +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +index fb7b69c0dd1af589f28193f640f194ca9c421867..5327049f4445ab05b1e02267b7ddd970654e85dc 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +@@ -501,8 +501,8 @@ public class QtInputDelegate implements QtInputConnection.QtInputConnectionListe + // tablet methods + + // pointer methods +- public static native void mouseDown(int winId, int x, int y, int mouseButtonState); +- public static native void mouseUp(int winId, int x, int y, int mouseButtonState); ++ public static native void mouseDown(int winId, int x, int y); ++ public static native void mouseUp(int winId, int x, int y); + public static native void mouseMove(int winId, int x, int y); + public static native void mouseWheel(int winId, int x, int y, float hDelta, float vDelta); + public static native void touchBegin(int winId); +@@ -618,11 +618,11 @@ public class QtInputDelegate implements QtInputConnection.QtInputConnectionListe + { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_UP: +- mouseUp(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); ++ mouseUp(id, (int) event.getX(), (int) event.getY()); + break; + + case MotionEvent.ACTION_DOWN: +- mouseDown(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); ++ mouseDown(id, (int) event.getX(), (int) event.getY()); + m_oldX = (int) event.getX(); + m_oldY = (int) event.getY(); + break; +diff --git x/qtbase/src/plugins/platforms/android/androidjniinput.cpp y/qtbase/src/plugins/platforms/android/androidjniinput.cpp +index d074e73b9e5519d433089e5cae6cd6d6da4e28e8..00e6b7ca51d3e90dc09a14f3bb1cc14029c5dcdc 100644 +--- x/qtbase/src/plugins/platforms/android/androidjniinput.cpp ++++ y/qtbase/src/plugins/platforms/android/androidjniinput.cpp +@@ -28,8 +28,6 @@ Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout") + namespace QtAndroidInput + { + static bool m_ignoreMouseEvents = false; +- static Qt::MouseButtons m_buttons = Qt::NoButton; +- + static QRect m_softwareKeyboardRect; + + static QList m_touchPoints; +@@ -162,72 +160,7 @@ namespace QtAndroidInput + anchor.x(), anchor.y(), rtl); + } + +- // from https://developer.android.com/reference/android/view/MotionEvent#getButtonState() +- enum AndroidMouseButton { +- BUTTON_PRIMARY = 0x00000001, +- BUTTON_SECONDARY = 0x00000002, +- BUTTON_TERTIARY = 0x00000004, +- BUTTON_BACK = 0x00000008, +- BUTTON_FORWARD = 0x00000010, +- BUTTON_STYLUS_PRIMARY = 0x00000020, +- BUTTON_STYLUS_SECONDARY = 0x00000040, +- }; +- Q_DECLARE_FLAGS(AndroidMouseButtons, AndroidMouseButton) +- +- static Qt::MouseButtons toMouseButtons(jint j_buttons) +- { +- const auto buttons = static_cast(j_buttons); +- Qt::MouseButtons mouseButtons; +- if (buttons.testFlag(BUTTON_PRIMARY)) +- mouseButtons.setFlag(Qt::LeftButton); +- +- if (buttons.testFlag(BUTTON_SECONDARY)) +- mouseButtons.setFlag(Qt::RightButton); +- +- if (buttons.testFlag(BUTTON_TERTIARY)) +- mouseButtons.setFlag(Qt::MiddleButton); +- +- if (buttons.testFlag(BUTTON_BACK)) +- mouseButtons.setFlag(Qt::BackButton); +- +- if (buttons.testFlag(BUTTON_FORWARD)) +- mouseButtons.setFlag(Qt::ForwardButton); +- +- if (buttons.testFlag(BUTTON_STYLUS_PRIMARY)) +- mouseButtons.setFlag(Qt::LeftButton); +- +- if (buttons.testFlag(BUTTON_STYLUS_SECONDARY)) +- mouseButtons.setFlag(Qt::RightButton); +- +- // Fall back to left button +- if (Q_UNLIKELY(buttons != 0 && mouseButtons == Qt::NoButton)) { +- qWarning() << "Unhandled button value:" << buttons << "Falling back to Qt::LeftButton"; +- mouseButtons = Qt::LeftButton; +- } +- return mouseButtons; +- } +- +- static void sendMouseButtonEvents(QWindow *topLevel, QPoint localPos, QPoint globalPos, +- jint mouseButtonState, QEvent::Type type) +- { +- const Qt::MouseButtons mouseButtons = toMouseButtons(mouseButtonState); +- const Qt::MouseButtons changedButtons = mouseButtons & ~m_buttons; +- +- if (changedButtons == Qt::NoButton) +- return; +- +- static_assert (sizeof(changedButtons) <= sizeof(uint), "Qt::MouseButtons size changed. Adapt code."); +- +- for (uint buttonInt = 0x1; static_cast(changedButtons) >= buttonInt; buttonInt <<= 1) { +- const auto button = static_cast(buttonInt); +- if (changedButtons.testFlag(button)) { +- QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos, +- mouseButtons, button, type); +- } +- } +- } +- +- static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState) ++ static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) + { + if (m_ignoreMouseEvents) + return; +@@ -236,11 +169,13 @@ namespace QtAndroidInput + QWindow *window = windowFromId(winId); + m_mouseGrabber = window; + const QPoint localPos = window && window->handle() ? +- window->handle()->mapFromGlobal(globalPos) : globalPos; +- sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonPress); ++ window->handle()->mapFromGlobal(globalPos) : globalPos; ++ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, ++ Qt::MouseButtons(Qt::LeftButton), ++ Qt::LeftButton, QEvent::MouseButtonPress); + } + +- static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState) ++ static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) + { + const QPoint globalPos(x,y); + QWindow *window = m_mouseGrabber.data(); +@@ -249,8 +184,9 @@ namespace QtAndroidInput + + const QPoint localPos = window && window->handle() ? + window->handle()->mapFromGlobal(globalPos) : globalPos; +- +- sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonRelease); ++ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, ++ Qt::MouseButtons(Qt::NoButton), ++ Qt::LeftButton, QEvent::MouseButtonRelease); + m_ignoreMouseEvents = false; + m_mouseGrabber.clear(); + } +@@ -964,8 +900,8 @@ namespace QtAndroidInput + {"touchAdd","(IIIZIIFFFF)V",(void*)touchAdd}, + {"touchEnd","(II)V",(void*)touchEnd}, + {"touchCancel", "(I)V", (void *)touchCancel}, +- {"mouseDown", "(IIII)V", (void *)mouseDown}, +- {"mouseUp", "(IIII)V", (void *)mouseUp}, ++ {"mouseDown", "(III)V", (void *)mouseDown}, ++ {"mouseUp", "(III)V", (void *)mouseUp}, + {"mouseMove", "(III)V", (void *)mouseMove}, + {"mouseWheel", "(IIIFF)V", (void *)mouseWheel}, + {"longPress", "(III)V", (void *)longPress}, diff --git a/libs/patches/qtbase-0011-Workaround-for-broken-keyboard-input-on-ChromeOS.patch b/libs/patches/qtbase-0011-Workaround-for-broken-keyboard-input-on-ChromeOS.patch new file mode 100644 index 000000000..05a115da7 --- /dev/null +++ b/libs/patches/qtbase-0011-Workaround-for-broken-keyboard-input-on-ChromeOS.patch @@ -0,0 +1,74 @@ +From 055ea3f9b3942c7151b72b0452a66ae8aade7cbf Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Thu, 13 Jun 2024 15:43:11 +0200 +Subject: Workaround for broken keyboard input on ChromeOS + +* The keyboard input was slightly broken with Qt 6.6.2 already. After changing + the SaC device name in the settings, activating elements via space did not + work anymore. +* In Qt 6.6 the Android layer used one QtEditText instance for the entire app. + Until Qt 6.7 this was reworked to support multiple windows, each QtWindow + now features its "own" QtEditText. +* On ChromeOS, keyboard input seems to get "stuck" in this case. All input + that would make sense for a text input field (letters, digits, SPACES) end + up in the (virtual) text input field and don't get dispatched to the actual + Android App. +* This workaround "forbids" the text input field to consume these inputs and + directly call the QtInputDelegate. +* Changing the SaC device name still works on ChromeOS. +* By checking if the code is run on ChromeOS, the impact on actual Android + smartphones is minimized. + +issue: QTBUG-126187, AUTENTAPP-61485 +--- + .../src/org/qtproject/qt/android/QtEditText.java | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtEditText.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtEditText.java +index 7e1198c52aae24a9ac870b7bbce9b170befb0afb..09f86d769c4339fad5fedbf48cb580f0d3a57001 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtEditText.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtEditText.java +@@ -5,6 +5,7 @@ + package org.qtproject.qt.android; + + import android.content.Context; ++import android.content.pm.PackageManager; + import android.graphics.Canvas; + import android.text.InputType; + import android.view.View; +@@ -20,6 +21,7 @@ public class QtEditText extends View + int m_imeOptions = 0; + int m_inputType = InputType.TYPE_CLASS_TEXT; + boolean m_optionsChanged = false; ++ boolean m_isChromeOS = false; + QtInputConnection m_inputConnection = null; + + // input method hints - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h +@@ -55,6 +57,9 @@ public class QtEditText extends View + setFocusable(true); + setFocusableInTouchMode(true); + m_qtInputConnectionListener = listener; ++ ++ PackageManager packageManager = context.getPackageManager(); ++ m_isChromeOS = packageManager.hasSystemFeature("org.chromium.arc") || packageManager.hasSystemFeature("org.chromium.arc.device_management"); + } + + private void setImeOptions(int imeOptions) +@@ -114,6 +119,17 @@ public class QtEditText extends View + super.onDraw(canvas); + } + ++ @Override ++ public boolean dispatchKeyEventPreIme(KeyEvent event) { ++ if (m_isChromeOS && m_qtInputConnectionListener instanceof QtInputDelegate) { ++ final QtInputDelegate delegate = (QtInputDelegate) m_qtInputConnectionListener; ++ if (event.getAction() == KeyEvent.ACTION_DOWN) { ++ return delegate.onKeyDown(event.getKeyCode(), event); ++ } ++ return delegate.onKeyUp(event.getKeyCode(), event); ++ } ++ return super.dispatchKeyEventPreIme(event); ++ } + + public void setEditTextOptions(int enterKeyType, int inputHints) + { diff --git a/libs/patches/qtbase-0012-Fix-an-evaluated-use-of-std-declval-in-qjnitypes.h.patch b/libs/patches/qtbase-0012-Fix-an-evaluated-use-of-std-declval-in-qjnitypes.h.patch new file mode 100644 index 000000000..bc6a4509f --- /dev/null +++ b/libs/patches/qtbase-0012-Fix-an-evaluated-use-of-std-declval-in-qjnitypes.h.patch @@ -0,0 +1,54 @@ +From 4792d096ce5b976107cea653aecfd00d77c5ba21 Mon Sep 17 00:00:00 2001 +From: Ville Voutilainen +Date: Sun, 18 Aug 2024 01:59:29 +0300 +Subject: Fix an evaluated use of std::declval in qjnitypes.h + +While other compilers don't seem to have trouble with this, the latest +NDK (27) compiler does. That compiler diagnoses the empty-pack case, even though in that case there is no actual use of declval, as the pack-expanded expression contains no use of declval. +For other compilers, that may work for functions that have no arguments, but will not work for any function that does have arguments; in that case, the attempt to use declval will always be ill-formed, and there will be an attempt to use declval. + +The fix is straightforward; we have a Ret(*)(Args...), its return type +is simply Ret. So use a simple trait instead of the result of a call. + +Task-number: QTBUG-127468 +Change-Id: I0dc9e1201914ab94acc2940870be7c6d8cb16c12 +Pick-to: 6.8 6.7 +Reviewed-by: Thiago Macieira +(cherry picked from commit 236c6ec6f4c777d0534539f1c293cfc74006a6eb) +--- + src/corelib/kernel/qjnitypes.h | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git x/qtbase/src/corelib/kernel/qjnitypes.h y/qtbase/src/corelib/kernel/qjnitypes.h +index 4317f75fdba76abbd671e37ad434a4cf4e0c95f5..5e0754714b7936297d58c65cc03d1cc6664d35a9 100644 +--- x/qtbase/src/corelib/kernel/qjnitypes.h ++++ y/qtbase/src/corelib/kernel/qjnitypes.h +@@ -123,12 +123,14 @@ static constexpr auto makeTupleFromArgs(Ret (*)(JNIEnv *, jclass, Args...), va_l + return makeTupleFromArgsHelper(args); + } + +-// Get the return type of a function point +-template +-auto nativeFunctionReturnType(Ret(*function)(Args...)) ++template ++struct NativeFunctionReturnType {}; ++ ++template ++struct NativeFunctionReturnType + { +- return function(std::declval()...); +-} ++ using type = Ret; ++}; + + } // namespace Detail + } // namespace QtJniMethods +@@ -139,7 +141,7 @@ auto nativeFunctionReturnType(Ret(*function)(Args...)) + // the actual function with. This then takes care of implicit conversions, + // e.g. a jobject becomes a QJniObject. + #define Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method) \ +-static decltype(QtJniMethods::Detail::nativeFunctionReturnType(Method)) \ ++static QtJniMethods::Detail::NativeFunctionReturnType::type \ + va_##Method(JNIEnv *env, jclass thiz, ...) \ + { \ + va_list args; \ diff --git a/libs/patches/qtbase-0013-androiddeployqt-Fix-the-sign-argument-handling-order.patch b/libs/patches/qtbase-0013-androiddeployqt-Fix-the-sign-argument-handling-order.patch new file mode 100644 index 000000000..b60db2d7a --- /dev/null +++ b/libs/patches/qtbase-0013-androiddeployqt-Fix-the-sign-argument-handling-order.patch @@ -0,0 +1,53 @@ +From 50f8d79bd3d8753523512d187cb4b77fdaf8d000 Mon Sep 17 00:00:00 2001 +From: Alexey Edelev +Date: Wed, 21 Aug 2024 14:54:37 +0200 +Subject: androiddeployqt: Fix the --sign argument handling ordering + +Allow using the follow arguments after '--sign' argument in +androiddeployqt. The previous fix had no effect since we should +consider the argument count first and the type of arguments next. + +Amends 9c56a77027db2fedfc2b50f96ceaee5003a7d383 + +Fixes: QTBUG-128254 +Task-number: QTBUG-109619 +Pick-to: 6.5 6.7 6.8 +Change-Id: I34eac4def94c1d0c8d304f383d60c1e21b7dc6a2 +Reviewed-by: Assam Boudjelthia +(cherry picked from commit fd2c408af2f300e100d94a386743c7cbe74fadef) +--- + src/tools/androiddeployqt/main.cpp | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git x/qtbase/src/tools/androiddeployqt/main.cpp y/qtbase/src/tools/androiddeployqt/main.cpp +index d858bce1ce8516ae97accfafd4dd9fb3a9d30a99..72fa2a149698b5206492d4c15a369d02bbfd59b4 100644 +--- x/qtbase/src/tools/androiddeployqt/main.cpp ++++ y/qtbase/src/tools/androiddeployqt/main.cpp +@@ -444,7 +444,11 @@ Options parseOptions() + else + options.buildDirectory = arguments.at(++i); + } else if (argument.compare("--sign"_L1, Qt::CaseInsensitive) == 0) { +- if (i + 2 >= arguments.size()) { ++ if (i + 2 < arguments.size() && !arguments.at(i + 1).startsWith("--"_L1) && ++ !arguments.at(i + 2).startsWith("--"_L1)) { ++ options.keyStore = arguments.at(++i); ++ options.keyStoreAlias = arguments.at(++i); ++ } else { + const QString keyStore = qEnvironmentVariable("QT_ANDROID_KEYSTORE_PATH"); + const QString storeAlias = qEnvironmentVariable("QT_ANDROID_KEYSTORE_ALIAS"); + if (keyStore.isEmpty() || storeAlias.isEmpty()) { +@@ -457,14 +461,6 @@ Options parseOptions() + options.keyStore = keyStore; + options.keyStoreAlias = storeAlias; + } +- } else if (!arguments.at(i + 1).startsWith("--"_L1) && +- !arguments.at(i + 2).startsWith("--"_L1)) { +- options.keyStore = arguments.at(++i); +- options.keyStoreAlias = arguments.at(++i); +- } else { +- options.helpRequested = true; +- fprintf(stderr, "Package signing path and alias values are not " +- "specified.\n"); + } + + // Do not override if the passwords are provided through arguments diff --git a/libs/patches/qtbase-0014-Android-update-AGP-to-version-8.2.2.patch b/libs/patches/qtbase-0014-Android-update-AGP-to-version-8.2.2.patch new file mode 100644 index 000000000..4539d5b1f --- /dev/null +++ b/libs/patches/qtbase-0014-Android-update-AGP-to-version-8.2.2.patch @@ -0,0 +1,46 @@ +From 26743604b484cb338b15e2929de1b38ee813ad9d Mon Sep 17 00:00:00 2001 +From: Assam Boudjelthia +Date: Tue, 7 May 2024 15:59:21 +0300 +Subject: Android: update AGP to version 8.2.2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This works better with the current Gradle 8.3 and supports +Android api 34 builds. + +Task-number: QTBUG-106907 +Change-Id: I816a1aa163a9aee0a5859872129cff62f81a2dea +Reviewed-by: Tinja Paavoseppä +(cherry picked from commit 112e554cbf787fa6b093354d75889f520307c33e) +--- + doc/global/macros.qdocconf | 2 +- + src/android/templates/build.gradle | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git x/qtbase/doc/global/macros.qdocconf y/qtbase/doc/global/macros.qdocconf +index a4c38fa04255ec3ab43a843347ecc694b371adf2..a147be5653badd5924c8d475b7cc600035401605 100644 +--- x/qtbase/doc/global/macros.qdocconf ++++ y/qtbase/doc/global/macros.qdocconf +@@ -87,7 +87,7 @@ macro.AndroidMaxVer = "14" + macro.AndroidPlatformVer = "34" + macro.AndroidBuildToolsVer = "34.0.0" + macro.GradleVer = "8.3" +-macro.AGPVer = "7.4.1" ++macro.AGPVer = "8.2.2" + macro.AAOSVer = "10 to 13" + + macro.beginfloatleft.HTML = "
" +diff --git x/qtbase/src/android/templates/build.gradle y/qtbase/src/android/templates/build.gradle +index b03f36b136bed04fe38d0f376b62c4e9a1d1c123..e1f804dea7721f251f776ecb728eaac80f3b8745 100644 +--- x/qtbase/src/android/templates/build.gradle ++++ y/qtbase/src/android/templates/build.gradle +@@ -5,7 +5,7 @@ buildscript { + } + + dependencies { +- classpath 'com.android.tools.build:gradle:7.4.1' ++ classpath 'com.android.tools.build:gradle:8.2.2' + } + } + diff --git a/libs/patches/qtbase-0015-Android-Exclude-the-QtWindow-itself-from-Accessibilt.patch b/libs/patches/qtbase-0015-Android-Exclude-the-QtWindow-itself-from-Accessibilt.patch new file mode 100644 index 000000000..4cd37a8e2 --- /dev/null +++ b/libs/patches/qtbase-0015-Android-Exclude-the-QtWindow-itself-from-Accessibilt.patch @@ -0,0 +1,40 @@ +From 9cda8311d85365009c9523a5e56dc1e96d99146f Mon Sep 17 00:00:00 2001 +From: Julian Greilich +Date: Wed, 31 Jul 2024 14:01:41 +0200 +Subject: Android: Exclude the QtWindow itself from Accessibilty +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since the QtWindow and its QtEditText are focusable only to hand +over events to other components, the QtWindow itself should not be +focusable by TalkBack, since this leads to an unnecessary nameless A11y-Element +in the A11y tree. + +Task-number: QTBUG-126672 +Pick-to: 6.8 +Change-Id: I532b9d3e252fbe01da7c953446242b045c57eebe +Reviewed-by: Assam Boudjelthia +Reviewed-by: Jan Arve Sæther +(cherry-picked from 46cb9027f1ed6c61faec5364b5537ae7ab9e57c1) +--- + src/android/jar/src/org/qtproject/qt/android/QtWindow.java | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtWindow.java y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtWindow.java +index d72e69d32a73276e14a5fa725ed800a98a6be34f..816f52620c4d7b11d1bfeb6a287be3e337ccd24e 100644 +--- x/qtbase/src/android/jar/src/org/qtproject/qt/android/QtWindow.java ++++ y/qtbase/src/android/jar/src/org/qtproject/qt/android/QtWindow.java +@@ -31,10 +31,12 @@ class QtWindow extends QtLayout implements QtSurfaceInterface { + super(context); + setId(View.generateViewId()); + m_editText = new QtEditText(context, delegate); ++ m_editText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + setParent(parentWindow); + setFocusableInTouchMode(true); + addView(m_editText, new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); ++ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + + QtNative.runAction(() -> { + m_gestureDetector = diff --git a/libs/patches/qtconnectivity-0001-Increase-NFC-timeout-on-Android.patch b/libs/patches/qtconnectivity-0001-Increase-NFC-timeout-on-Android.patch new file mode 100644 index 000000000..d106a7f16 --- /dev/null +++ b/libs/patches/qtconnectivity-0001-Increase-NFC-timeout-on-Android.patch @@ -0,0 +1,22 @@ +From f08d9ee3dd97ad045f579e6e9966903b78231f1f Mon Sep 17 00:00:00 2001 +From: Lars Schmertmann +Date: Tue, 13 Feb 2024 07:34:17 +0100 +Subject: Increase NFC timeout on Android + +--- + src/nfc/qnearfieldtarget_android.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp y/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp +index c7f842ae781bd0e24865a1bf011af2accd8dd739..95935920d89f3cc5f5e4fb1a9a7bf53d1f19c71b 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp ++++ y/qtconnectivity/src/nfc/qnearfieldtarget_android.cpp +@@ -463,7 +463,7 @@ bool QNearFieldTargetPrivateImpl::connect() + if (connected) + return true; + +- setCommandTimeout(2000); ++ setCommandTimeout(3000); + methodId = env.findMethod(tagTech.objectClass(), "connect"); + if (!methodId) + return false; diff --git a/libs/patches/qtconnectivity-0001-Reset-status-of-isSessionScheduled-when-starting-a-i.patch b/libs/patches/qtconnectivity-0001-Reset-status-of-isSessionScheduled-when-starting-a-i.patch deleted file mode 100644 index f408630b0..000000000 --- a/libs/patches/qtconnectivity-0001-Reset-status-of-isSessionScheduled-when-starting-a-i.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7436b286698ff67a1834fc1e8e6d4a8446ab7a5d Mon Sep 17 00:00:00 2001 -From: Jens Trillmann -Date: Thu, 5 Oct 2023 14:56:43 +0200 -Subject: Reset status of isSessionScheduled when starting a iOS NFC session - -If a user cancels the NFC popup and then starts a new session immediately -after then isSessionScheduled gets set to true. This value has to be reset -when the session gets started as isSessionScheduled==true leads to the -QTimer always triggering a new NFC session. - -Pick-to: 6.6 6.5 -Change-Id: I53d71d5c9b419d334ac6a229cff3e32aa81e9230 ---- - src/nfc/qnearfieldmanager_ios.mm | 1 + - 1 file changed, 1 insertion(+) - -diff --git x/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm y/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm -index 2709e2c7..259c3c17 100644 ---- x/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm -+++ y/qtconnectivity/src/nfc/qnearfieldmanager_ios.mm -@@ -143,6 +143,7 @@ bool QNearFieldManagerPrivateImpl::scheduleSession(QNearFieldTarget::AccessMetho - isSessionScheduled = true; - return true; - } -+ isSessionScheduled = false; - - if (accessMethod == QNearFieldTarget::TagTypeSpecificAccess) { - startSession(); diff --git a/libs/patches/qtconnectivity-0002-iOS-Allow-to-recognize-a-security-violation.patch b/libs/patches/qtconnectivity-0002-iOS-Allow-to-recognize-a-security-violation.patch new file mode 100644 index 000000000..e1c955c6e --- /dev/null +++ b/libs/patches/qtconnectivity-0002-iOS-Allow-to-recognize-a-security-violation.patch @@ -0,0 +1,73 @@ +From 070365219ec34c7d132253305345db1c3ef73de6 Mon Sep 17 00:00:00 2001 +From: Lars Schmertmann +Date: Fri, 15 Mar 2024 14:42:43 +0100 +Subject: iOS: Allow to recognize a security violation + +Currently it is not possible to decide if an unexpected card +was used or the connection failed in general. So we need to +add a new Error to QNearFieldTarget. + +Pick-to: 6.7 +Change-Id: I8f88bb81b998e61516ed4ceef207ba1528061e7d +--- + src/nfc/qnearfieldtarget.cpp | 3 +++ + src/nfc/qnearfieldtarget.h | 3 ++- + src/nfc/qnearfieldtarget_ios.mm | 12 ++++++++---- + 3 files changed, 13 insertions(+), 5 deletions(-) + +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget.cpp y/qtconnectivity/src/nfc/qnearfieldtarget.cpp +index dbcca2bd9ad4328886687843e6c1dc5be634c8b6..7df2e531c9b40b910c93733f24ebcc4b6338e0fc 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget.cpp ++++ y/qtconnectivity/src/nfc/qnearfieldtarget.cpp +@@ -90,6 +90,9 @@ QT_IMPL_METATYPE_EXTERN_TAGGED(QNearFieldTarget::RequestId, QNearFieldTarget__Re + \value CommandError Failed to send a command to the target. + \value TimeoutError The request could not be completed within the time + specified in waitForRequestCompleted(). ++ \value SecurityViolation A security violation has occurred. As example this can occur ++ on iOS when communication with a card is started where the ++ identifier is not included in the entitlements. + */ + + /*! +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget.h y/qtconnectivity/src/nfc/qnearfieldtarget.h +index 0d67011d4e2f3d23fc666f96d5207ebd53dae9b2..024d4454c8899e1b1c0f3c088e8c319dca5c7432 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget.h ++++ y/qtconnectivity/src/nfc/qnearfieldtarget.h +@@ -59,7 +59,8 @@ public: + NdefReadError, + NdefWriteError, + CommandError, +- TimeoutError ++ TimeoutError, ++ SecurityViolation + }; + Q_ENUM(Error) + +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm y/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm +index b058ad7507065bff8c21e66c16de3eefe9d3440e..256393da290c1db19f403196eb97143b9f8b3b67 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm ++++ y/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm +@@ -270,15 +270,19 @@ bool QNearFieldTargetPrivateImpl::connect() + id tag = static_cast>(nfcTag.get()); + NFCTagReaderSession* session = tag.session; + [session connectToTag: tag completionHandler: ^(NSError* error){ +- const bool success = error == nil; +- QMetaObject::invokeMethod(this, [this, success] { ++ const int errorCode = error == nil ? -1 : error.code; ++ QMetaObject::invokeMethod(this, [this, errorCode] { + requestInProgress = QNearFieldTarget::RequestId(); +- if (success) { ++ if (errorCode == -1) { + connected = true; + onExecuteRequest(); + } else { + const auto requestId = queue.dequeue().first; +- reportError(QNearFieldTarget::ConnectionError, requestId); ++ reportError( ++ errorCode == NFCReaderError::NFCReaderErrorSecurityViolation ++ ? QNearFieldTarget::SecurityViolation ++ : QNearFieldTarget::ConnectionError, ++ requestId); + invalidate(); + } + }); diff --git a/libs/patches/qtconnectivity-0003-iOS-Improve-reporting-of-NFCReaderTransceiveErrorSes.patch b/libs/patches/qtconnectivity-0003-iOS-Improve-reporting-of-NFCReaderTransceiveErrorSes.patch new file mode 100644 index 000000000..f113876bf --- /dev/null +++ b/libs/patches/qtconnectivity-0003-iOS-Improve-reporting-of-NFCReaderTransceiveErrorSes.patch @@ -0,0 +1,119 @@ +From 974c647cc989b635a9214e3a81daaa7548637c60 Mon Sep 17 00:00:00 2001 +From: Timon Sassor +Date: Fri, 11 Oct 2024 15:57:51 +0200 +Subject: iOS: Improve reporting of NFCReaderTransceiveErrorSessionInvalidated + +In 9163f0081459fd9303aa6c31602f4e1b95e5e1b6 the reporting of unsupported NFC +cards was improved on iOS by emitting QNearFieldTarget::UnsupportedTargetError. +In the meantime, Apple has changed the behavior. Current versions of iOS no +longer use NFCReaderErrorSecurityViolation during connect but use +NFCReaderTransceiveErrorSessionInvalidated or +NFCReaderTransceiveErrorTagNotConnected in sendCommandAPDU. + +Change-Id: I4fd553ed25718a03de9aecfe4e67501714c78376 +--- + src/nfc/qnearfieldtarget_ios.mm | 30 +++++++++++++++++++++++------- + src/nfc/qnearfieldtarget_ios_p.h | 7 ++++--- + 2 files changed, 27 insertions(+), 10 deletions(-) + +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm y/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm +index 256393da290c1db19f403196eb97143b9f8b3b67..5a6738bfe15548f897b46c2036cd27a56fe14188 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm ++++ y/qtconnectivity/src/nfc/qnearfieldtarget_ios.mm +@@ -19,8 +19,8 @@ QT_BEGIN_NAMESPACE + + Q_APPLICATION_STATIC(ResponseProvider, responseProvider) + +-void ResponseProvider::provideResponse(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer) { +- Q_EMIT responseReceived(requestId, success, recvBuffer); ++void ResponseProvider::provideResponse(QNearFieldTarget::RequestId requestId, QNearFieldTarget::Error error, QByteArray recvBuffer) { ++ Q_EMIT responseReceived(requestId, error, recvBuffer); + } + + void NfcDeleter::operator()(void *obj) +@@ -275,6 +275,7 @@ bool QNearFieldTargetPrivateImpl::connect() + requestInProgress = QNearFieldTarget::RequestId(); + if (errorCode == -1) { + connected = true; ++ justConnected = true; + onExecuteRequest(); + } else { + const auto requestId = queue.dequeue().first; +@@ -428,23 +429,38 @@ void QNearFieldTargetPrivateImpl::onExecuteRequest() + QByteArray recvBuffer = QByteArray::fromNSData(responseData); + recvBuffer += static_cast(sw1); + recvBuffer += static_cast(sw2); +- const bool success = error == nil; +- responseProvider->provideResponse(request.first, success, recvBuffer); ++ auto errorToReport = QNearFieldTarget::NoError; ++ if (error != nil) ++ { ++ switch (error.code) { ++ case NFCReaderError::NFCReaderTransceiveErrorSessionInvalidated: ++ case NFCReaderError::NFCReaderTransceiveErrorTagNotConnected: ++ if (justConnected) { ++ errorToReport = QNearFieldTarget::SecurityViolation; ++ justConnected = false; ++ break; ++ } ++ Q_FALLTHROUGH(); ++ default: ++ errorToReport = QNearFieldTarget::CommandError; ++ } ++ } ++ responseProvider->provideResponse(request.first, errorToReport, recvBuffer); + }]; + } + } + +-void QNearFieldTargetPrivateImpl::onResponseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer) ++void QNearFieldTargetPrivateImpl::onResponseReceived(QNearFieldTarget::RequestId requestId, QNearFieldTarget::Error error, QByteArray recvBuffer) + { + if (requestInProgress != requestId) + return; + + requestInProgress = QNearFieldTarget::RequestId(); +- if (success) { ++ if (error == QNearFieldTarget::NoError) { + setResponseForRequest(requestId, recvBuffer, true); + onExecuteRequest(); + } else { +- reportError(QNearFieldTarget::CommandError, requestId); ++ reportError(error, requestId); + invalidate(); + } + } +diff --git x/qtconnectivity/src/nfc/qnearfieldtarget_ios_p.h y/qtconnectivity/src/nfc/qnearfieldtarget_ios_p.h +index c0cde0b621c9f64bc14d36a4b469462a88c5b9b0..9c9b1d302ff1e107fbec27f2d2cbaf885608a155 100644 +--- x/qtconnectivity/src/nfc/qnearfieldtarget_ios_p.h ++++ y/qtconnectivity/src/nfc/qnearfieldtarget_ios_p.h +@@ -33,10 +33,10 @@ class ResponseProvider : public QObject + Q_OBJECT + + public: +- void provideResponse(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); ++ void provideResponse(QNearFieldTarget::RequestId requestId, QNearFieldTarget::Error error, QByteArray recvBuffer); + + Q_SIGNALS: +- void responseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); ++ void responseReceived(QNearFieldTarget::RequestId requestId, QNearFieldTarget::Error error, QByteArray recvBuffer); + }; + + struct NfcDeleter +@@ -95,6 +95,7 @@ private: + bool hasNDEFMessage = false; + + bool connected = false; ++ bool justConnected = false; + QTimer targetCheckTimer; + QNearFieldTarget::RequestId requestInProgress; + QQueue> queue; +@@ -108,7 +109,7 @@ private Q_SLOTS: + void onTargetCheck(); + void onTargetError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + void onExecuteRequest(); +- void onResponseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer); ++ void onResponseReceived(QNearFieldTarget::RequestId requestId, QNearFieldTarget::Error error, QByteArray recvBuffer); + // NDEF: + void messageRead(const QNdefMessage &ndefMessage, QNearFieldTarget::RequestId request); + void messageWritten(QNearFieldTarget::RequestId request); diff --git a/libs/patches/qtdeclarative-0001-A11y-Send-a11y-events-on-Accessible.ignored-changes.patch b/libs/patches/qtdeclarative-0001-A11y-Send-a11y-events-on-Accessible.ignored-changes.patch new file mode 100644 index 000000000..663bccd36 --- /dev/null +++ b/libs/patches/qtdeclarative-0001-A11y-Send-a11y-events-on-Accessible.ignored-changes.patch @@ -0,0 +1,29 @@ +From 32e3976af18232312c83cb5b3c8e9b93f9895cb8 Mon Sep 17 00:00:00 2001 +From: Jens Trillmann +Date: Mon, 19 Feb 2024 09:41:13 +0100 +Subject: A11y: Send a11y events on Accessible.ignored changes + +The Accessible.ignored setter does not send a11y events like the setter +in the header STATE_PROPERTY macro and other setter do. This leads to +changes of Accessible.ignored not being registered by screen readers. + +Fixes: QTBUG-122436 +Pick-to: 6.5 6.6 6.7 +Change-Id: I0626b66c91876fa3e6dd23e76c32e8bfe43136bf +--- + src/quick/items/qquickaccessibleattached.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git x/qtdeclarative/src/quick/items/qquickaccessibleattached.cpp y/qtdeclarative/src/quick/items/qquickaccessibleattached.cpp +index 865fb8bf11cd956961109d2c65ec5f2989922521..0a4672382ec141e0f6a20459a3347728f0d688a1 100644 +--- x/qtdeclarative/src/quick/items/qquickaccessibleattached.cpp ++++ y/qtdeclarative/src/quick/items/qquickaccessibleattached.cpp +@@ -430,6 +430,8 @@ void QQuickAccessibleAttached::setIgnored(bool ignored) + { + if (this->ignored() != ignored && item()) { + item()->d_func()->isAccessible = !ignored; ++ QAccessibleEvent ev(item(), ignored ? QAccessible::ObjectHide : QAccessible::ObjectShow); ++ QAccessible::updateAccessibility(&ev); + emit ignoredChanged(); + } + } diff --git a/libs/patches/qtdeclarative-0001-QtQml-Re-add-pthread_attr_init-to-stackPropertiesGen.patch b/libs/patches/qtdeclarative-0001-QtQml-Re-add-pthread_attr_init-to-stackPropertiesGen.patch deleted file mode 100644 index 974b7a1f9..000000000 --- a/libs/patches/qtdeclarative-0001-QtQml-Re-add-pthread_attr_init-to-stackPropertiesGen.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5bb3161566b3540e6909e585675eab225dcb994a Mon Sep 17 00:00:00 2001 -From: Ulf Hermann -Date: Tue, 26 Sep 2023 12:36:09 +0200 -Subject: QtQml: Re-add pthread_attr_init() to stackPropertiesGeneric() - -Before calling pthread_attr_get_np(), as opposed to -pthread_getattr_np(), we do need to call pthread_attr_init(). Both the -FreeBSD and the NetBSD manpages tell us to do so. - -Amends commit 9f4aeeabb982cfc4306c9d350dbb68f64914fb32. - -Pick-to: 6.6 6.5 -Fixes: QTBUG-117513 -Change-Id: Ic851ba2ffcf13d268b3a53d926cb92f7bed7a3d9 -(cherry picked from commit 94e0bb6de357cb5e1fca32a4107363d95346222e) ---- - src/qml/memory/qv4stacklimits.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git x/qtdeclarative/src/qml/memory/qv4stacklimits.cpp y/qtdeclarative/src/qml/memory/qv4stacklimits.cpp -index 68ef7a366a..429520e527 100644 ---- x/qtdeclarative/src/qml/memory/qv4stacklimits.cpp -+++ y/qtdeclarative/src/qml/memory/qv4stacklimits.cpp -@@ -235,6 +235,7 @@ StackProperties stackPropertiesGeneric(qsizetype stackSize = 0) - pthread_t thread = pthread_self(); - pthread_attr_t sattr; - # if defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(Q_OS_NETBSD) -+ pthread_attr_init(&sattr); - pthread_attr_get_np(thread, &sattr); - # else - pthread_getattr_np(thread, &sattr); diff --git a/libs/patches/qtdeclarative-0002-Fix-polish-issue-in-the-quick-layout.patch b/libs/patches/qtdeclarative-0002-Fix-polish-issue-in-the-quick-layout.patch new file mode 100644 index 000000000..09780d3d1 --- /dev/null +++ b/libs/patches/qtdeclarative-0002-Fix-polish-issue-in-the-quick-layout.patch @@ -0,0 +1,92 @@ +From 7c5c6ace67894d1bb14982e41716f834bc2f5aa9 Mon Sep 17 00:00:00 2001 +From: Santhosh Kumar +Date: Tue, 4 Jun 2024 21:20:19 +0200 +Subject: Fix polish issue in the quick layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The patch 3fa4719789921ff8be440ec760d8b9ab569758eb skip geometry change +of layout items when it has already been invalidated. This can cause +problems when we have nested layouts, as the dirty flag set in the +child layout during invalidate blocks further rearranging its items +(i.e. setting geometry to its items). + +This patch fixes it by allowing rearrange when the parent item is a +layout by itself. For other cases (i.e. not the nested layout), the +child layout schedules the polish, and this polish takes care of +further rearranging its items. + +Fixes: QTBUG-125481 +Pick-to: 6.8 6.7 +Change-Id: I86c5b584e27fbe71b3e740fe7b3fdb0f3ac7ae14 +Reviewed-by: Jan Arve Sæther +(cherry picked from commit 49f7eabeac959fb448482bd0a7ebb1b774bc5bcb) +--- + src/quicklayouts/qquicklayout.cpp | 3 +- + .../qquicklayouts/data/tst_rowlayout.qml | 38 +++++++++++++++++++ + 2 files changed, 40 insertions(+), 1 deletion(-) + +diff --git x/qtdeclarative/src/quicklayouts/qquicklayout.cpp y/qtdeclarative/src/quicklayouts/qquicklayout.cpp +index f38bdfd39611ed68dcdc5e3d8b9ab242d07a25af..d1b643d092ba8c7f5e822b9f5332bf74752e8e54 100644 +--- x/qtdeclarative/src/quicklayouts/qquicklayout.cpp ++++ y/qtdeclarative/src/quicklayouts/qquicklayout.cpp +@@ -923,7 +923,8 @@ void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGe + { + Q_D(QQuickLayout); + QQuickItem::geometryChange(newGeometry, oldGeometry); +- if (invalidated() || d->m_disableRearrange || !isReady()) ++ if ((invalidated() && !qobject_cast(parentItem())) || ++ d->m_disableRearrange || !isReady()) + return; + + qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry; +diff --git x/qtdeclarative/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml y/qtdeclarative/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +index d31a0b0fb8085ec08757ae5c3505a22bcb944deb..56198f0d2e8387072bb917a046f1d42539ee5bb8 100644 +--- x/qtdeclarative/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml ++++ y/qtdeclarative/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +@@ -1512,6 +1512,44 @@ Item { + compare(itemRect(r1), [80,0,20,20]) + } + ++ Component { ++ id: rearrangeInvalidatedChildInNestedLayout ++ ColumnLayout { ++ anchors.fill: parent ++ RowLayout { ++ spacing: 0 ++ Text { ++ Layout.preferredWidth: 50 ++ text: "Text Text Text" ++ wrapMode: Text.WordWrap ++ } ++ Rectangle { ++ color: "red"; ++ Layout.preferredWidth: 50 ++ Layout.preferredHeight: 20 ++ } ++ Rectangle { ++ color: "green" ++ Layout.preferredHeight: 20 ++ Layout.fillWidth: true ++ } ++ } ++ } ++ } ++ ++ function test_rearrangeInvalidatedChildInNestedLayout() { ++ let layout = rearrangeInvalidatedChildInNestedLayout.createObject(container) ++ waitForRendering(layout) ++ ++ let item1 = layout.children[0].children[0] ++ let item2 = layout.children[0].children[1] ++ let item3 = layout.children[0].children[2] ++ ++ compare(item1.width, 50) ++ compare(item2.width, 50) ++ compare(item3.width, 100) ++ } ++ + Component { + id: changeChildrenOfHiddenLayout_Component + RowLayout { diff --git a/libs/patches/qtdeclarative-0002-Remove-warnings-about-polish-and-binding-loops.patch b/libs/patches/qtdeclarative-0002-Remove-warnings-about-polish-and-binding-loops.patch deleted file mode 100644 index d8d8a6d88..000000000 --- a/libs/patches/qtdeclarative-0002-Remove-warnings-about-polish-and-binding-loops.patch +++ /dev/null @@ -1,57 +0,0 @@ -From acf5a10d344f9e711a3c7c6d7d6629077c1ce1fc Mon Sep 17 00:00:00 2001 -From: Julian Greilich -Date: Fri, 27 Oct 2023 11:34:09 +0200 -Subject: Remove warnings about polish and binding loops - -Since the polish and binding loops are known problems we don't want -them to spam into the log files. - -Change-Id: I72b73ed0652c3b2b6fff1def264c812add4377f6 ---- - src/qml/qml/qqmlabstractbinding.cpp | 2 +- - src/qml/qml/qqmlpropertybinding.cpp | 1 - - src/quicklayouts/qquicklayout.cpp | 3 --- - 3 files changed, 1 insertion(+), 5 deletions(-) - -diff --git x/qtdeclarative/src/qml/qml/qqmlabstractbinding.cpp y/qtdeclarative/src/qml/qml/qqmlabstractbinding.cpp -index 78d1d68f55..87348a97e5 100644 ---- x/qtdeclarative/src/qml/qml/qqmlabstractbinding.cpp -+++ y/qtdeclarative/src/qml/qml/qqmlabstractbinding.cpp -@@ -157,7 +157,7 @@ void QQmlAbstractBinding::removeFromObject() - - void QQmlAbstractBinding::printBindingLoopError(const QQmlProperty &prop) - { -- qmlWarning(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); -+ Q_UNUSED(prop) - } - - void QQmlAbstractBinding::getPropertyData( -diff --git x/qtdeclarative/src/qml/qml/qqmlpropertybinding.cpp y/qtdeclarative/src/qml/qml/qqmlpropertybinding.cpp -index 5f646b62de..7219cb0a0e 100644 ---- x/qtdeclarative/src/qml/qml/qqmlpropertybinding.cpp -+++ y/qtdeclarative/src/qml/qml/qqmlpropertybinding.cpp -@@ -148,7 +148,6 @@ void QQmlPropertyBindingJS::expressionChanged() - else - err.setDescription(QString::fromLatin1("Binding loop detected")); - err.setObject(asBinding()->target()); -- qmlWarning(this->scopeObject(), err); - return; - } - m_error.setTag(InEvaluationLoop); -diff --git x/qtdeclarative/src/quicklayouts/qquicklayout.cpp y/qtdeclarative/src/quicklayouts/qquicklayout.cpp -index fc2bcc130c..193f014f58 100644 ---- x/qtdeclarative/src/quicklayouts/qquicklayout.cpp -+++ y/qtdeclarative/src/quicklayouts/qquicklayout.cpp -@@ -840,9 +840,6 @@ void QQuickLayout::invalidate(QQuickItem * /*childItem*/) - // (e.g QQuickText changes implicitHeight when its width gets changed) - qCDebug(lcQuickLayouts) << "QQuickLayout::invalidate(), polish()"; - polish(); -- } else { -- qmlWarning(this).nospace() << "Layout polish loop detected for " << this -- << ". Aborting after two iterations."; - } - } - } --- -2.42.0 - diff --git a/libs/patches/qtscxml-0001-Build-statemachine-only.patch b/libs/patches/qtscxml-0001-Build-statemachine-only.patch index 7476d8b75..65566e872 100644 --- a/libs/patches/qtscxml-0001-Build-statemachine-only.patch +++ b/libs/patches/qtscxml-0001-Build-statemachine-only.patch @@ -1,4 +1,4 @@ -From 4766db9f067c4121e77d5e80767bbe83ecf59ffc Mon Sep 17 00:00:00 2001 +From f1e7e940ec7bff5a4875803d679a8c1a2680d1f4 Mon Sep 17 00:00:00 2001 From: Andre Klitzing Date: Tue, 12 Apr 2022 11:39:12 +0200 Subject: Build statemachine only @@ -9,7 +9,7 @@ Subject: Build statemachine only 2 files changed, 5 insertions(+), 5 deletions(-) diff --git x/qtscxml/src/CMakeLists.txt y/qtscxml/src/CMakeLists.txt -index 5fbfbd9d..2f94949d 100644 +index 5fbfbd9d495ba5a926b3a44380a04a60bc06d5ee..2f94949dd4410973d577062533a449ef65a091a6 100644 --- x/qtscxml/src/CMakeLists.txt +++ y/qtscxml/src/CMakeLists.txt @@ -2,10 +2,10 @@ @@ -28,7 +28,7 @@ index 5fbfbd9d..2f94949d 100644 -add_subdirectory(plugins) +#add_subdirectory(plugins) diff --git x/qtscxml/tools/CMakeLists.txt y/qtscxml/tools/CMakeLists.txt -index c5831a40..234fa606 100644 +index c5831a40460daefec3845fa34a2757b0232511fd..234fa6065eb30588d7015b5e90bc498d79981951 100644 --- x/qtscxml/tools/CMakeLists.txt +++ y/qtscxml/tools/CMakeLists.txt @@ -3,5 +3,5 @@ diff --git a/libs/patches/qttools-0001-Disable-linguist-but-keep-translation-tools.patch b/libs/patches/qttools-0001-Disable-linguist-but-keep-translation-tools.patch index 3715343c9..9d56427e0 100644 --- a/libs/patches/qttools-0001-Disable-linguist-but-keep-translation-tools.patch +++ b/libs/patches/qttools-0001-Disable-linguist-but-keep-translation-tools.patch @@ -1,4 +1,4 @@ -From e00687d94bec135898675ffd87f1037c9234b0c4 Mon Sep 17 00:00:00 2001 +From 7e1f300a48a23abc1136fb03e3886a87fd4fe1bb Mon Sep 17 00:00:00 2001 From: Jan Moeller Date: Mon, 14 Feb 2022 13:46:46 +0100 Subject: Disable linguist but keep translation tools @@ -9,7 +9,7 @@ Change-Id: I1c54eb0e7bb86ec0861b54b5abe753c86bb57dd9 1 file changed, 3 deletions(-) diff --git x/qttools/src/linguist/CMakeLists.txt y/qttools/src/linguist/CMakeLists.txt -index d85254b32..dfcfe7271 100644 +index ab2169dec545393074e926cd084981527b071651..63b0d1df32a854e039113d539fb8272ee788f1af 100644 --- x/qttools/src/linguist/CMakeLists.txt +++ y/qttools/src/linguist/CMakeLists.txt @@ -14,9 +14,6 @@ add_subdirectory(lrelease) @@ -21,4 +21,4 @@ index d85254b32..dfcfe7271 100644 -endif() # Create a fake module that would emulate the Qt5::LinguistTools CMake Config package - qt_internal_add_module(Linguist NO_MODULE_HEADERS HEADER_MODULE) + qt_internal_add_module(Linguist diff --git a/libs/patches/qttools-0002-Disable-designer-and-uitools.patch b/libs/patches/qttools-0002-Disable-designer-and-uitools.patch index 910f7ae5a..ebb939c4d 100644 --- a/libs/patches/qttools-0002-Disable-designer-and-uitools.patch +++ b/libs/patches/qttools-0002-Disable-designer-and-uitools.patch @@ -1,4 +1,4 @@ -From 9852f44ab2b6c6e30d8c6ec4a5d45025bc13c2f4 Mon Sep 17 00:00:00 2001 +From f22b30d4fe85d20f2641d163f04e32945063b33b Mon Sep 17 00:00:00 2001 From: Andre Klitzing Date: Wed, 21 Jun 2023 12:22:46 +0200 Subject: Disable designer and uitools @@ -9,7 +9,7 @@ See https://bugreports.qt.io/browse/QTBUG-95236 1 file changed, 3 insertions(+), 3 deletions(-) diff --git x/qttools/src/CMakeLists.txt y/qttools/src/CMakeLists.txt -index 014e4c874..1574b1b20 100644 +index dc03e1c144fc9ad798adec8e1ab3eb32b4a368d9..873b231b6fd29241c89c40ad061a3886341b8632 100644 --- x/qttools/src/CMakeLists.txt +++ y/qttools/src/CMakeLists.txt @@ -18,8 +18,8 @@ qt_exclude_tool_directories_from_default_target( diff --git a/libs/patches/qttools-0003-Revert-Add-the-dependency-on-PrintSupport-module-to-.patch b/libs/patches/qttools-0003-Revert-Add-the-dependency-on-PrintSupport-module-to-.patch new file mode 100644 index 000000000..3bf8d8a60 --- /dev/null +++ b/libs/patches/qttools-0003-Revert-Add-the-dependency-on-PrintSupport-module-to-.patch @@ -0,0 +1,23 @@ +From 36a5a754b8dd94c18e9e1f7c0e379d099f6dcd62 Mon Sep 17 00:00:00 2001 +From: Jan Moeller +Date: Thu, 20 Jun 2024 10:44:46 +0200 +Subject: Revert "Add the dependency on PrintSupport module to the 'linguist' + feature" + +This reverts commit 99d6f17777dd2c4fa36d128ac668e662ce24a5bc. +--- + configure.cmake | 1 - + 1 file changed, 1 deletion(-) + +diff --git x/qttools/configure.cmake y/qttools/configure.cmake +index 813789e9f74f306a97b516d228d4edca8cf004c6..7d9ab8724f10a2dc05fe47d1ef4c2d7a634aa753 100644 +--- x/qttools/configure.cmake ++++ y/qttools/configure.cmake +@@ -74,7 +74,6 @@ qt_feature("kmap2qmap" PRIVATE + qt_feature("linguist" PRIVATE + LABEL "Qt Linguist" + PURPOSE "Qt Linguist can be used by translator to translate text in Qt applications." +- CONDITION TARGET Qt::PrintSupport + ) + qt_feature("pixeltool" PRIVATE + LABEL "pixeltool" diff --git a/presets/ci-android.json b/presets/ci-android.json new file mode 100644 index 000000000..493529c68 --- /dev/null +++ b/presets/ci-android.json @@ -0,0 +1,44 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-android", + "hidden": true, + "inherits": "ci-with-libs", + "toolchainFile": "${sourceDir}/cmake/android.toolchain.cmake" + }, + { + "name": "ci-android-apk", + "inherits": "ci-android", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + }, + { + "name": "ci-android-apk-review", + "inherits": "ci-android", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "DEBUG" + } + }, + { + "name": "ci-android-aar", + "inherits": "ci-android", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel", + "INTEGRATED_SDK": "ON" + } + }, + { + "name": "ci-android-aar-review", + "inherits": "ci-android", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "DEBUG", + "INTEGRATED_SDK": "ON" + } + } + ] +} diff --git a/presets/ci-bsd.json b/presets/ci-bsd.json new file mode 100644 index 000000000..76896ff57 --- /dev/null +++ b/presets/ci-bsd.json @@ -0,0 +1,12 @@ +{ + "version": 6, + "include": [ + "ci-linux.json" + ], + "configurePresets": [ + { + "name": "ci-bsd", + "inherits": "ci-linux" + } + ] +} diff --git a/presets/ci-iOS.json b/presets/ci-iOS.json new file mode 100644 index 000000000..6df3493ca --- /dev/null +++ b/presets/ci-iOS.json @@ -0,0 +1,40 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-ios", + "inherits": "ci-with-libs", + "generator": "Xcode", + "toolchainFile": "${sourceDir}/cmake/iOS.toolchain.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + }, + { + "name": "ci-ios-framework", + "inherits": "ci-ios", + "cacheVariables": { + "INTEGRATED_SDK": "ON" + } + }, + { + "name": "ci-ios-framework-simulator", + "inherits": "ci-ios-framework", + "generator": "Xcode", + "cacheVariables": { + "CMAKE_OSX_SYSROOT": "iphonesimulator", + "CMAKE_OSX_ARCHITECTURES": "x86_64" + } + }, + { + "name": "ci-ios-framework-simulator-arm64", + "inherits": "ci-ios-framework-simulator", + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "arm64" + } + } + ] +} diff --git a/presets/ci-linux.json b/presets/ci-linux.json new file mode 100644 index 000000000..c0d5b7e9d --- /dev/null +++ b/presets/ci-linux.json @@ -0,0 +1,25 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-linux", + "inherits": "ci-with-libs", + "cacheVariables": { + "COVERAGE": "ON", + "BUILD_SHARED_LIBS": "ON", + "SANITIZER": "ON" + } + }, + { + "name": "ci-integrated", + "inherits": "ci-linux", + "cacheVariables": { + "INTEGRATED_SDK": "ON", + "CMAKE_CXX_COMPILER": "clazy" + } + } + ] +} diff --git a/presets/ci-macOS.json b/presets/ci-macOS.json new file mode 100644 index 000000000..4ec31fb84 --- /dev/null +++ b/presets/ci-macOS.json @@ -0,0 +1,33 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-macos", + "inherits": "ci-with-libs", + "generator": "Xcode", + "cacheVariables": { + "BUILD_SHARED_LIBS": "ON", + "SANITIZER": "ON" + } + }, + { + "name": "ci-macos-release", + "inherits": "ci-with-libs", + "generator": "Xcode", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + }, + { + "name": "ci-macos-integrated", + "inherits": "ci-with-libs", + "cacheVariables": { + "INTEGRATED_SDK": "ON", + "SANITIZER": "ON" + } + } + ] +} diff --git a/presets/ci-tools.json b/presets/ci-tools.json new file mode 100644 index 000000000..ef52e3886 --- /dev/null +++ b/presets/ci-tools.json @@ -0,0 +1,32 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-translations", + "inherits": "ci-with-libs", + "cacheVariables": { + "UPDATE_TRANSLATIONS": "ON", + "UPDATE_TRANSLATIONS_NO_OBSOLETE": "ON" + } + }, + { + "name": "ci-tools", + "inherits": "ci", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RELEASE", + "tools.only": "ON", + "CMAKE_CXX_COMPILER_LAUNCHER": null + } + }, + { + "name": "ci-tools-with-libs", + "inherits": "ci-tools", + "cacheVariables": { + "CMAKE_PREFIX_PATH": "${sourceParentDir}/libs/dist" + } + } + ] +} diff --git a/presets/ci-windows.json b/presets/ci-windows.json new file mode 100644 index 000000000..903e7177f --- /dev/null +++ b/presets/ci-windows.json @@ -0,0 +1,32 @@ +{ + "version": 6, + "include": [ + "ci.json" + ], + "configurePresets": [ + { + "name": "ci-win", + "inherits": "ci-with-libs" + }, + { + "name": "ci-win-release", + "inherits": "ci-win", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel", + "WIN_SIGN_KEYSTORE": "$env{WIN_SIGN_KEYSTORE}", + "WIN_SIGN_KEYSTORE_PSW": "$env{WIN_SIGN_KEYSTORE_PSW}", + "WIN_SIGN_SUBJECT_NAME": "$env{WIN_SIGN_SUBJECT_NAME}" + } + }, + { + "name": "ci-win-debug", + "inherits": "ci-win", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "DEBUG", + "WIN_SIGN_KEYSTORE": "$env{WIN_SIGN_KEYSTORE}", + "WIN_SIGN_KEYSTORE_PSW": "$env{WIN_SIGN_KEYSTORE_PSW}", + "WIN_SIGN_SUBJECT_NAME": "$env{WIN_SIGN_SUBJECT_NAME}" + } + } + ] +} diff --git a/presets/ci.json b/presets/ci.json new file mode 100644 index 000000000..2e14d0737 --- /dev/null +++ b/presets/ci.json @@ -0,0 +1,26 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "ci", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceParentDir}/build", + "cacheVariables": { + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" + }, + "errors": { + "dev": true, + "deprecated": true + } + }, + { + "name": "ci-with-libs", + "hidden": true, + "inherits": "ci", + "cacheVariables": { + "CMAKE_PREFIX_PATH": "${sourceParentDir}/libs/dist" + } + } + ] +} diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 81f649c12..327bceb3e 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -1,38 +1,7 @@ -function(GET_BASENAME _file _output) - string(REGEX REPLACE "_[\.|0-9]+" "." _file "${_file}") - set(${_output} ${_file} PARENT_SCOPE) -endfunction() - -function(FILTER_VERSIONED _files _output) - set(regex ".+_([\.|0-9]+)\.(qml|js)$") - - set(versioned_files "${_files}") - list(FILTER versioned_files INCLUDE REGEX ${regex}) - list(SORT versioned_files COMPARE NATURAL) - - list(FILTER _files EXCLUDE REGEX ${regex}) - - foreach(file ${versioned_files}) - string(REGEX MATCH ${regex} _unused "${file}") - if(CMAKE_MATCH_1 AND QT_VERSION VERSION_LESS CMAKE_MATCH_1) - GET_BASENAME("${file}" basefile) - list(FIND _files "${basefile}" index) - if(NOT index EQUAL -1) - list(REMOVE_ITEM _files "${basefile}") - list(APPEND _files "${file}") - endif() - endif() - endforeach() - - set(${_output} ${_files} PARENT_SCOPE) -endfunction() - function(WRITE_QRC _dest_file _dir _prefix _files) - FILTER_VERSIONED("${_files}" _files) file(WRITE "${_dest_file}" "\n") foreach(file ${_files}) string(REPLACE "${_dir}/" "" file_alias "${file}") - GET_BASENAME("${file_alias}" file_alias) file(APPEND "${_dest_file}" "${file}\n") endforeach() file(APPEND "${_dest_file}" "") @@ -48,18 +17,18 @@ endfunction() function(ADD_SHADERS_TO_TARGET _target) if(TARGET ${Qt}::Qml AND NOT INTEGRATED_SDK) - file(GLOB QT6_SHADERS "${RESOURCES_DIR}/shader/qt6/*.frag") - message(STATUS "QT6_SHADERS " "${QT6_SHADERS}") - foreach(shaderPath ${QT6_SHADERS}) + file(GLOB QT_SHADERS "${RESOURCES_DIR}/shader/*.frag") + foreach(shaderPath ${QT_SHADERS}) get_filename_component(shaderName ${shaderPath} NAME) - list(APPEND QT6_SHADER_OUTPUTS ${shaderName}) + list(APPEND QT_SHADER_OUTPUTS ${shaderName}) endforeach() - message(STATUS "QT6_SHADER_OUTPUTS " "${QT6_SHADER_OUTPUTS}") - qt6_add_shaders(${_target} "${_target}_shader" + + qt_add_shaders(${_target} "${_target}_shader" PRECOMPILE - PREFIX "/shader/+qt6" - FILES "${QT6_SHADERS}" - OUTPUTS "${QT6_SHADER_OUTPUTS}") + PREFIX "/shader" + FILES "${QT_SHADERS}" + OUTPUTS "${QT_SHADER_OUTPUTS}" + QUIET) endif() endfunction() @@ -92,26 +61,15 @@ if((DESKTOP AND NOT INTEGRATED_SDK) OR BUILD_TESTING) list(APPEND QRC_FILES "ausweisapp_desktop.qrc") endif() -if((DESKTOP OR INTEGRATED_SDK) OR BUILD_TESTING) +if((DESKTOP OR CONTAINER_SDK) OR BUILD_TESTING) list(APPEND QRC_FILES "ausweisapp_webservice.qrc") endif() if(TARGET ${Qt}::Qml) - file(GLOB_RECURSE QMLDIR_FILES "${CMAKE_CURRENT_SOURCE_DIR}/qml" qmldir) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${QMLDIR_FILES}) - - set(ausweisapp_qml.qrc "${CMAKE_CURRENT_BINARY_DIR}/ausweisapp_qml.qrc") - WRITE_GLOB_QRC("${ausweisapp_qml.qrc}" "${CMAKE_CURRENT_SOURCE_DIR}/qml" "/qml" "*.qml" "qmldir") - list(APPEND QRC_FILES "${ausweisapp_qml.qrc}") - set(ausweisapp_license.qrc "${CMAKE_CURRENT_BINARY_DIR}/ausweisapp_license.qrc") configure_file("${RESOURCES_DIR}/ausweisapp_license.qrc.in" "${ausweisapp_license.qrc}" @ONLY) list(APPEND QRC_FILES "${ausweisapp_license.qrc}") - - set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml CACHE STRING "qml files" FORCE) - - add_subdirectory(qml) endif() if(NOT INTEGRATED_SDK) @@ -130,7 +88,7 @@ if(NOT INTEGRATED_SDK) file(GLOB EXISTING_QM_FILES ${CMAKE_CURRENT_BINARY_DIR}/translations/*.qm) option(UPDATE_TRANSLATIONS "Update translations/*.ts files (WARNING: make clean will delete the *.ts files!)") - if(UPDATE_TRANSLATIONS) + if(UPDATE_TRANSLATIONS AND COMMAND qt_create_translation) option(UPDATE_TRANSLATIONS_NO_OBSOLETE "Remove obsolete translations from translations/*.ts files )") set(LUPDATE_OPTIONS -extensions c,cpp,h,ui,m,mm,qml,js -no-ui-lines -locations none) @@ -143,8 +101,10 @@ if(NOT INTEGRATED_SDK) configure_file("${CMAKE_DIR}/Translation.cmake.in" "${CMAKE_BINARY_DIR}/Translation.cmake" @ONLY) add_custom_target(update.translations COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/Translation.cmake DEPENDS ${QM_FILES}) message(WARNING "'make clean' will delete *.ts files!") - else() + elseif(COMMAND qt_add_translation) qt_add_translation(QM_FILES ${TRANSLATION_FILES}) + else() + message(WARNING "Cannot build translations") endif() list(APPEND QM_FILES ${EXISTING_QM_FILES}) @@ -157,7 +117,13 @@ endif() if(QRC_FILES) - set(RCC ${CMAKE_BINARY_DIR}/src/${PROJECT_NAME}.rcc) + if(ANDROID) + file(MAKE_DIRECTORY ${ANDROID_PACKAGE_SRC_DIR}/assets/) + set(RCC ${ANDROID_PACKAGE_SRC_DIR}/assets/${PROJECT_NAME}.rcc) + else() + set(RCC ${CMAKE_BINARY_DIR}/src/${PROJECT_NAME}.rcc) + endif() + set(RCC ${RCC} PARENT_SCOPE) qt_add_binary_resources(AusweisAppRcc "${QRC_FILES}" DESTINATION ${RCC} OPTIONS -compress-algo zlib) endif() diff --git a/resources/animations/enter_can.svg b/resources/animations/enter_can.svg new file mode 100644 index 000000000..092a9df5c --- /dev/null +++ b/resources/animations/enter_can.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/resources/animations/enter_new_pin.svg b/resources/animations/enter_new_pin.svg new file mode 100644 index 000000000..8d6ee8050 --- /dev/null +++ b/resources/animations/enter_new_pin.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/pin_unknown.svg b/resources/animations/enter_no_pin.svg similarity index 57% rename from resources/images/pin_unknown.svg rename to resources/animations/enter_no_pin.svg index 7a9d342c2..d6ec62137 100644 --- a/resources/images/pin_unknown.svg +++ b/resources/animations/enter_no_pin.svg @@ -9,36 +9,6 @@ - - - - - - + + + diff --git a/resources/animations/enter_password_error.svg b/resources/animations/enter_password_error.svg new file mode 100644 index 000000000..47e1bedea --- /dev/null +++ b/resources/animations/enter_password_error.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/animations/enter_password_star.svg b/resources/animations/enter_password_star.svg new file mode 100644 index 000000000..701babf31 --- /dev/null +++ b/resources/animations/enter_password_star.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/animations/enter_password_warning.svg b/resources/animations/enter_password_warning.svg new file mode 100644 index 000000000..604cfea66 --- /dev/null +++ b/resources/animations/enter_password_warning.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/animations/enter_pin.svg b/resources/animations/enter_pin.svg new file mode 100644 index 000000000..a861f8855 --- /dev/null +++ b/resources/animations/enter_pin.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + diff --git a/resources/animations/enter_puk.svg b/resources/animations/enter_puk.svg new file mode 100644 index 000000000..9d3ad4179 --- /dev/null +++ b/resources/animations/enter_puk.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/animations/enter_remote_pin.svg b/resources/animations/enter_remote_pin.svg new file mode 100644 index 000000000..ae45c1506 --- /dev/null +++ b/resources/animations/enter_remote_pin.svg @@ -0,0 +1,56 @@ + + + + + + + diff --git a/resources/animations/enter_transport_pin.svg b/resources/animations/enter_transport_pin.svg new file mode 100644 index 000000000..b180f49a6 --- /dev/null +++ b/resources/animations/enter_transport_pin.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/images/sandglass.svg b/resources/animations/hourglass.svg similarity index 100% rename from resources/images/sandglass.svg rename to resources/animations/hourglass.svg diff --git a/resources/animations/hourglass_arrows.svg b/resources/animations/hourglass_arrows.svg new file mode 100644 index 000000000..0e59563c7 --- /dev/null +++ b/resources/animations/hourglass_arrows.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/resources/animations/hourglass_background.svg b/resources/animations/hourglass_background.svg new file mode 100644 index 000000000..6b301c013 --- /dev/null +++ b/resources/animations/hourglass_background.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/resources/animations/hourglass_mask_bottom.svg b/resources/animations/hourglass_mask_bottom.svg new file mode 100644 index 000000000..d166cc819 --- /dev/null +++ b/resources/animations/hourglass_mask_bottom.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/resources/animations/hourglass_mask_top.svg b/resources/animations/hourglass_mask_top.svg new file mode 100644 index 000000000..18eb77746 --- /dev/null +++ b/resources/animations/hourglass_mask_top.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/resources/animations/hourglass_sand.svg b/resources/animations/hourglass_sand.svg new file mode 100644 index 000000000..d75fd9976 --- /dev/null +++ b/resources/animations/hourglass_sand.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/resources/animations/wait_for_idcard_sac.svg b/resources/animations/wait_for_idcard_sac.svg new file mode 100644 index 000000000..48e7d6f0b --- /dev/null +++ b/resources/animations/wait_for_idcard_sac.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/animations/wait_for_idcard_usb.svg b/resources/animations/wait_for_idcard_usb.svg new file mode 100644 index 000000000..5fe712447 --- /dev/null +++ b/resources/animations/wait_for_idcard_usb.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/resources/animations/wait_for_questionmark.svg b/resources/animations/wait_for_questionmark.svg new file mode 100644 index 000000000..ac3eb6d78 --- /dev/null +++ b/resources/animations/wait_for_questionmark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/animations/wait_for_reader.svg b/resources/animations/wait_for_reader.svg new file mode 100644 index 000000000..1be7e72dc --- /dev/null +++ b/resources/animations/wait_for_reader.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/resources/ausweisapp.qrc b/resources/ausweisapp.qrc index e9af18b23..144262037 100644 --- a/resources/ausweisapp.qrc +++ b/resources/ausweisapp.qrc @@ -1,74 +1,46 @@ - fonts/Roboto-Medium.ttf + animations/enter_can.svg + animations/enter_new_pin.svg + animations/enter_no_pin.svg + animations/enter_password_check.svg + animations/enter_password_error.svg + animations/enter_password_star.svg + animations/enter_password_warning.svg + animations/enter_pin.svg + animations/enter_puk.svg + animations/enter_remote_pin.svg + animations/enter_transport_pin.svg + animations/hourglass.svg + animations/hourglass_arrows.svg + animations/hourglass_background.svg + animations/hourglass_mask_bottom.svg + animations/hourglass_mask_top.svg + animations/hourglass_sand.svg + animations/wait_for_idcard_sac.svg + animations/wait_for_idcard_usb.svg + animations/wait_for_questionmark.svg + animations/wait_for_reader.svg + fonts/AusweisApp_Roboto_Bold.ttf + fonts/AusweisApp_Roboto_Medium.ttf + fonts/AusweisApp_Roboto_Regular.ttf images/appearance_dark_mode.svg images/appearance_light_mode.svg images/appearance_system_mode.svg + images/ausweis.svg + images/ausweis_outline.svg + images/can_info.svg + images/checkbox_indicator.svg + images/email_icon.svg images/eye_visibility_off.svg images/eye_visibility_on.svg images/faq_icon.svg images/filter.svg images/filter_off.svg - images/mydata.svg - images/material_arrow_back.svg - images/lock.svg - images/open_website.svg - images/material_location.svg - images/material_mail.svg - images/material_phone.svg - images/material_close.svg - images/material_clear.svg - images/material_check.svg - images/material_refresh.svg - images/material_block.svg - images/material_person.svg - images/material_expand_less.svg - images/material_expand_more.svg - images/material_arrow_right.svg - images/checkbox_indicator.svg - images/npa.svg - images/can.svg - images/signature.jp2 - images/pin_letter_pinpuk.svg - images/transportpin_lightmode.svg - images/transportpin_darkmode.svg - images/transportpin_highcontrast.svg - images/pin_person.svg - images/pin_person.webp - images/pin_unknown.svg - images/can.webp - images/logo_beta_background.svg - images/logo_beta_testing.svg - images/status_error_darkmode.svg - images/status_error_highcontrast.svg - images/status_error_lightmode.svg - images/status_ok_darkmode.svg - images/status_ok_highcontrast.svg - images/status_ok_lightmode.svg - images/status_info_darkmode.svg - images/status_info_highcontrast.svg - images/status_info_lightmode.svg - images/status_warning.svg - images/ausweis.svg - images/ausweis_outline.svg - images/identify.svg - images/info.svg - images/pairingCode.webp - images/puk_darkmode.webp - images/puk_highcontrast.webp - images/puk_lightmode.webp - images/puk_darkmode.svg - images/puk_highcontrast.svg - images/puk_lightmode.svg - images/transportpin_darkmode.webp - images/transportpin_highcontrast.webp - images/transportpin_lightmode.webp - updatable-files/supported-providers.json images/icon_five_digit_pin.svg - images/icon_six_digit_pin.svg - images/icon_remote_inactive_darkmode.svg - images/icon_remote_inactive_highcontrast.svg - images/icon_remote_inactive_lightmode.svg + images/icon_remote_100_darkmode.svg + images/icon_remote_100_highcontrast.svg + images/icon_remote_100_lightmode.svg images/icon_remote_25_darkmode.svg images/icon_remote_25_highcontrast.svg images/icon_remote_25_lightmode.svg @@ -78,27 +50,73 @@ images/icon_remote_75_darkmode.svg images/icon_remote_75_highcontrast.svg images/icon_remote_75_lightmode.svg - images/icon_remote_100_darkmode.svg - images/icon_remote_100_highcontrast.svg - images/icon_remote_100_lightmode.svg - images/phone_to_pc.svg + images/icon_remote_inactive_darkmode.svg + images/icon_remote_inactive_highcontrast.svg + images/icon_remote_inactive_lightmode.svg + images/icon_six_digit_pin.svg + images/identify.svg + images/info.svg images/location_flag_de.svg images/location_flag_en.svg images/location_flag_ru.svg images/location_flag_uk.svg + images/lock.svg + images/logo_beta_background.svg + images/logo_beta_testing.svg + images/material_arrow_back.svg + images/material_arrow_right.svg + images/material_backspace.svg + images/material_block.svg + images/material_check.svg + images/material_clear.svg + images/material_close.svg + images/material_expand_less.svg + images/material_expand_more.svg + images/material_location.svg + images/material_person.svg + images/material_phone.svg + images/material_refresh.svg + images/mydata_tile.svg + images/npa.svg + images/no_internet.svg + images/open_website.svg + images/phone_to_pc.svg + images/puk_correct_darkmode.svg + images/puk_correct_highcontrast.svg + images/puk_correct_lightmode.svg + images/signature.jp2 images/siteWithLogo_darkmode.svg images/siteWithLogo_highcontrast.svg images/siteWithLogo_lightmode.svg - images/sandglass.svg - images/sandglass.webp + images/status_error_darkmode.svg + images/status_error_highcontrast.svg + images/status_error_lightmode.svg + images/status_info_darkmode.svg + images/status_info_highcontrast.svg + images/status_info_lightmode.svg + images/status_ok_darkmode.svg + images/status_ok_highcontrast.svg + images/status_ok_lightmode.svg + images/status_warning.svg images/trash_icon.svg - images/trash_icon_old.svg images/workflow_error_card_darkmode.svg images/workflow_error_card_highcontrast.svg images/workflow_error_card_lightmode.svg images/workflow_error_network_darkmode.svg images/workflow_error_network_highcontrast.svg images/workflow_error_network_lightmode.svg + images/workflow_error_nfc_darkmode.svg + images/workflow_error_nfc_highcontrast.svg + images/workflow_error_nfc_lightmode.svg + images/workflow_error_no_sak_darkmode.svg + images/workflow_error_no_sak_highcontrast.svg + images/workflow_error_no_sak_lightmode.svg + images/workflow_error_puk_blocked_darkmode.svg + images/workflow_error_puk_blocked_highcontrast.svg + images/workflow_error_puk_blocked_lightmode.svg + images/workflow_error_sak_connection_darkmode.svg + images/workflow_error_sak_connection_highcontrast.svg + images/workflow_error_sak_connection_lightmode.svg images/workflow_error_wrong_can_darkmode.svg images/workflow_error_wrong_can_highcontrast.svg images/workflow_error_wrong_can_lightmode.svg @@ -111,20 +129,12 @@ images/workflow_error_wrong_transportpin_darkmode.svg images/workflow_error_wrong_transportpin_highcontrast.svg images/workflow_error_wrong_transportpin_lightmode.svg - images/workflow_error_no_sak_darkmode.svg - images/workflow_error_no_sak_highcontrast.svg - images/workflow_error_no_sak_lightmode.svg - images/workflow_error_puk_blocked_darkmode.svg - images/workflow_error_puk_blocked_highcontrast.svg - images/workflow_error_puk_blocked_lightmode.svg images/workflow_success_changepin_darkmode.svg images/workflow_success_changepin_highcontrast.svg images/workflow_success_changepin_lightmode.svg - images/workflow_error_nfc_darkmode.svg - images/workflow_error_nfc_highcontrast.svg - images/workflow_error_nfc_lightmode.svg - shader/ConicalGradientShader.frag shader/ColorOverlayShader.frag + shader/ConicalGradientShader.frag shader/DesaturateShader.frag + updatable-files/supported-providers.json diff --git a/resources/ausweisapp_desktop.qrc b/resources/ausweisapp_desktop.qrc index 7d3f1351a..634140b45 100644 --- a/resources/ausweisapp_desktop.qrc +++ b/resources/ausweisapp_desktop.qrc @@ -1,95 +1,55 @@ - images/macos/appIcon.svg + images/desktop/a11y_icon.svg images/desktop/autostart.svg - images/desktop/info_white.svg + images/desktop/default_reader.png images/desktop/help.svg images/desktop/help_icon.svg images/desktop/home.svg - images/desktop/titlebar_arrow.svg + images/desktop/list_icon.svg + images/desktop/material_arrow_forward.svg images/desktop/material_assistant.svg images/desktop/material_new_releases.svg + images/desktop/material_open_in_browser.svg + images/desktop/material_question_answer.svg images/desktop/material_rate_review.svg - images/desktop/notifications_on.svg + images/desktop/material_settings.svg images/desktop/notifications_off.svg - images/desktop/material_arrow_forward.svg - images/desktop/material_question_answer.svg - images/desktop/material_settings_white.svg - images/desktop/material_open_in_browser.svg - images/desktop/a11y_icon.svg - images/desktop/list_icon.svg + images/desktop/notifications_on.svg + images/desktop/privacy_icon.svg images/desktop/save_icon.svg images/desktop/settings.svg - images/desktop/status_ok_darkmode.svg - images/desktop/status_ok_highcontrast.svg - images/desktop/status_ok_lightmode.svg - images/desktop/privacy_icon.svg - images/desktop/trash_icon_white.svg - images/desktop/warning.svg + images/desktop/titlebar_arrow.svg images/desktop/workflow_idcard_nfc.svg images/desktop/workflow_idcard_usb.svg - images/desktop/workflow_waitfor_idcard_sak.webp - images/desktop/workflow_waitfor_idcard_usb.webp - images/desktop/workflow_waitfor_reader.webp - images/desktop/workflow_error_sak_connection_darkmode.svg - images/desktop/workflow_error_sak_connection_highcontrast.svg - images/desktop/workflow_error_sak_connection_lightmode.svg - images/reader/default_more_reader.png - images/reader/default_no_reader.png - images/reader/default_reader.png - images/reader/default_reader_mit_ausweis.png - updatable-files/supported-readers.json + images/macos/appIcon.svg updatable-files/reader/img_ACS_ACR1281U.png - updatable-files/reader/img_ACS_ACR1281U_mit_ausweis.png + updatable-files/reader/img_ACS_ACR1581U-C1.png + updatable-files/reader/img_Cherry_ST_1275.png updatable-files/reader/img_Cherry_TC_1200.png - updatable-files/reader/img_Cherry_TC_1200_mit_ausweis.png updatable-files/reader/img_Cherry_TC_1300.png - updatable-files/reader/img_Cherry_TC_1300_mit_ausweis.png - updatable-files/reader/img_cyberjack_wave.png - updatable-files/reader/img_cyberjack_wave_mit_ausweis.png + updatable-files/reader/img_Cherry_secure_board.png updatable-files/reader/img_FEIG_myAXXES_basic.png - updatable-files/reader/img_FEIG_myAXXES_basic_mit_ausweis.png updatable-files/reader/img_Gemalto_Prox_DU.png - updatable-files/reader/img_Gemalto_Prox_DU_mit_ausweis.png updatable-files/reader/img_Gemalto_Prox_SU.png - updatable-files/reader/img_Gemalto_Prox_SU_mit_ausweis.png updatable-files/reader/img_HID_Global_OMNIKEY_5321_V2.png - updatable-files/reader/img_HID_Global_OMNIKEY_5321_V2_mit_ausweis.png updatable-files/reader/img_HID_Omnikey_542x.png - updatable-files/reader/img_HID_Omnikey_542x_mit_ausweis.png updatable-files/reader/img_HID_Omnikey_Mobile_Reader_502X_CL.png - updatable-files/reader/img_HID_Omnikey_Mobile_Reader_502X_CL_mit_ausweis.png - updatable-files/reader/img_Identive_XXXX_F.png - updatable-files/reader/img_Identive_XXXX_F_mit_ausweis.png - updatable-files/reader/img_Identive_Cloud_4700_F.png - updatable-files/reader/img_Identive_Cloud_4700_F_mit_ausweis.png updatable-files/reader/img_Identive_4701_F.png - updatable-files/reader/img_Identive_4701_F_mit_ausweis.png + updatable-files/reader/img_Identive_Cloud_4700_F.png updatable-files/reader/img_Identive_SCL011.png - updatable-files/reader/img_Identive_SCL011_mit_ausweis.png updatable-files/reader/img_Identive_SCL3711.png - updatable-files/reader/img_Identive_SCL3711_mit_ausweis.png updatable-files/reader/img_Identive_SDI011.png - updatable-files/reader/img_Identive_SDI011_mit_ausweis.png + updatable-files/reader/img_Identive_XXXX_F.png updatable-files/reader/img_KOBIL_ID_Token.png - updatable-files/reader/img_KOBIL_ID_Token_mit_ausweis.png updatable-files/reader/img_PersoSim.png - updatable-files/reader/img_PersoSim_mit_ausweis.png - updatable-files/reader/img_Simulator.png - updatable-files/reader/img_Simulator_mit_ausweis.png updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_basis.png - updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_basis_mit_ausweis.png updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_komfort.png - updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_komfort_mit_ausweis.png updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_standard.png - updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_standard_mit_ausweis.png updatable-files/reader/img_RemoteReader.png - updatable-files/reader/img_RemoteReader_mit_ausweis.png - updatable-files/reader/img_Cherry_ST_1275.png - updatable-files/reader/img_Cherry_ST_1275_mit_ausweis.png updatable-files/reader/img_Signotec_Omega_Pad.png - updatable-files/reader/img_Signotec_Omega_Pad_mit_ausweis.png - updatable-files/reader/img_Cherry_secure_board.png - updatable-files/reader/img_Cherry_secure_board_mit_ausweis.png + updatable-files/reader/img_Simulator.png + updatable-files/reader/img_cyberjack_wave.png + updatable-files/supported-readers.json diff --git a/resources/ausweisapp_mobile.qrc b/resources/ausweisapp_mobile.qrc index e690f309d..ec684d274 100644 --- a/resources/ausweisapp_mobile.qrc +++ b/resources/ausweisapp_mobile.qrc @@ -1,13 +1,10 @@ - images/ios/material_more_horiz.svg images/material_add.svg - images/mobile/x.svg - images/mobile/questionmark.svg images/mobile/card.svg images/mobile/device.svg images/mobile/device_button.svg - images/mobile/mydata_button.svg + images/mobile/device_tile.svg images/mobile/generic_id_card.svg images/mobile/help.svg images/mobile/home.svg @@ -15,26 +12,26 @@ images/mobile/icon_remote.svg images/mobile/icon_simulator.svg images/mobile/icon_smart.svg - images/mobile/share.svg images/mobile/material_arrow_left.svg - images/mobile/material_backspace.svg images/mobile/material_view_headline.svg + images/mobile/mydata.svg + images/mobile/mydata_button.svg images/mobile/phone_card_reader.svg images/mobile/phone_nfc.svg + images/mobile/phone_nfc_info.svg images/mobile/phone_nfc_with_card.svg images/mobile/phone_remote.svg + images/mobile/phone_remote_info.svg images/mobile/phone_simulator.svg images/mobile/phone_smart.svg - images/mobile/phone_nfc_info.svg - images/mobile/phone_remote_info.svg + images/mobile/questionmark.svg images/mobile/settings.svg + images/mobile/share.svg images/mobile/smarteid.svg - images/mobile/no_internet_darkmode.svg - images/mobile/no_internet_highcontrast.svg - images/mobile/no_internet_lightmode.svg images/mobile/workflow_success_nfc_darkmode.svg images/mobile/workflow_success_nfc_highcontrast.svg images/mobile/workflow_success_nfc_lightmode.svg + images/mobile/x.svg qtquickcontrols2.conf diff --git a/resources/ausweisapp_webservice.qrc b/resources/ausweisapp_webservice.qrc index 09d370f72..bdd8dc1d9 100644 --- a/resources/ausweisapp_webservice.qrc +++ b/resources/ausweisapp_webservice.qrc @@ -1,9 +1,9 @@ - template.html ../docs/sdk/AusweisApp_Logo.svg - images/html_templates/icon_attention.svg - images/html_templates/html_message_section.jpg images/desktop/npa.ico + images/html_templates/html_message_section.jpg + images/html_templates/icon_attention.svg + template.html diff --git a/resources/config.json.in b/resources/config.json.in index 4e4f06176..29e57739c 100644 --- a/resources/config.json.in +++ b/resources/config.json.in @@ -5,6 +5,7 @@ "_comment_1": "array of CVCs; hex encoded", "_comment_2": [ + "DECVCAeID00106_DECVCAeID00107", "DECVCAeID00105_DECVCAeID00106", "DECVCAeID00104_DECVCAeID00105", "DECVCAeID00103_DECVCAeID00104", @@ -12,6 +13,7 @@ "DECVCAeID00102" ], "cvRootCertificates": [ + "7F218201B67F4E82016E5F290100420E44454356434165494430303130367F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104798F2B51459558D31976AD732AA57ECA873169A3EDC0B6B49D3795C104AF2CD41D89CD880D2B3DF68B8813B83E55BB0290B46CCB890D9460AE166483C2C5AE5A8701015F200E44454356434165494430303130377F4C12060904007F0007030102025305FC4F13FFFF5F25060203010102085F24060206010102075F3740A2B6A35EEFB93B0FBABBA0C52D88825EBAC8E83C236FFBFCAE4795A67063EA6C00E5D84365733DD91C80FC506B78519C798589CF716CCFA5F988C9C3DA149527", "7F218201B67F4E82016E5F290100420E44454356434165494430303130357F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410439524CBDF8CCE2C15CD6450C9DC0BBE65D5B5D01C391AE6EF63028040D233FA30502F26B5FAFCD21CE38E4CFD42A3115A8F11A49A98DBF43E0DB83F0520627A98701015F200E44454356434165494430303130367F4C12060904007F0007030102025305FC0F13FFFF5F25060201000300095F24060204000300095F3740A2D07CC9FEC2A10AE9F26D77C3CF06AA19F0CF641763373B960D64A4CCD431BC96AC630765CEDD09BCED8351A2AE9DD0F28EFFCB38111343E9D6B1B37D4ABDC9", "7F218201B67F4E82016E5F290100420E44454356434165494430303130347F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410459D1A08A2572022E17FED831982A9CB904518003CF83DABED88DBED28963768B88DBA22A153558BD21DDAA99318378B7CD7EBFE849557CD43F8526ABE72734538701015F200E44454356434165494430303130357F4C12060904007F0007030102025305FC0F13FFFF5F25060108000601025F24060201000601025F37402FBEEAE1B1ADE6CFB6CAB9D9B19F6A6EFACB7D9701997F43CF608BF72CF496F485F691E75190DEC25C672B92CF9BA917883659A6DC16793D22BBEC4019C616CC", "7F218201B67F4E82016E5F290100420E44454356434165494430303130337F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104241D8627338B64F20077FFD558909A096C635DDB222852038EAAE642E869A40173D588F817D95DB2A6A0F077EA5EE63596A20F85BC3CB176D2F98D88D90219AA8701015F200E44454356434165494430303130347F4C12060904007F0007030102025305FC0F13FFFF5F25060105000901045F24060108000901045F3740313A81ED8734E7A8C45F16B55FB603E63027B7F44C2DE3A8E782552D35949DB221CA33BD41A01DA6A1288C7885714FC3A03FA45683B75D3884930EC6738AF8A0", @@ -28,6 +30,7 @@ "DETESTeID00002_DETESTeID00004", "DETESTeID00001_DETESTeID00002", "DETESTeID00001", + "DECVCAeIDCTL0404_DECVCAeIDCTL0405", "DECVCAeIDCTL0403_DECVCAeIDCTL0404", "DECVCAeIDCTL0402_DECVCAeIDCTL0403", "DECVCAeIDCTL0401_DECVCAeIDCTL0402", @@ -42,11 +45,12 @@ "7F218201B67F4E82016E5F290100420E44455445535465494430303030327F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410474FF63AB838C73C303AC003DFEE95CF8BF55F91E8FEBCB7395D942036E47CF1845EC786EC95BB453AAC288AD023B6067913CF9B63F908F49304E5CFC8B3050DD8701015F200E44455445535465494430303030347F4C12060904007F0007030102025305FC0F13FFFF5F25060102000501015F24060105000501015F37405C035A0611B6C58F0B5261FDD009DECAB7DC7A79482D5248CCA119059B7D82B2157CF0C4A499BCF441EFDD35E294A58C0AF19A34A0762159533285ACF170A505", "7F218201B67F4E82016E5F290100420E44455445535465494430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104096EB58BFD86252238EC2652185C43C3A56C320681A21E37A8E69DDC387C0C5F5513856EFE2FDC656E604893212E29449B365E304605AC5413E75BE31E641F128701015F200E44455445535465494430303030327F4C12060904007F0007030102025305FE0F01FFFF5F25060100000902015F24060103000902015F3740141120A0FDFC011A52F3F72B387A3DC7ACA88B4868D5AE9741780B6FF8A0B49E5F55169A2D298EF5CF95935DCA0C3DF3E9D42DC45F74F2066317154961E6C746", "7F218201B67F4E82016E5F290100420E44455445535465494430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104184BB519FC2A8F52DC0DC73112FACFE914F2A49B678DD5799A2B1DFE95E1A66359014E22FA8D66438413CEBA6CF0E215576B673376BF617AF4DFE9761D2290148701015F200E44455445535465494430303030317F4C12060904007F0007030102025305FE0F01FFFF5F25060100000801035F24060103000801035F37409F25EBFAF4B91E4C60A1683754C5DC076A3179753EF97D9F8CB01FE1DCD3B8C83E7A26602AB1F344BE5706006D79A9FF6A9716404DC83B9F30E1213B393128A2", - "7F218201BA7F4E8201725F290100421044454356434165494443544C303430337F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641044E2F055DB59B29C01B94010DC6066AF963497E38D9F10ACCBC47CB80D001812965A7BED693454AE8E76A1981623442F340A490C6C247938A0377E461F847EF078701015F201044454356434165494443544C303430347F4C12060904007F0007030102025305FE1FFFFFFF5F25060201000601045F24060204000601035F37402256E309924EFF18830B44006435906102C022E6AD84B335E8C39B90A7953758021EC44435AA34B40DB8213529B19411FCF92B2481046B1CE0322B055EFDD814", - "7F218201BA7F4E8201725F290100421044454356434165494443544C303430327F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641043543F779937155A0E3C051C54E38D2236EAF962C5315AF589C64A148254823124D15A61831163DEA6F9316CAA60300AE3DA49C909C3A2AE38528ECB3984BC07E8701015F201044454356434165494443544C303430337F4C12060904007F0007030102025305FE1FFFFFFF5F25060201000601045F24060204000601035F3740939F1910A03C3A79ED8B872535AE4896BA69CB106E27585B98ECC8EAD827894FA6CFCB2DD6065A7E2C527234518DC3847043C9C21AADF8A8BE0222606C65DE10", - "7F218201BA7F4E8201725F290100421044454356434165494443544C303430317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104045BE7308B90CAF802944EDA4BEBDB9AE8669E3E80B82DF5D9C096FFD34A8470699CC5AC513A6B0E2A29264B10263035CA39761C0ABDBC83F1DC1264211BA9578701015F201044454356434165494443544C303430327F4C12060904007F0007030102025305FE1FFFFFFF5F25060201000601045F24060204000601035F37409C480E1BE3C4FE918F104C8E946135DB66CBF8A7C3793DE3E2B517F2F40D078197C6929E4C3045423D9F4C87CD58D8F9DDB47AFD47ED0861DBCF69C118549675", - "7F218201BA7F4E8201725F2901004210444543564341654944435430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641045877AA008F94EE9E41C9A19C06878623DEC573B2A6ED779CD04563BB7D19021B736D8F77B31BEDDA2F36A1EDC181F3A3C1E10E662B59F936ECCACD14A95343F28701015F201044454356434165494443544C303430317F4C12060904007F0007030102025305FE1FFFFFFF5F25060201000601045F24060204000601035F37401E82551EE0E130E472CAA002837C18C356F1C89F47DB2C2C16B7CD570784726C3FF3629F09BADA8C25CE0FBDC47B7A441FECFA77E342EB8C52A905414B2CB5D9", - "7F218201BA7F4E8201725F2901004210444543564341654944435430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7864104063E1365669562F4DA86A6ABF7696FE91B1DD1D581C2810D77FD9703236C5291A0A6B83180D652E3B7B7CCA3B53B35E0AA3F44DAAA023B717A428E4E54BAE81B8701015F2010444543564341654944435430303030317F4C12060904007F0007030102025305FE1FFFFFFF5F25060201000601045F24060204000601035F37404CA892E299163475D68A1AF35270EB21D6A47133CB4D6DD2E405EDE20AEEC8F7470BB8A778EC542347E832E0F81EB803946D5538F861710AF6A88A9A32CAE08A" + "7F218201BA7F4E8201725F290100421044454356434165494443544C303430347F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641046F3D366B7319581EE48D9D9EE273D4BC41E53BAB45358CD74E18AC9D602DEA993FA366E3061EF944B9C7CAD560CC6A8933925C8BC3359284923A873316D97FD98701015F201044454356434165494443544C303430357F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F37407C2D73524FB2F9C393201C85338EA4BD8A818601C8D2750A17AAD690042DBA3C340AC69F907B0D82296BCD542A5DEAF26DC62FB481610A5690972613026E4C02", + "7F218201BA7F4E8201725F290100421044454356434165494443544C303430337F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410443836548E0D56977680A1B08BB205C98C835884205752C9E12C0DF001C9F55003F37772E0C6A0880129511CCE06CC71634F624EF45E61B975F5FEBF5B1A43F118701015F201044454356434165494443544C303430347F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F374098AB56059D92DB9877238B0C6EF3DD42E2B52D60E3EBC7AB3A9C4D51388062D04FDA64EDDFD49B7C95D541CD5CB197D46B792B01386910A1F7DDF18C2BF94ABD", + "7F218201BA7F4E8201725F290100421044454356434165494443544C303430327F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641043FD0CCB9B743EF5A7F55380A9CE2074300B8982D279BEA4BFD77C42ACC85F7BB6F8F3B88119546826DC712AF496178D154FE23064927E4ABB6B0B22DBE9BD6658701015F201044454356434165494443544C303430337F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F374048CF7AEEE2D7669693390CE5885397099AE90F81852BF28FACDF4BDBB4DCEB2EA031FBCF2F495EAD4222C91194373AEA3081ABC45FAD306C0957FBEF866F37B9", + "7F218201BA7F4E8201725F290100421044454356434165494443544C303430317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641044633685F4AA11C433376C04EF7A7D9DB9B6E8717CBFADC257620D18CEA2CBD911C32133B2B91EB551D7315AE2875032F82445C4738800A3B65C5EC611162DAFC8701015F201044454356434165494443544C303430327F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F374026DC0E7E15DB8EEF43781F6225F6CEBED27D71ECD6A9E27060DECCDF39913327609F08CCF7912BB4C0AA2EA2B7ADCEB07F1B9EB4C9701B61656597AE3D458C47", + "7F218201BA7F4E8201725F2901004210444543564341654944435430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A78641046E7C1FD08E10D9A0D3FDDF61D0EB8076784E6EF61A1915B8E474BE91CD7562772C2F5560231F1A6819689433123CA17D12F43DA7B21CABF0317D2120D1309E288701015F201044454356434165494443544C303430317F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F3740A9F770304FD2FE590799F2FCB109054E586092D1A021674C1BD87EDBE3FF622188D6C7D4D2669380FC4DEF700453FB6FDC7BD0C56E82318B37A2E468D407EED2", + "7F218201BA7F4E8201725F2901004210444543564341654944435430303030317F4982011D060A04007F000702020202038120A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A786410486E5153975643814C32A934028AFA4402D4A0D732C60CFDDBC060842257D84DF358682D54333179114328448273577F65D9CC0232EA6F3B4F90D34EEA83991598701015F2010444543564341654944435430303030317F4C12060904007F0007030102025305FE1FFFFFFF5F25060202010200075F24060205010200065F3740445884C8A680B0490B1F4BF1117DC008156A309281CBBADB005AEC745F5F4E0E294321F2A0D339BA477C04F33670E25371768C15EBBE4C4D1D786977888612FB" ], "_comment_5": "array of certificates for checking the authenticity of updates; DER format, hex encoded", @@ -184,18 +188,21 @@ ] }, - "minStaticKeySizes": { - "Rsa": 2000, - "Dsa": 2000, - "Dh": 2000, + "minKeySizes": { + "Rsa": 3000, + "Dsa": 3000, + "Dh": 3000, "Ec": 250 }, - "minEphemeralKeySizes": { - "Rsa": 2000, - "Dsa": 2000, - "Dh": 2000, - "Ec": 250 + "sizesIfd": { + "createRsa": 3072, + "min": { + "Rsa": 2000, + "Dsa": 2000, + "Dh": 2000, + "Ec": 250 + } }, "selfAuthentication": { diff --git a/resources/fonts/AusweisApp_Roboto_Bold.ttf b/resources/fonts/AusweisApp_Roboto_Bold.ttf new file mode 100644 index 000000000..18779a912 Binary files /dev/null and b/resources/fonts/AusweisApp_Roboto_Bold.ttf differ diff --git a/resources/fonts/AusweisApp_Roboto_Medium.ttf b/resources/fonts/AusweisApp_Roboto_Medium.ttf new file mode 100644 index 000000000..d816faa57 Binary files /dev/null and b/resources/fonts/AusweisApp_Roboto_Medium.ttf differ diff --git a/resources/fonts/AusweisApp_Roboto_Regular.ttf b/resources/fonts/AusweisApp_Roboto_Regular.ttf new file mode 100644 index 000000000..6fe31d150 Binary files /dev/null and b/resources/fonts/AusweisApp_Roboto_Regular.ttf differ diff --git a/resources/fonts/Roboto-Medium.ttf b/resources/fonts/Roboto-Medium.ttf deleted file mode 100644 index ac0f908b9..000000000 Binary files a/resources/fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/resources/images/can.svg b/resources/images/can.svg deleted file mode 100644 index 372a19b0f..000000000 --- a/resources/images/can.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/can.webp b/resources/images/can.webp deleted file mode 100644 index f81086651..000000000 Binary files a/resources/images/can.webp and /dev/null differ diff --git a/resources/images/can_info.svg b/resources/images/can_info.svg new file mode 100644 index 000000000..7d4227d57 --- /dev/null +++ b/resources/images/can_info.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/images/reader/default_reader.png b/resources/images/desktop/default_reader.png similarity index 100% rename from resources/images/reader/default_reader.png rename to resources/images/desktop/default_reader.png diff --git a/resources/images/desktop/help.svg b/resources/images/desktop/help.svg index 8c19f5c4b..cb91a3f60 100644 --- a/resources/images/desktop/help.svg +++ b/resources/images/desktop/help.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/desktop/info_white.svg b/resources/images/desktop/info_white.svg deleted file mode 100644 index 6725deeef..000000000 --- a/resources/images/desktop/info_white.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/resources/images/desktop/list_icon.svg b/resources/images/desktop/list_icon.svg index 80545797b..8864bf298 100644 --- a/resources/images/desktop/list_icon.svg +++ b/resources/images/desktop/list_icon.svg @@ -2,13 +2,13 @@ - - - - - - - - - + + + + + + + + + diff --git a/resources/images/desktop/material_settings_white.svg b/resources/images/desktop/material_settings.svg similarity index 97% rename from resources/images/desktop/material_settings_white.svg rename to resources/images/desktop/material_settings.svg index f7ca45ae7..c9eee20ee 100644 --- a/resources/images/desktop/material_settings_white.svg +++ b/resources/images/desktop/material_settings.svg @@ -1 +1 @@ - + diff --git a/resources/images/desktop/settings.svg b/resources/images/desktop/settings.svg index 430f3c75f..bbbfe0e39 100644 --- a/resources/images/desktop/settings.svg +++ b/resources/images/desktop/settings.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/desktop/status_ok_darkmode.svg b/resources/images/desktop/status_ok_darkmode.svg deleted file mode 100644 index db7cb67e6..000000000 --- a/resources/images/desktop/status_ok_darkmode.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/resources/images/desktop/status_ok_highcontrast.svg b/resources/images/desktop/status_ok_highcontrast.svg deleted file mode 100644 index 5dc19926f..000000000 --- a/resources/images/desktop/status_ok_highcontrast.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/resources/images/desktop/status_ok_lightmode.svg b/resources/images/desktop/status_ok_lightmode.svg deleted file mode 100644 index 334955b00..000000000 --- a/resources/images/desktop/status_ok_lightmode.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/resources/images/desktop/trash_icon_white.svg b/resources/images/desktop/trash_icon_white.svg deleted file mode 100644 index d7d2584b2..000000000 --- a/resources/images/desktop/trash_icon_white.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/resources/images/desktop/warning.svg b/resources/images/desktop/warning.svg deleted file mode 100644 index 23e6fc329..000000000 --- a/resources/images/desktop/warning.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/resources/images/desktop/workflow_waitfor_idcard_sak.webp b/resources/images/desktop/workflow_waitfor_idcard_sak.webp deleted file mode 100644 index dd28124bc..000000000 Binary files a/resources/images/desktop/workflow_waitfor_idcard_sak.webp and /dev/null differ diff --git a/resources/images/desktop/workflow_waitfor_idcard_usb.webp b/resources/images/desktop/workflow_waitfor_idcard_usb.webp deleted file mode 100644 index 70cccde15..000000000 Binary files a/resources/images/desktop/workflow_waitfor_idcard_usb.webp and /dev/null differ diff --git a/resources/images/desktop/workflow_waitfor_reader.webp b/resources/images/desktop/workflow_waitfor_reader.webp deleted file mode 100644 index 541aedcac..000000000 Binary files a/resources/images/desktop/workflow_waitfor_reader.webp and /dev/null differ diff --git a/resources/images/email_icon.svg b/resources/images/email_icon.svg new file mode 100644 index 000000000..0c383b387 --- /dev/null +++ b/resources/images/email_icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/resources/images/ios/material_more_horiz.svg b/resources/images/ios/material_more_horiz.svg deleted file mode 100644 index afb392c86..000000000 --- a/resources/images/ios/material_more_horiz.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/images/material_add.svg b/resources/images/material_add.svg index 70898c171..b23b9395c 100644 --- a/resources/images/material_add.svg +++ b/resources/images/material_add.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_arrow_back.svg b/resources/images/material_arrow_back.svg index 00d44bf54..d8637c1c0 100644 --- a/resources/images/material_arrow_back.svg +++ b/resources/images/material_arrow_back.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_arrow_right.svg b/resources/images/material_arrow_right.svg index e74898bbc..503b199a9 100644 --- a/resources/images/material_arrow_right.svg +++ b/resources/images/material_arrow_right.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/mobile/material_backspace.svg b/resources/images/material_backspace.svg similarity index 90% rename from resources/images/mobile/material_backspace.svg rename to resources/images/material_backspace.svg index ec36e4070..bb496ae1c 100644 --- a/resources/images/mobile/material_backspace.svg +++ b/resources/images/material_backspace.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_block.svg b/resources/images/material_block.svg index 62df84f09..272a2af7e 100644 --- a/resources/images/material_block.svg +++ b/resources/images/material_block.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_close.svg b/resources/images/material_close.svg index 08bd742c9..cb11475d4 100644 --- a/resources/images/material_close.svg +++ b/resources/images/material_close.svg @@ -1 +1 @@ - + diff --git a/resources/images/material_expand_less.svg b/resources/images/material_expand_less.svg index 8032f4a6e..476291c34 100644 --- a/resources/images/material_expand_less.svg +++ b/resources/images/material_expand_less.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_expand_more.svg b/resources/images/material_expand_more.svg index 6d040715b..e36f3b2fd 100644 --- a/resources/images/material_expand_more.svg +++ b/resources/images/material_expand_more.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_mail.svg b/resources/images/material_mail.svg deleted file mode 100644 index 7bb856fc8..000000000 --- a/resources/images/material_mail.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/images/material_person.svg b/resources/images/material_person.svg index a65b4a8e0..6325cb795 100644 --- a/resources/images/material_person.svg +++ b/resources/images/material_person.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/material_refresh.svg b/resources/images/material_refresh.svg index b8d69f402..1cd6ba8ad 100644 --- a/resources/images/material_refresh.svg +++ b/resources/images/material_refresh.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/mobile/device.svg b/resources/images/mobile/device.svg index 8dc7a07c3..a594f0087 100644 --- a/resources/images/mobile/device.svg +++ b/resources/images/mobile/device.svg @@ -1,41 +1,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/mobile/device_tile.svg b/resources/images/mobile/device_tile.svg new file mode 100644 index 000000000..8dc7a07c3 --- /dev/null +++ b/resources/images/mobile/device_tile.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/mobile/material_arrow_left.svg b/resources/images/mobile/material_arrow_left.svg index 7002d8438..8411c78f6 100644 --- a/resources/images/mobile/material_arrow_left.svg +++ b/resources/images/mobile/material_arrow_left.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/mobile/material_view_headline.svg b/resources/images/mobile/material_view_headline.svg index 1ee5f9a0f..7ecb80e92 100644 --- a/resources/images/mobile/material_view_headline.svg +++ b/resources/images/mobile/material_view_headline.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources/images/mobile/mydata.svg b/resources/images/mobile/mydata.svg new file mode 100644 index 000000000..152aa6e82 --- /dev/null +++ b/resources/images/mobile/mydata.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/mobile/no_internet_darkmode.svg b/resources/images/mobile/no_internet_darkmode.svg deleted file mode 100644 index ebc9275c2..000000000 --- a/resources/images/mobile/no_internet_darkmode.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - diff --git a/resources/images/mobile/no_internet_highcontrast.svg b/resources/images/mobile/no_internet_highcontrast.svg deleted file mode 100644 index a569d5a16..000000000 --- a/resources/images/mobile/no_internet_highcontrast.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - diff --git a/resources/images/mobile/phone_nfc_with_card.svg b/resources/images/mobile/phone_nfc_with_card.svg index 7235e985a..fb476d66f 100644 --- a/resources/images/mobile/phone_nfc_with_card.svg +++ b/resources/images/mobile/phone_nfc_with_card.svg @@ -2,4 +2,4 @@ - \ No newline at end of file + diff --git a/resources/images/mobile/x.svg b/resources/images/mobile/x.svg index 6445d732d..bc8aa2654 100644 --- a/resources/images/mobile/x.svg +++ b/resources/images/mobile/x.svg @@ -4,7 +4,7 @@ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 16.9 16.9" overflow="visible" xml:space="preserve"> - diff --git a/resources/images/mydata.svg b/resources/images/mydata_tile.svg similarity index 100% rename from resources/images/mydata.svg rename to resources/images/mydata_tile.svg diff --git a/resources/images/mobile/no_internet_lightmode.svg b/resources/images/no_internet.svg similarity index 100% rename from resources/images/mobile/no_internet_lightmode.svg rename to resources/images/no_internet.svg diff --git a/resources/images/pairingCode.webp b/resources/images/pairingCode.webp deleted file mode 100644 index 56ed05ec0..000000000 Binary files a/resources/images/pairingCode.webp and /dev/null differ diff --git a/resources/images/pin_letter_five_digit_pin.svg b/resources/images/pin_letter_five_digit_pin.svg deleted file mode 100644 index a8a0d5274..000000000 --- a/resources/images/pin_letter_five_digit_pin.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/images/pin_letter_pinpuk.svg b/resources/images/pin_letter_pinpuk.svg deleted file mode 100644 index 7ee0b7364..000000000 --- a/resources/images/pin_letter_pinpuk.svg +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/pin_person.svg b/resources/images/pin_person.svg deleted file mode 100644 index 6917c97af..000000000 --- a/resources/images/pin_person.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/pin_person.webp b/resources/images/pin_person.webp deleted file mode 100644 index 152767886..000000000 Binary files a/resources/images/pin_person.webp and /dev/null differ diff --git a/resources/images/puk_correct_darkmode.svg b/resources/images/puk_correct_darkmode.svg new file mode 100644 index 000000000..59c129172 --- /dev/null +++ b/resources/images/puk_correct_darkmode.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/puk_correct_highcontrast.svg b/resources/images/puk_correct_highcontrast.svg new file mode 100644 index 000000000..d1e36a00a --- /dev/null +++ b/resources/images/puk_correct_highcontrast.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/puk_correct_lightmode.svg b/resources/images/puk_correct_lightmode.svg new file mode 100644 index 000000000..0af8a8dab --- /dev/null +++ b/resources/images/puk_correct_lightmode.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/puk_darkmode.svg b/resources/images/puk_darkmode.svg deleted file mode 100644 index 5d26d99ef..000000000 --- a/resources/images/puk_darkmode.svg +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/puk_darkmode.webp b/resources/images/puk_darkmode.webp deleted file mode 100644 index fbf41df5c..000000000 Binary files a/resources/images/puk_darkmode.webp and /dev/null differ diff --git a/resources/images/puk_highcontrast.svg b/resources/images/puk_highcontrast.svg deleted file mode 100644 index 69fc9bf0c..000000000 --- a/resources/images/puk_highcontrast.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/puk_highcontrast.webp b/resources/images/puk_highcontrast.webp deleted file mode 100644 index 56bc28d1a..000000000 Binary files a/resources/images/puk_highcontrast.webp and /dev/null differ diff --git a/resources/images/puk_lightmode.svg b/resources/images/puk_lightmode.svg deleted file mode 100644 index 3f4ad1917..000000000 --- a/resources/images/puk_lightmode.svg +++ /dev/null @@ -1,371 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/puk_lightmode.webp b/resources/images/puk_lightmode.webp deleted file mode 100644 index 2483d20e8..000000000 Binary files a/resources/images/puk_lightmode.webp and /dev/null differ diff --git a/resources/images/reader/default_more_reader.png b/resources/images/reader/default_more_reader.png deleted file mode 100644 index d0fd5caac..000000000 Binary files a/resources/images/reader/default_more_reader.png and /dev/null differ diff --git a/resources/images/reader/default_no_reader.png b/resources/images/reader/default_no_reader.png deleted file mode 100644 index dada0b8c7..000000000 Binary files a/resources/images/reader/default_no_reader.png and /dev/null differ diff --git a/resources/images/reader/default_reader_mit_ausweis.png b/resources/images/reader/default_reader_mit_ausweis.png deleted file mode 100644 index 49cc2b378..000000000 Binary files a/resources/images/reader/default_reader_mit_ausweis.png and /dev/null differ diff --git a/resources/images/reader/src/img_DefaultReader_card_position.svg b/resources/images/reader/src/img_DefaultReader_card_position.svg deleted file mode 100644 index fe8e0ab02..000000000 --- a/resources/images/reader/src/img_DefaultReader_card_position.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/resources/images/reader/src/img_DefaultReader_mit_ausweis.svg b/resources/images/reader/src/img_DefaultReader_mit_ausweis.svg deleted file mode 100644 index 0c64be9ce..000000000 --- a/resources/images/reader/src/img_DefaultReader_mit_ausweis.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/resources/images/reader/src/img_PersoSim_mit_ausweis.svg b/resources/images/reader/src/img_PersoSim_mit_ausweis.svg deleted file mode 100644 index b387aab81..000000000 --- a/resources/images/reader/src/img_PersoSim_mit_ausweis.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - PersoSim - - diff --git a/resources/images/reader/src/img_Personalausweis.png b/resources/images/reader/src/img_Personalausweis.png deleted file mode 100644 index 448ed85f5..000000000 Binary files a/resources/images/reader/src/img_Personalausweis.png and /dev/null differ diff --git a/resources/images/reader/src/img_RemoteReader_mit_ausweis.svg b/resources/images/reader/src/img_RemoteReader_mit_ausweis.svg deleted file mode 100644 index 6a5fda0de..000000000 --- a/resources/images/reader/src/img_RemoteReader_mit_ausweis.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/resources/images/reader/src/img_Simulator_mit_ausweis.svg b/resources/images/reader/src/img_Simulator_mit_ausweis.svg deleted file mode 100644 index c179dcd9b..000000000 --- a/resources/images/reader/src/img_Simulator_mit_ausweis.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - Simulator - - diff --git a/resources/images/sandglass.webp b/resources/images/sandglass.webp deleted file mode 100644 index 525d0b738..000000000 Binary files a/resources/images/sandglass.webp and /dev/null differ diff --git a/resources/images/reader/src/img_PersoSim.svg b/resources/images/src/img_PersoSim.svg similarity index 83% rename from resources/images/reader/src/img_PersoSim.svg rename to resources/images/src/img_PersoSim.svg index 7d0163b2b..2be85e54b 100644 --- a/resources/images/reader/src/img_PersoSim.svg +++ b/resources/images/src/img_PersoSim.svg @@ -1,5 +1,5 @@ - + PersoSim diff --git a/resources/images/reader/src/img_RemoteReader.svg b/resources/images/src/img_RemoteReader.svg similarity index 100% rename from resources/images/reader/src/img_RemoteReader.svg rename to resources/images/src/img_RemoteReader.svg diff --git a/resources/images/reader/src/img_Remote_Display.png b/resources/images/src/img_Remote_Display.png similarity index 100% rename from resources/images/reader/src/img_Remote_Display.png rename to resources/images/src/img_Remote_Display.png diff --git a/resources/images/reader/src/img_Simulator.svg b/resources/images/src/img_Simulator.svg similarity index 83% rename from resources/images/reader/src/img_Simulator.svg rename to resources/images/src/img_Simulator.svg index 11055c614..7d9d431fb 100644 --- a/resources/images/reader/src/img_Simulator.svg +++ b/resources/images/src/img_Simulator.svg @@ -1,5 +1,5 @@ - + Simulator diff --git a/resources/images/status_warning.svg b/resources/images/status_warning.svg index b9105f577..bc0e3f8b5 100644 --- a/resources/images/status_warning.svg +++ b/resources/images/status_warning.svg @@ -1,12 +1,8 @@ - - - - - - - - - - - + + + + + + + diff --git a/resources/images/transportpin_darkmode.svg b/resources/images/transportpin_darkmode.svg deleted file mode 100644 index 1a3f853f4..000000000 --- a/resources/images/transportpin_darkmode.svg +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/transportpin_darkmode.webp b/resources/images/transportpin_darkmode.webp deleted file mode 100644 index ffc9b8998..000000000 Binary files a/resources/images/transportpin_darkmode.webp and /dev/null differ diff --git a/resources/images/transportpin_highcontrast.svg b/resources/images/transportpin_highcontrast.svg deleted file mode 100644 index fbf8c9a8f..000000000 --- a/resources/images/transportpin_highcontrast.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/transportpin_highcontrast.webp b/resources/images/transportpin_highcontrast.webp deleted file mode 100644 index 8fe58fb0e..000000000 Binary files a/resources/images/transportpin_highcontrast.webp and /dev/null differ diff --git a/resources/images/transportpin_lightmode.svg b/resources/images/transportpin_lightmode.svg deleted file mode 100644 index adb47e7f8..000000000 --- a/resources/images/transportpin_lightmode.svg +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/transportpin_lightmode.webp b/resources/images/transportpin_lightmode.webp deleted file mode 100644 index 642754d28..000000000 Binary files a/resources/images/transportpin_lightmode.webp and /dev/null differ diff --git a/resources/images/trash_icon_old.svg b/resources/images/trash_icon_old.svg deleted file mode 100644 index 7f286a457..000000000 --- a/resources/images/trash_icon_old.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/images/workflow_error_no_sak_darkmode.svg b/resources/images/workflow_error_no_sak_darkmode.svg index 16775573b..24e4437b6 100644 --- a/resources/images/workflow_error_no_sak_darkmode.svg +++ b/resources/images/workflow_error_no_sak_darkmode.svg @@ -21,9 +21,9 @@ - - diff --git a/resources/images/workflow_error_no_sak_lightmode.svg b/resources/images/workflow_error_no_sak_lightmode.svg index 7bd1fb1fb..eb9c5ab25 100644 --- a/resources/images/workflow_error_no_sak_lightmode.svg +++ b/resources/images/workflow_error_no_sak_lightmode.svg @@ -21,9 +21,9 @@ - - diff --git a/resources/images/desktop/workflow_error_sak_connection_darkmode.svg b/resources/images/workflow_error_sak_connection_darkmode.svg similarity index 100% rename from resources/images/desktop/workflow_error_sak_connection_darkmode.svg rename to resources/images/workflow_error_sak_connection_darkmode.svg diff --git a/resources/images/desktop/workflow_error_sak_connection_highcontrast.svg b/resources/images/workflow_error_sak_connection_highcontrast.svg similarity index 100% rename from resources/images/desktop/workflow_error_sak_connection_highcontrast.svg rename to resources/images/workflow_error_sak_connection_highcontrast.svg diff --git a/resources/images/desktop/workflow_error_sak_connection_lightmode.svg b/resources/images/workflow_error_sak_connection_lightmode.svg similarity index 100% rename from resources/images/desktop/workflow_error_sak_connection_lightmode.svg rename to resources/images/workflow_error_sak_connection_lightmode.svg diff --git a/resources/jenkins/check_formatting.sh b/resources/jenkins/check_formatting.sh new file mode 100755 index 000000000..080cc4707 --- /dev/null +++ b/resources/jenkins/check_formatting.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +if [ -z "$BUILD_URL" ]; then +echo "Warning: This script should be called on jenkins only" + exit 1 +fi + +if [ -n "$1" ]; then + PATCH=$1 +else + PATCH="../patch.diff" +fi + +REVISION_CURRENT=$(hg id -i) + +# Check if the current repository state is formatted +cmake --build ../build --target format +STATUS_CURRENT=$(hg status | wc -c) +if [ "$STATUS_CURRENT" != "0" ]; then + echo 'Current repository state is not formatted!' + hg addremove + hg diff + hg commit -m "fix formatting" -s +fi +REVISION_FORMATTED=$(hg id -i) + +if [ ! -f "$PATCH" ] && [ -n "$NO_PATCH" ]; then + if [ "$STATUS_CURRENT" != "0" ]; then + echo 'FORMATTING FAILED' + else + echo 'FORMATTING SUCCEDED' + fi + exit 0 +fi + +# Rollback any changes +hg update -C -r "$REVISION_CURRENT" + +# Apply patch on the current repository state +hg --config patch.eol=auto --config phases.new-commit=secret import -m 'jenkins patch formatting' -d 'today' -u 'jenkins' "$PATCH" +if [ "$?" != "0" ]; then + echo 'FORMATTING FAILED: Patch cannot be applied' + exit 0 +fi + +# Check if the repository state is formatted after the patch +cmake --build ../build --target rebuild_cache +cmake --build ../build --target format +STATUS_PATCH=$(hg status | wc -c) +if [ "$STATUS_PATCH" = "0" ]; then + if [ "$STATUS_CURRENT" != "0" ]; then + echo 'Patch fixes repository formatting.' + fi + echo 'FORMATTING SUCCEDED' + exit 0 +elif [ "$STATUS_CURRENT" = "0" ]; then + echo 'FORMATTING FAILED: Patch is not formatted' + hg diff + hg revert -a -C + exit 0 +fi + +# Checkout formatted repository state +hg update -C -r "$REVISION_FORMATTED" + +# Apply patch on the formatted repository state +hg --config patch.eol=auto --config phases.new-commit=secret import -m 'jenkins patch formatting' -d 'today' -u 'jenkins' "$PATCH" +if [ "$?" != "0" ]; then + echo 'FORMATTING FAILED: Patch cannot be applied, because the current repository state is unformatted and the patch conflicts with the formatted repository state without fixing the formatting!' + exit 0 +fi + +# Check if the patch itself is formatted even though is does not fix +# the unformatted repository state +cmake --build ../build --target rebuild_cache +cmake --build ../build --target format +STATUS_PATCH=$(hg status | wc -c) +if [ "$STATUS_PATCH" != "0" ]; then + echo 'FORMATTING FAILED: Patch is not formatted' + hg diff + hg revert -a -C + exit 0 +fi + +echo 'FORMATTING SUCCEDED: Patch does not introduce new formatting issues.' diff --git a/resources/jenkins/docker/Dockerfile b/resources/jenkins/docker/Dockerfile index d27bf31eb..dd979ef30 100644 --- a/resources/jenkins/docker/Dockerfile +++ b/resources/jenkins/docker/Dockerfile @@ -1,6 +1,6 @@ ARG ALPINE_VERSION=3.17 -FROM alpine:$ALPINE_VERSION as builder +FROM alpine:$ALPINE_VERSION AS builder # Install development stuff RUN apk --no-cache upgrade -a && \ apk --no-cache add patch cmake ccache make ninja g++ pkgconf pcsc-lite-dev binutils-gold eudev-libs \ @@ -57,4 +57,4 @@ USER ausweisapp VOLUME ["/home/ausweisapp/.config"] ENTRYPOINT ["/sbin/tini", "--"] EXPOSE 5900/tcp 24727/tcp 24727/udp -CMD ["AusweisApp", "--address", "0.0.0.0"] +CMD ["AusweisApp", "--address", "0.0.0.0", "--no-logfile"] diff --git a/resources/jenkins/docker/alpine-common/Dockerfile b/resources/jenkins/docker/alpine-common/Dockerfile index 68fa974db..831a0cdc8 100644 --- a/resources/jenkins/docker/alpine-common/Dockerfile +++ b/resources/jenkins/docker/alpine-common/Dockerfile @@ -1,5 +1,4 @@ FROM dev-docker.governikus.de/ausweisapp2/alpine:swarm -MAINTAINER Governikus KG ARG UNCRUSTIFY=0.74.0 ENV NAME=Common LABELS=Common @@ -12,6 +11,7 @@ RUN mkdir /build/ && \ cmake --build build && \ cmake --install build && \ apk --no-cache del deps && \ + apk --no-cache add dos2unix && \ rm -rf /build diff --git a/resources/jenkins/docker/alpine-docs/Dockerfile b/resources/jenkins/docker/alpine-docs/Dockerfile index 054b6cb2c..4fd5992de 100644 --- a/resources/jenkins/docker/alpine-docs/Dockerfile +++ b/resources/jenkins/docker/alpine-docs/Dockerfile @@ -1,10 +1,9 @@ FROM dev-docker.governikus.de/ausweisapp2/alpine:swarm -MAINTAINER Governikus KG ENV NAME=Docs LABELS=Docs -RUN apk --no-cache add py3-setuptools icu poppler zziplib enscript ghostscript texlive-full py3-sphinx py3-sphinx_rtd_theme py3-sphinx-copybutton && \ - pip3 install doc8 +RUN apk --no-cache add py3-setuptools icu poppler zziplib enscript ghostscript texlive-full py3-sphinx py3-sphinx_rtd_theme py3-sphinx-copybutton py3-sphinxcontrib-tabs && \ + pip3 install --break-system-packages doc8 USER governikus diff --git a/resources/jenkins/docker/alpine-linux/Dockerfile b/resources/jenkins/docker/alpine-linux/Dockerfile index 8077d7f64..63618d99d 100644 --- a/resources/jenkins/docker/alpine-linux/Dockerfile +++ b/resources/jenkins/docker/alpine-linux/Dockerfile @@ -1,10 +1,9 @@ FROM dev-docker.governikus.de/ausweisapp2/alpine:swarm -MAINTAINER Governikus KG -ENV NAME=Linux LABELS="Linux g++ clang++" PACKAGES_DIR=/home/governikus/packages +ENV NAME=Linux LABELS="Linux g++ clang++ clazy" PACKAGES_DIR=/home/governikus/packages RUN apk --no-cache add g++ clang clang-analyzer ccache gcovr cloc clazy cppcheck pkgconf pcsc-lite-dev binutils-gold lld \ - py3-setuptools py3-jsonschema mesa-dev libx11-dev libxkbcommon-dev xcb-util-wm-dev xcb-util-image-dev xcb-util-keysyms-dev && \ + py3-setuptools check-jsonschema mesa-dev libx11-dev libxkbcommon-dev xcb-util-wm-dev xcb-util-image-dev xcb-util-keysyms-dev && \ ln -s /usr/libexec/c++-analyzer /usr/local/bin && ln -s /usr/libexec/ccc-analyzer /usr/local/bin USER governikus diff --git a/resources/jenkins/docker/alpine-swarm/Dockerfile b/resources/jenkins/docker/alpine-swarm/Dockerfile index 5c75ef601..661674cef 100644 --- a/resources/jenkins/docker/alpine-swarm/Dockerfile +++ b/resources/jenkins/docker/alpine-swarm/Dockerfile @@ -1,12 +1,11 @@ -FROM alpine:3.18 -MAINTAINER Governikus KG +FROM alpine:3.20 -ARG JENKINS_SWARM_VERSION=3.40 +ARG JENKINS_SWARM_VERSION=3.47 ENV EXECUTOR=3 LABELS= NAME= PASSWORD= RUN adduser governikus -s /bin/sh -D -RUN apk --no-cache add openjdk11-jre-headless cmake samurai make tini mercurial py3-pip py3-hglib wget && \ - pip3 install rbtools +RUN apk --no-cache add openjdk11-jre-headless cmake samurai make tini gnupg mercurial py3-pip wget rbtools && \ + pip3 install --break-system-packages python-hglib RUN wget -O /swarm-client.jar https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/$JENKINS_SWARM_VERSION/swarm-client-$JENKINS_SWARM_VERSION.jar ADD swarm.sh / diff --git a/resources/jenkins/docker/alpine-trigger/Dockerfile b/resources/jenkins/docker/alpine-trigger/Dockerfile index 4271630d7..03cde287c 100644 --- a/resources/jenkins/docker/alpine-trigger/Dockerfile +++ b/resources/jenkins/docker/alpine-trigger/Dockerfile @@ -1,5 +1,4 @@ FROM dev-docker.governikus.de/ausweisapp2/alpine:swarm -MAINTAINER Governikus KG ENV NAME=Trigger LABELS="Trigger Seeder" diff --git a/resources/jenkins/docker/ubuntu-android/Dockerfile b/resources/jenkins/docker/ubuntu-android/Dockerfile index 921bb14eb..9622a0749 100644 --- a/resources/jenkins/docker/ubuntu-android/Dockerfile +++ b/resources/jenkins/docker/ubuntu-android/Dockerfile @@ -1,24 +1,27 @@ FROM dev-docker.governikus.de/ausweisapp2/ubuntu:swarm -MAINTAINER Governikus KG -ARG ANDROID_CMDLINE_TOOLS=10406996 -ARG ANDROID_NDK_VERSION=26.1.10909125 -ARG CMAKE=3.27.7 +ARG ANDROID_CMDLINE_TOOLS=11076708 +ARG ANDROID_NDK_VERSION=27.1.12297006 +ARG CMAKE=3.30.5 +ARG MAVEN=3.9.9 ENV NAME=Android LABELS="Android" PACKAGES_DIR=/home/governikus/packages ENV ANDROID_SDK_ROOT /opt/android-sdk ENV ANDROID_NDK_ROOT $ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION RUN apt-get update && \ - apt-get -y install g++ make ccache ninja-build perl unzip gradle maven patch openjdk-17-jdk-headless && \ + apt-get -y install g++ make ccache ninja-build perl unzip gradle patch openjdk-17-jdk-headless && \ rm -rf /var/lib/apt/lists/* RUN wget https://github.com/Kitware/CMake/releases/download/v$CMAKE/cmake-$CMAKE-Linux-x86_64.sh -O /tmp/cmake.sh && \ sh /tmp/cmake.sh --prefix=/usr --skip-license --exclude-subdir && rm /tmp/cmake.sh +RUN wget https://dlcdn.apache.org/maven/maven-3/$MAVEN/binaries/apache-maven-$MAVEN-bin.tar.gz -O /tmp/maven.tar.gz && \ + tar xf /tmp/maven.tar.gz --strip-components=1 -C /usr/local && rm /tmp/maven.tar.gz + RUN mkdir -p /tmp/dl && cd /tmp/dl && wget -O sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_CMDLINE_TOOLS}_latest.zip && \ unzip sdk.zip && \ - yes | /tmp/dl/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "cmdline-tools;11.0" "build-tools;34.0.0" "platforms;android-33" "platforms;android-34" "ndk;${ANDROID_NDK_VERSION}" && \ + yes | /tmp/dl/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "cmdline-tools;12.0" "build-tools;34.0.0" "platforms;android-35" "ndk;${ANDROID_NDK_VERSION}" && \ rm -rf /tmp/dl USER governikus diff --git a/resources/jenkins/docker/ubuntu-swarm/Dockerfile b/resources/jenkins/docker/ubuntu-swarm/Dockerfile index ae4298168..9595f9a88 100644 --- a/resources/jenkins/docker/ubuntu-swarm/Dockerfile +++ b/resources/jenkins/docker/ubuntu-swarm/Dockerfile @@ -1,7 +1,6 @@ -FROM ubuntu:23.04 -MAINTAINER Governikus KG +FROM ubuntu:24.04 -ARG JENKINS_SWARM_VERSION=3.40 +ARG JENKINS_SWARM_VERSION=3.47 ENV EXECUTOR=3 LABELS= NAME= PASSWORD= ENV DEBIAN_FRONTEND noninteractive ENV PIP_BREAK_SYSTEM_PACKAGES=1 @@ -13,7 +12,7 @@ ENV CCACHE_REMOTE_STORAGE= CCACHE_RESHARE=true CCACHE_REMOTE_ONLY= RUN useradd -m governikus -g users -u 1111 RUN apt-get update && \ apt-get -y install openjdk-17-jre-headless tini python3-pip wget && \ - pip3 install rbtools mercurial python-hglib && \ + pip3 install --break-system-packages rbtools mercurial python-hglib && \ rm -rf /var/lib/apt/lists/* RUN wget -O /swarm-client.jar https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/$JENKINS_SWARM_VERSION/swarm-client-$JENKINS_SWARM_VERSION.jar diff --git a/resources/jenkins/docker/ubuntu-vanilla/Dockerfile b/resources/jenkins/docker/ubuntu-vanilla/Dockerfile index 1822ac91e..cfcfcc107 100644 --- a/resources/jenkins/docker/ubuntu-vanilla/Dockerfile +++ b/resources/jenkins/docker/ubuntu-vanilla/Dockerfile @@ -1,17 +1,10 @@ FROM dev-docker.governikus.de/ausweisapp2/ubuntu:swarm -MAINTAINER Governikus KG ENV NAME=Vanilla LABELS="Vanilla" PACKAGES_DIR=/home/governikus/packages RUN apt-get update && \ apt-get -y install cmake make g++ clazy clang clang-tidy ccache gcovr cloc pkg-config ninja-build binutils-gold lld \ valgrind tree libpcsclite-dev libhttp-parser-dev libssl-dev libudev-dev \ - \ - qml-module-qt-labs-platform qml-module-qtquick-controls2 qml-module-qtquick-controls2 qml-module-qttest \ - qml-module-qtquick-layouts qml-module-qtqml-models2 \ - qtdeclarative5-dev qtquickcontrols2-5-dev qttools5-dev libqt5svg5-dev \ - libqt5websockets5-dev qtconnectivity5-dev \ - \ libqt6opengl6-dev \ libqt6shadertools6-dev \ libqt6svg6-dev \ diff --git a/resources/jenkins/dsl/Builds/Build_Android.groovy b/resources/jenkins/dsl/Builds/Build_Android.groovy index c3a794cbb..e70196c6e 100644 --- a/resources/jenkins/dsl/Builds/Build_Android.groovy +++ b/resources/jenkins/dsl/Builds/Build_Android.groovy @@ -8,22 +8,27 @@ for(ARCH in Constants.AndroidArchAPK) def j = new Build ( name: 'Android_APK_' + ARCH, - libraries: ['Android_' + ARCH], + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'build/dist/**/AusweisApp-*.apk*,build/debug.symbols/*' + artifacts: 'build/dist/**,build/src/libAusweisApp*' ).generate(this) j.with { + wrappers + { + environmentVariables + { + env('QT_ANDROID_KEYSTORE_PATH', '${APK_SIGN_KEYSTORE_DEV}') + env('QT_ANDROID_KEYSTORE_ALIAS', '${APK_SIGN_KEYSTORE_ALIAS_DEV}') + env('QT_ANDROID_KEYSTORE_STORE_PASS', '${APK_SIGN_KEYSTORE_PSW_DEV}') + } + } + steps { - shell("cd source; cmake --preset ci-android-apk -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target apk') - shell('cmake --build build --target verify.signature') - shell('cmake --build build --target dump.apk') + shell("cmake -P source/ci.cmake -- -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") } publishers { @@ -34,10 +39,10 @@ j.with } } qualityGates { - qualityGate { + warningsQualityGate { threshold(1) type('TOTAL') - unstable(false) + criticality('UNSTABLE') } } } @@ -48,29 +53,22 @@ j.with // ----------------------------------------------------------------- AAR -def neededLibraries = [] for(ARCH in Constants.AndroidArchAAR) { - neededLibraries.add('Android_' + ARCH) -} def j = new Build ( - name: 'Android_AAR', - libraries: neededLibraries, + name: 'Android_AAR_' + ARCH, + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'build/dist/**/ausweisapp-*.aar,build/dist/**/ausweisapp-*.pom,build/dist/**/ausweisapp-*.jar,build/**/debug.symbols/*' + artifacts: 'build/dist/**,build/**/debug.symbols/*' ).generate(this) j.with { steps { - shell('cd source; cmake --preset ci-android-aar') - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target aar') - shell("cd build/dist; cmake -DCMD=DEPLOY_NEXUS -P \$WORKSPACE/source/cmake/cmd.cmake") + shell("cmake -P source/ci.cmake -- -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") } publishers { @@ -81,12 +79,44 @@ j.with } } qualityGates { - qualityGate { + warningsQualityGate { threshold(1) type('TOTAL') - unstable(false) + criticality('UNSTABLE') } } } } } + +} + + +def build = new Build + ( + name: 'Android_AAR', + label: 'Android', + artifacts: 'build/dist/**' + ) + +def j = build.generate(this) + +j.with +{ + steps + { + for(ARCH in Constants.AndroidArchAAR) + { + copyArtifacts(build.getSourceJobName('Android_AAR_' + ARCH)) + { + flatten() + buildSelector + { + latestSuccessful(true) + } + } + } + + shell('cmake -P source/ci.cmake') + } +} diff --git a/resources/jenkins/dsl/Builds/Build_Container.groovy b/resources/jenkins/dsl/Builds/Build_Container.groovy index 8980d2781..729e708af 100644 --- a/resources/jenkins/dsl/Builds/Build_Container.groovy +++ b/resources/jenkins/dsl/Builds/Build_Container.groovy @@ -11,37 +11,8 @@ def j = new Build j.with { - wrappers - { - environmentVariables - { - env('TAG', 'dev-${MERCURIAL_REVISION_BRANCH}') - } - } - steps { - shell('docker container prune -f') - - shell(strip('''\ - docker build --pull - -t dev-docker.govkg.de/ausweisapp/sdk:${TAG//-default/""} - --build-arg CCACHE_REMOTE_STORAGE="redis://${CCACHE_REMOTE_STORAGE_HOST}" - source - ''')) - - shell('docker save -o build/AusweisApp-${MERCURIAL_REVISION_SHORT}.tar dev-docker.govkg.de/ausweisapp/sdk:${TAG//-default/""}') - shell('docker push dev-docker.govkg.de/ausweisapp/sdk:${TAG//-default/""}') - - shell('''\ - IMAGES=`docker images --filter "dangling=true" -q | tail -n +50` - if [ -z "$IMAGES" ] - then - echo "No old dangling images" - else - echo "Remove dangling images" - docker rmi -f $IMAGES - fi - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Docker_VNC.groovy b/resources/jenkins/dsl/Builds/Build_Docker_VNC.groovy index 5287eefd0..3dc8a23c0 100644 --- a/resources/jenkins/dsl/Builds/Build_Docker_VNC.groovy +++ b/resources/jenkins/dsl/Builds/Build_Docker_VNC.groovy @@ -11,37 +11,8 @@ def j = new Build j.with { - wrappers - { - environmentVariables - { - env('TAG', 'dev-${MERCURIAL_REVISION_BRANCH}') - } - } - steps { - shell(strip('''\ - docker build --pull - -t dev-docker.govkg.de/ausweisapp/vnc:${TAG//-default/""} - --build-arg CCACHE_REMOTE_STORAGE="redis://${CCACHE_REMOTE_STORAGE_HOST}" - -f source/resources/jenkins/docker/Dockerfile - source - ''')) - - shell('docker run --rm dev-docker.govkg.de/ausweisapp/vnc:${TAG//-default/""} AusweisApp --help') - shell('docker save -o build/AusweisApp-VNC-${MERCURIAL_REVISION_SHORT}.tar dev-docker.govkg.de/ausweisapp/vnc:${TAG//-default/""}') - shell('docker push dev-docker.govkg.de/ausweisapp/vnc:${TAG//-default/""}') - - shell('''\ - IMAGES=`docker images --filter "dangling=true" -q | tail -n +50` - if [ -z "$IMAGES" ] - then - echo "No old dangling images" - else - echo "Remove dangling images" - docker rmi -f $IMAGES - fi - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Docs.groovy b/resources/jenkins/dsl/Builds/Build_Docs.groovy index 19dac6f00..87cdeea8c 100644 --- a/resources/jenkins/dsl/Builds/Build_Docs.groovy +++ b/resources/jenkins/dsl/Builds/Build_Docs.groovy @@ -12,23 +12,6 @@ j.with { steps { - shell('cd source; cmake --preset ci-tools') - - shell('cmake --build build --target notes') - shell('cmake --build build --target notes.latex.pdf') - shell('cd build/docs/notes; cmake -E tar cfJ ../AusweisApp_ReleaseNotes.tar.xz .') - - shell('cmake --build build --target sdk') - shell('cmake --build build --target sdk.latex.pdf') - shell('cd build/docs/sdk/html; cmake -E tar cfJ ../../AusweisApp_SDK.tar.xz .') - - shell('cmake --build build --target failurecodes') - shell('cmake --build build --target failurecodes.latex.pdf') - - shell('cmake --build build --target installation_integration.latex.pdf') - - shell('cmake --build build --target license') - - shell('cmake --build build --target doc8') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_FreeBSD.groovy b/resources/jenkins/dsl/Builds/Build_FreeBSD.groovy index 5f6acfe2c..8a72aa290 100644 --- a/resources/jenkins/dsl/Builds/Build_FreeBSD.groovy +++ b/resources/jenkins/dsl/Builds/Build_FreeBSD.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'FreeBSD', - libraries: ['FreeBSD'], + libraries: 'FreeBSD', label: 'FreeBSD', xunit: true ).generate(this) @@ -11,27 +11,8 @@ def j = new Build j.with { - wrappers - { - environmentVariables - { - env("QT_PLUGIN_PATH", '$WORKSPACE/libs/build/dist/plugins') - } - } - steps { - shell('cd source; cmake -Werror=dev --preset ci-bsd') - - shell('''\ - export LD_LIBRARY_PATH=$WORKSPACE/libs/build/dist/lib:$LD_LIBRARY_PATH - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export QML2_IMPORT_PATH=$WORKSPACE/libs/build/dist/qml - export LD_LIBRARY_PATH=$WORKSPACE/libs/build/dist/lib:$LD_LIBRARY_PATH - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Linux.groovy b/resources/jenkins/dsl/Builds/Build_Linux.groovy index 2fba68fc5..05279afe3 100644 --- a/resources/jenkins/dsl/Builds/Build_Linux.groovy +++ b/resources/jenkins/dsl/Builds/Build_Linux.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Linux', - libraries: ['Linux'], + libraries: 'Linux', label: 'Linux', xunit: true ).generate(this) @@ -11,39 +11,32 @@ def j = new Build j.with { - wrappers - { - environmentVariables - { - env("QT_PLUGIN_PATH", '$WORKSPACE/libs/build/dist/plugins') - } - } - steps { - shell('cd source; cmake --preset ci-linux') - - shell('''\ - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export QML2_IMPORT_PATH=$WORKSPACE/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) - - shell('''\ - DESTDIR=$WORKSPACE/install cmake --install build - '''.stripIndent().trim()) - - shell('cmake --build build --target gcovr') - - shell('cmake --build build --target cloc.report') + shell('cmake -P source/ci.cmake') } publishers { - cobertura('build/gcovr.xml') + recordCoverage + { + sourceDirectories + { + sourceCodeDirectory + { + path('source') + } + } + + tools + { + coverageTool + { + parser('COBERTURA') + pattern('build/gcovr.xml') + } + } + } slocCount { diff --git a/resources/jenkins/dsl/Builds/Build_Linux_Integrated.groovy b/resources/jenkins/dsl/Builds/Build_Linux_Integrated.groovy index 6fff719a0..87066ada3 100644 --- a/resources/jenkins/dsl/Builds/Build_Linux_Integrated.groovy +++ b/resources/jenkins/dsl/Builds/Build_Linux_Integrated.groovy @@ -12,17 +12,6 @@ j.with { steps { - shell('cd source; cmake --preset ci-integrated') - - shell('cmake --build build') - - shell('ctest --test-dir build --output-on-failure') - - shell('cmake --build build --target gcovr') - } - - publishers - { - cobertura('build/gcovr.xml') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_MacOS.groovy b/resources/jenkins/dsl/Builds/Build_MacOS.groovy index 5b1326e38..10ea79c19 100644 --- a/resources/jenkins/dsl/Builds/Build_MacOS.groovy +++ b/resources/jenkins/dsl/Builds/Build_MacOS.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'MacOS', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', xunit: true ).generate(this) @@ -13,22 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - export QT_PLUGIN_PATH=${WORKSPACE}/libs/build/dist/plugins - export QML2_IMPORT_PATH=${WORKSPACE}/libs/build/dist/qml - ctest -C Debug --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_MacOS_DMG_PKG.groovy b/resources/jenkins/dsl/Builds/Build_MacOS_DMG_PKG.groovy index 2751fd135..adc1b5bca 100644 --- a/resources/jenkins/dsl/Builds/Build_MacOS_DMG_PKG.groovy +++ b/resources/jenkins/dsl/Builds/Build_MacOS_DMG_PKG.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'MacOS_DMG_PKG', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', artifacts: 'build/*.dmg,build/*.pkg' ).generate(this) @@ -13,19 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos-release') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build --target package --config MinSizeRel - '''.stripIndent().trim()) - - shell('cd build/_CPack_Packages/Darwin/; codesign -vvvv **/**/*.app') - shell('cd build/_CPack_Packages/Darwin/DragNDrop; spctl -a -vv **/*.app') - - shell('cd build/; cmake -P ../source/cmake/Notarization.cmake') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_MacOS_Integrated.groovy b/resources/jenkins/dsl/Builds/Build_MacOS_Integrated.groovy index d2e1d9a54..1967462db 100644 --- a/resources/jenkins/dsl/Builds/Build_MacOS_Integrated.groovy +++ b/resources/jenkins/dsl/Builds/Build_MacOS_Integrated.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'MacOS_Integrated', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', xunit: true ).generate(this) @@ -13,21 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos-integrated') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - export QT_PLUGIN_PATH=${WORKSPACE}/libs/build/dist/plugins - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_SonarQube.groovy b/resources/jenkins/dsl/Builds/Build_SonarQube.groovy index 2452099ed..5a4a3c95e 100644 --- a/resources/jenkins/dsl/Builds/Build_SonarQube.groovy +++ b/resources/jenkins/dsl/Builds/Build_SonarQube.groovy @@ -24,31 +24,6 @@ j.with steps { - shell('mkdir -p cache') - - shell('cmake -P source/cmake/prepare_sonarqube_env.cmake') - - shell('cd source; cmake --preset ci-linux') - - shell('''\ - cd build; - $WORKSPACE/sonarqubetools/dependency-check/bin/dependency-check.sh --enableExperimental -f HTML -f JSON --scan $WORKSPACE/source/cmake --noupdate --connectionString=jdbc:mariadb://dependency-check-db.govkg.de/dependencycheck --dbUser=${DEPENDENCY_CHECK_USER} --dbPassword=${DEPENDENCY_CHECK_PASSWORD} --dbDriverName=org.mariadb.jdbc.Driver - '''.stripIndent().trim()) - - shell('$WORKSPACE/sonarqubetools/sonar-build-wrapper/build-wrapper-linux-x86-64 --out-dir build cmake --build build') - - shell('ctest -LE qml -E Test_ui_qml_Qml --test-dir build --output-on-failure') - - shell('cmake --build build --target gcovr.sonar') - - shell(strip('''\ - cd build; - $WORKSPACE/sonarqubetools/sonar-scanner/bin/sonar-scanner - -Dsonar.scanner.metadataFilePath=${WORKSPACE}/tmp/sonar-metadata.txt - -Dsonar.branch.name=${MERCURIAL_REVISION_BRANCH} - -Dsonar.login=${SONARQUBE_TOKEN} - -Dsonar.qualitygate.wait=true - -Dsonar.qualitygate.timeout=90 - ''')) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Source.groovy b/resources/jenkins/dsl/Builds/Build_Source.groovy index 8f6690672..c4314ee63 100644 --- a/resources/jenkins/dsl/Builds/Build_Source.groovy +++ b/resources/jenkins/dsl/Builds/Build_Source.groovy @@ -4,7 +4,7 @@ def j = new Build ( name: 'Source', label: 'Common', - artifacts: 'build/*.tar.gz' + artifacts: 'build/*.tar.gz*' ).generate(this) @@ -12,7 +12,6 @@ j.with { steps { - shell('cd source; cmake --preset ci-tools') - shell('cmake --build build --target package_source') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Translation.groovy b/resources/jenkins/dsl/Builds/Build_Translation.groovy index e3f196051..15f8b1f1f 100644 --- a/resources/jenkins/dsl/Builds/Build_Translation.groovy +++ b/resources/jenkins/dsl/Builds/Build_Translation.groovy @@ -4,7 +4,7 @@ def j = new Build ( name: 'Translation', excludePattern: '', - libraries: ['Linux'], + libraries: 'Linux', label: 'Linux', artifacts: 'source/resources/translations/*.ts' ).generate(this) diff --git a/resources/jenkins/dsl/Builds/Build_Win64_GNU.groovy b/resources/jenkins/dsl/Builds/Build_Win64_GNU.groovy index c8225367d..490b79182 100644 --- a/resources/jenkins/dsl/Builds/Build_Win64_GNU.groovy +++ b/resources/jenkins/dsl/Builds/Build_Win64_GNU.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Win64_GNU', - libraries: ['Win64_GNU'], + libraries: 'Win64_GNU', label: 'Windows', xunit: true, weight: 2 @@ -14,16 +14,6 @@ j.with { steps { - batchFile('cd source & cmake --preset ci-win') - - batchFile('cmake --build build') - - batchFile('''\ - set PATH=%WORKSPACE%/libs/build/dist/bin;%PATH% - set PATH=%WORKSPACE%/build/src;%WORKSPACE%/build/test/helper;%PATH% - set QT_PLUGIN_PATH=%WORKSPACE%/libs/build/dist/plugins - set QML2_IMPORT_PATH=%WORKSPACE%/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Win64_GNU_MSI.groovy b/resources/jenkins/dsl/Builds/Build_Win64_GNU_MSI.groovy index 7a145aa31..9c6777202 100644 --- a/resources/jenkins/dsl/Builds/Build_Win64_GNU_MSI.groovy +++ b/resources/jenkins/dsl/Builds/Build_Win64_GNU_MSI.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Win64_GNU_MSI', - libraries: ['Win64_GNU'], + libraries: 'Win64_GNU', label: 'Windows', artifacts: 'build/*.msi', weight: 2 @@ -14,12 +14,6 @@ j.with { steps { - batchFile('cd source & cmake --preset ci-win-release') - - batchFile('cmake --build build --target package') - - batchFile('cmake --build build --target package.sign') - - batchFile('cmake -DCMD=CHECK_WIX_WARNING -DFILE=build/_CPack_Packages/win64/WIX/wix.log -P source/cmake/cmd.cmake') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Win64_MSVC.groovy b/resources/jenkins/dsl/Builds/Build_Win64_MSVC.groovy index cd9d2ad5a..c3f7722e4 100644 --- a/resources/jenkins/dsl/Builds/Build_Win64_MSVC.groovy +++ b/resources/jenkins/dsl/Builds/Build_Win64_MSVC.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Win64_MSVC', - libraries: ['Win64_MSVC_dev'], + libraries: 'Win64_MSVC_dev', label: 'MSVC', xunit: true ).generate(this) @@ -13,21 +13,6 @@ j.with { steps { - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build - '''.stripIndent().trim()) - - batchFile('''\ - set PATH=%WORKSPACE%/libs/build/dist/bin;%PATH% - set QT_PLUGIN_PATH=%WORKSPACE%/libs/build/dist/plugins - set QML2_IMPORT_PATH=%WORKSPACE%/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI.groovy b/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI.groovy index 3a48b8151..eef336b3d 100644 --- a/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI.groovy +++ b/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Win64_MSVC_MSI', - libraries: ['Win64_MSVC'], + libraries: 'Win64_MSVC', label: 'MSVC', artifacts: 'build/*.msi' ).generate(this) @@ -13,21 +13,6 @@ j.with { steps { - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win-release - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package.sign - '''.stripIndent().trim()) - - batchFile('cmake -DCMD=CHECK_WIX_WARNING -DFILE=build/_CPack_Packages/win64/WIX/wix.log -P source/cmake/cmd.cmake') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI_dev.groovy b/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI_dev.groovy index a57a30c00..50bf5f0e6 100644 --- a/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI_dev.groovy +++ b/resources/jenkins/dsl/Builds/Build_Win64_MSVC_MSI_dev.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'Win64_MSVC_MSI_dev', - libraries: ['Win64_MSVC_dev'], + libraries: 'Win64_MSVC_dev', label: 'MSVC', artifacts: 'build/*.msi' ).generate(this) @@ -13,21 +13,6 @@ j.with { steps { - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win-debug - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package.sign - '''.stripIndent().trim()) - - batchFile('cmake -DCMD=CHECK_WIX_WARNING -DFILE=build/_CPack_Packages/win64/WIX/wix.log -P source/cmake/cmd.cmake') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_Win64_clang_MSI.groovy b/resources/jenkins/dsl/Builds/Build_Win64_clang_MSI.groovy new file mode 100644 index 000000000..2c8908fb8 --- /dev/null +++ b/resources/jenkins/dsl/Builds/Build_Win64_clang_MSI.groovy @@ -0,0 +1,25 @@ +import common.Build +import common.Build.JobType + +def j = new Build + ( + name: 'Win64_clang_MSI', + libraries: 'Win64_MSVC', + label: 'MSVC', + artifacts: 'build/*.msi', + jobType: JobType.Matrix + ).generate(this) + + +j.with +{ + axes + { + label('Compiler', 'clang-cl') + } + + steps + { + batchFile('cmake -P source/ci.cmake -- -DCMAKE_CXX_COMPILER=%Compiler%') + } +} diff --git a/resources/jenkins/dsl/Builds/Build_iOS_Framework.groovy b/resources/jenkins/dsl/Builds/Build_iOS_Framework.groovy index 14d2546a3..3c0bc5de8 100644 --- a/resources/jenkins/dsl/Builds/Build_iOS_Framework.groovy +++ b/resources/jenkins/dsl/Builds/Build_iOS_Framework.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'iOS_Framework', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,11 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_iOS_IPA.groovy b/resources/jenkins/dsl/Builds/Build_iOS_IPA.groovy index 9a914966d..d4b89712f 100644 --- a/resources/jenkins/dsl/Builds/Build_iOS_IPA.groovy +++ b/resources/jenkins/dsl/Builds/Build_iOS_IPA.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'iOS_IPA', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', artifacts: 'build/*.ipa,build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,12 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios') - - shell('cd build; xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -scheme AusweisAppBinary archive') - shell('cd build; xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -exportArchive -exportOptionsPlist exportOptions.plist -exportPath .') - shell('cd build; xcodebuild -configuration MinSizeRel -target ipa') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_iOS_Simulator_Framework.groovy b/resources/jenkins/dsl/Builds/Build_iOS_Simulator_Framework.groovy index d11d6fdf7..bf7328e6b 100644 --- a/resources/jenkins/dsl/Builds/Build_iOS_Simulator_Framework.groovy +++ b/resources/jenkins/dsl/Builds/Build_iOS_Simulator_Framework.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'iOS_Simulator_Framework', - libraries: ['iOS_Simulator'], + libraries: 'iOS_Simulator', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,11 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_iOS_Simulator_arm64_Framework.groovy b/resources/jenkins/dsl/Builds/Build_iOS_Simulator_arm64_Framework.groovy index 3a4207d69..cb1d72ec4 100644 --- a/resources/jenkins/dsl/Builds/Build_iOS_Simulator_arm64_Framework.groovy +++ b/resources/jenkins/dsl/Builds/Build_iOS_Simulator_arm64_Framework.groovy @@ -3,7 +3,7 @@ import common.Build def j = new Build ( name: 'iOS_Simulator_arm64_Framework', - libraries: ['iOS_Simulator_arm64'], + libraries: 'iOS_Simulator_arm64', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,11 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator-arm64') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Builds/Build_iOS_SwiftPackage.groovy b/resources/jenkins/dsl/Builds/Build_iOS_SwiftPackage.groovy index 5b741716d..af12c81bb 100644 --- a/resources/jenkins/dsl/Builds/Build_iOS_SwiftPackage.groovy +++ b/resources/jenkins/dsl/Builds/Build_iOS_SwiftPackage.groovy @@ -16,7 +16,8 @@ j.with { copyArtifacts(build.getSourceJobName('iOS_Framework')) { - targetDirectory('build/arm64') + targetDirectory('arm64') + flatten() buildSelector { latestSuccessful(true) @@ -25,7 +26,8 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_Framework')) { - targetDirectory('build/x86_64-simulator') + targetDirectory('x86_64-simulator') + flatten() buildSelector { latestSuccessful(true) @@ -34,13 +36,14 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_arm64_Framework')) { - targetDirectory('build/arm64-simulator') + targetDirectory('arm64-simulator') + flatten() buildSelector { latestSuccessful(true) } } - shell('cd build; cmake -P ../source/cmake/SwiftPackage.cmake') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Libraries/Libs_Android.groovy b/resources/jenkins/dsl/Libraries/Libs_Android.groovy index 50339f6d8..146cd3f4f 100644 --- a/resources/jenkins/dsl/Libraries/Libs_Android.groovy +++ b/resources/jenkins/dsl/Libraries/Libs_Android.groovy @@ -1,7 +1,7 @@ import common.Library import common.Constants -for(ARCH in Constants.AndroidArch) +for(ARCH in Constants.AndroidArchLibs) { def j = new Library diff --git a/resources/jenkins/dsl/Releases/Release_Android.groovy b/resources/jenkins/dsl/Releases/Release_Android.groovy index ccc21ef07..65fd38da6 100644 --- a/resources/jenkins/dsl/Releases/Release_Android.groovy +++ b/resources/jenkins/dsl/Releases/Release_Android.groovy @@ -10,9 +10,9 @@ for(ARCH in Constants.AndroidArchAPK) def j = new Release ( name: 'Android_APK_' + ARCH, - libraries: ['Android_' + ARCH], + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'libs/build/Toolchain_*,build/dist/**/AusweisApp-*.apk*,build/debug.symbols/*' + artifacts: 'libs/Toolchain_*,build/dist/**,build/src/libAusweisApp*' ).generate(this) @@ -24,22 +24,26 @@ j.with booleanParam("BUILD_PREVIEW", false, "Use com.governikus.ausweisapp2.dev as package name") } + wrappers + { + environmentVariables + { + env('QT_ANDROID_KEYSTORE_PATH', '${APK_SIGN_KEYSTORE}') + env('QT_ANDROID_KEYSTORE_ALIAS', '${APK_SIGN_KEYSTORE_ALIAS}') + env('QT_ANDROID_KEYSTORE_STORE_PASS', '${APK_SIGN_KEYSTORE_PSW}') + } + } + steps { buildDescription('', 'ANDROID_VERSION_CODE: ${ANDROID_VERSION_CODE}
BUILD_PREVIEW: ${BUILD_PREVIEW}') shell(strip("""\ - cd source; cmake --preset ci-android-apk-release + cmake -P source/ci.cmake -- -DCMAKE_ANDROID_ARCH_ABI=${ARCH} -DANDROID_VERSION_CODE=\${ANDROID_VERSION_CODE} -DBUILD_PREVIEW=\${BUILD_PREVIEW} """)) - - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target apk') - shell('cmake --build build --target verify.signature') - shell('cmake --build build --target dump.apk') } } @@ -47,18 +51,15 @@ j.with // ----------------------------------------------------------------- AAR -def neededLibraries = [] for(ARCH in Constants.AndroidArchAAR) { - neededLibraries.add('Android_' + ARCH) -} def j = new Release ( - name: 'Android_AAR', - libraries: neededLibraries, + name: 'Android_AAR_' + ARCH, + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'libs/build/Toolchain_*,build/**/dist/**/ausweisapp-*.aar,build/**/dist/**/ausweisapp-*.pom,build/**/dist/**/ausweisapp-*.jar,build/**/debug.symbols/*' + artifacts: 'libs/Toolchain_*,build/dist/**,build/**/debug.symbols/*' ).generate(this) j.with @@ -73,13 +74,58 @@ j.with buildDescription('', 'BUILD_PREVIEW: ${BUILD_PREVIEW}') shell(strip("""\ - cd source; cmake --preset ci-android-aar + cmake -P source/ci.cmake -- + -DCMAKE_ANDROID_ARCH_ABI=${ARCH} -DBUILD_PREVIEW=\${BUILD_PREVIEW} """)) + } +} + +} + - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target aar') - shell("cd build/dist; cmake -DCMD=DEPLOY_NEXUS -P \$WORKSPACE/source/cmake/cmd.cmake") +def build = new Release + ( + name: 'Android_AAR', + label: 'Android', + artifacts: 'build/dist/**' + ) + +def j = build.generate(this) + +j.with +{ + parameters + { + booleanParam("PUBLISH", false, "Publish to maven central") + + for(ARCH in Constants.AndroidArchAAR) + { + buildSelectorParam(build.getSourceJobNameParam('Android_AAR_' + ARCH)) + { + defaultBuildSelector + { + latestSuccessful(true) + } + description('Build of ' + ARCH) + } + } + } + + steps + { + for(ARCH in Constants.AndroidArchAAR) + { + copyArtifacts(build.getSourceJobName('Android_AAR_' + ARCH)) + { + flatten() + buildSelector + { + buildParameter(build.getSourceJobNameParam('Android_AAR_' + ARCH)) + } + } + } + + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_Container.groovy b/resources/jenkins/dsl/Releases/Release_Container.groovy index dbdf112f9..3bcfb4559 100644 --- a/resources/jenkins/dsl/Releases/Release_Container.groovy +++ b/resources/jenkins/dsl/Releases/Release_Container.groovy @@ -18,28 +18,6 @@ j.with steps { - shell(strip('''\ - docker build --pull - -t dev-docker.govkg.de/ausweisapp/sdk:${changeset} - --build-arg CCACHE_REMOTE_STORAGE="redis://${CCACHE_REMOTE_STORAGE_HOST}" - source - ''')) - - shell('docker save -o build/AusweisApp-${changeset}.tar dev-docker.govkg.de/ausweisapp/sdk:${changeset}') - shell('docker push dev-docker.govkg.de/ausweisapp/sdk:${changeset}') - - conditionalSteps - { - condition - { - booleanCondition('${LATEST}') - } - - steps - { - shell('docker tag dev-docker.govkg.de/ausweisapp/sdk:${changeset} dev-docker.govkg.de/ausweisapp/sdk:latest') - shell('docker push dev-docker.govkg.de/ausweisapp/sdk:latest') - } - } + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_Docs.groovy b/resources/jenkins/dsl/Releases/Release_Docs.groovy index f7c7d7b22..fa67f9194 100644 --- a/resources/jenkins/dsl/Releases/Release_Docs.groovy +++ b/resources/jenkins/dsl/Releases/Release_Docs.groovy @@ -17,21 +17,6 @@ j.with steps { - shell('cd source; cmake --preset ci-tools -DENABLE_DVCS=\${ENABLE_DVCS}') - - shell('cmake --build build --target notes') - shell('cmake --build build --target notes.latex.pdf') - shell('cd build/docs/notes; cmake -E tar cfJ ../AusweisApp_ReleaseNotes.tar.xz .') - - shell('cmake --build build --target sdk') - shell('cmake --build build --target sdk.latex.pdf') - shell('cd build/docs/sdk/html; cmake -E tar cfJ ../../AusweisApp_SDK.tar.xz .') - - shell('cmake --build build --target failurecodes') - shell('cmake --build build --target failurecodes.latex.pdf') - - shell('cmake --build build --target installation_integration.latex.pdf') - - shell('cmake --build build --target license') + shell('cmake -P source/ci.cmake -- -DENABLE_DVCS=\${ENABLE_DVCS}') } } diff --git a/resources/jenkins/dsl/Releases/Release_MacOS.groovy b/resources/jenkins/dsl/Releases/Release_MacOS.groovy index 7a491ff87..61742b33a 100644 --- a/resources/jenkins/dsl/Releases/Release_MacOS.groovy +++ b/resources/jenkins/dsl/Releases/Release_MacOS.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'MacOS_DMG_PKG', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', - artifacts: 'libs/build/Toolchain_*,build/*.dmg,build/*.pkg,build/*.zip' + artifacts: 'libs/Toolchain_*,build/*.dmg,build/*.pkg,build/*.zip' ).generate(this) @@ -13,39 +13,13 @@ j.with { parameters { - booleanParam("UPLOAD", true, "Upload AusweisApp to the AppStore") + booleanParam("USE_DISTRIBUTION_PROFILE", true, "Use the provisioning profile necessary to upload AusweisApp to the AppStore") } steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') + buildDescription('', 'USE_DISTRIBUTION_PROFILE: ${USE_DISTRIBUTION_PROFILE}') - shell('cd source; cmake --preset ci-macos-release') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build --target package --config MinSizeRel - '''.stripIndent().trim()) - - shell('cd build/src/MinSizeRel/; cmake -E tar cf ../../AusweisApp.app.dSYM.zip --format=zip AusweisApp.app.dSYM') - - shell('cd build/_CPack_Packages/Darwin/; codesign -vvvv **/**/*.app') - shell('cd build/_CPack_Packages/Darwin/DragNDrop; spctl -a -vv **/*.app') - - shell('cd build/; cmake -P ../source/cmake/Notarization.cmake') - - conditionalSteps - { - condition - { - booleanCondition('${UPLOAD}') - } - - steps - { - shell('cd build/; xcrun altool -t osx --upload-app -u "ausweisapp@governikus.com" -p @env:PASSWORD -f *.pkg') - } - } + shell('cmake -P source/ci.cmake -- -DUSE_DISTRIBUTION_PROFILE=${USE_DISTRIBUTION_PROFILE}') } } diff --git a/resources/jenkins/dsl/Releases/Release_Source.groovy b/resources/jenkins/dsl/Releases/Release_Source.groovy index 4a19db4cd..9630b18bd 100644 --- a/resources/jenkins/dsl/Releases/Release_Source.groovy +++ b/resources/jenkins/dsl/Releases/Release_Source.groovy @@ -4,7 +4,7 @@ def j = new Release ( name: 'Source', label: 'Common', - artifacts: 'build/*.tar.gz' + artifacts: 'build/*.tar.gz*' ).generate(this) @@ -12,7 +12,6 @@ j.with { steps { - shell('cd source; cmake --preset ci-tools') - shell('cmake --build build --target package_source') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_Win64_GNU.groovy b/resources/jenkins/dsl/Releases/Release_Win64_GNU.groovy index 4fc281a17..4c51d8e85 100644 --- a/resources/jenkins/dsl/Releases/Release_Win64_GNU.groovy +++ b/resources/jenkins/dsl/Releases/Release_Win64_GNU.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'Win64_GNU_MSI', - libraries: ['Win64_GNU'], + libraries: 'Win64_GNU', label: 'Windows', - artifacts: 'libs/build/Toolchain_*,build/*.msi', + artifacts: 'libs/Toolchain_*,build/*.msi', weight: 2 ).generate(this) @@ -14,10 +14,6 @@ j.with { steps { - batchFile('cd source & cmake --preset ci-win-release') - - batchFile('cmake --build build --target package') - - batchFile('cmake --build build --target package.sign') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_Win64_MSVC.groovy b/resources/jenkins/dsl/Releases/Release_Win64_MSVC.groovy index 6fe7ee2d0..3e7a8cbd2 100644 --- a/resources/jenkins/dsl/Releases/Release_Win64_MSVC.groovy +++ b/resources/jenkins/dsl/Releases/Release_Win64_MSVC.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'Win64_MSVC_MSI', - libraries: ['Win64_MSVC'], + libraries: 'Win64_MSVC', label: 'MSVC', - artifacts: 'libs/build/Toolchain_*,build/*.msi' + artifacts: 'libs/Toolchain_*,build/*.msi' ).generate(this) @@ -13,19 +13,6 @@ j.with { steps { - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win-release - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package.sign - '''.stripIndent().trim()) + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_iOS.groovy b/resources/jenkins/dsl/Releases/Release_iOS.groovy index 717edb9d3..73e26caa6 100644 --- a/resources/jenkins/dsl/Releases/Release_iOS.groovy +++ b/resources/jenkins/dsl/Releases/Release_iOS.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'iOS_IPA', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', - artifacts: 'libs/build/Toolchain_*,build/*.ipa,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' + artifacts: 'libs/Toolchain_*,build/*.ipa,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' ).generate(this) @@ -20,28 +20,6 @@ j.with { buildDescription('', 'USE_DISTRIBUTION_PROFILE: ${USE_DISTRIBUTION_PROFILE}') - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios -DUSE_DISTRIBUTION_PROFILE=${USE_DISTRIBUTION_PROFILE}') - - shell('cd build; xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -scheme AusweisAppBinary archive') - shell('cd build; xcodebuild -configuration MinSizeRel -archivePath AusweisApp.xcarchive -exportArchive -exportOptionsPlist exportOptions.plist -exportPath .') - shell('cmake -E tar cf AusweisApp_BuildDir.tar.zstd --zstd build') - shell('cd build; xcodebuild -configuration MinSizeRel -target ipa') - - conditionalSteps - { - condition - { - booleanCondition('${USE_DISTRIBUTION_PROFILE}') - } - - steps - { - shell('cd build; xcrun altool -t ios --validate-app --verbose -u "ausweisapp@governikus.com" -p @env:PASSWORD -f *.ipa') - - shell('cd build; xcrun altool -t ios --upload-app -u "ausweisapp@governikus.com" -p @env:PASSWORD -f *.ipa') - } - } + shell('cmake -P source/ci.cmake -- -DUSE_DISTRIBUTION_PROFILE=${USE_DISTRIBUTION_PROFILE}') } } diff --git a/resources/jenkins/dsl/Releases/Release_iOS_Framework.groovy b/resources/jenkins/dsl/Releases/Release_iOS_Framework.groovy index 11873d865..c0f682452 100644 --- a/resources/jenkins/dsl/Releases/Release_iOS_Framework.groovy +++ b/resources/jenkins/dsl/Releases/Release_iOS_Framework.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'iOS_Framework', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', - artifacts: 'libs/build/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' + artifacts: 'libs/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' ).generate(this) @@ -13,12 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cmake -E tar cf AusweisApp_BuildDir.tar.zstd --zstd build') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_iOS_Simulator_Framework.groovy b/resources/jenkins/dsl/Releases/Release_iOS_Simulator_Framework.groovy index e2d005452..6232a20b1 100644 --- a/resources/jenkins/dsl/Releases/Release_iOS_Simulator_Framework.groovy +++ b/resources/jenkins/dsl/Releases/Release_iOS_Simulator_Framework.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'iOS_Simulator_Framework', - libraries: ['iOS_Simulator'], + libraries: 'iOS_Simulator', label: 'iOS', - artifacts: 'libs/build/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' + artifacts: 'libs/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' ).generate(this) @@ -13,12 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cmake -E tar cf AusweisApp_BuildDir.tar.zstd --zstd build') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_iOS_Simulator_arm64_Framework.groovy b/resources/jenkins/dsl/Releases/Release_iOS_Simulator_arm64_Framework.groovy index bbcac9e30..ac0034391 100644 --- a/resources/jenkins/dsl/Releases/Release_iOS_Simulator_arm64_Framework.groovy +++ b/resources/jenkins/dsl/Releases/Release_iOS_Simulator_arm64_Framework.groovy @@ -3,9 +3,9 @@ import common.Release def j = new Release ( name: 'iOS_Simulator_arm64_Framework', - libraries: ['iOS_Simulator_arm64'], + libraries: 'iOS_Simulator_arm64', label: 'iOS', - artifacts: 'libs/build/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' + artifacts: 'libs/Toolchain_*,build/*.zip,build/*.bcsymbolmap,*.tar.zstd' ).generate(this) @@ -13,12 +13,6 @@ j.with { steps { - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator-arm64') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cmake -E tar cf AusweisApp_BuildDir.tar.zstd --zstd build') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Releases/Release_iOS_SwiftPackage.groovy b/resources/jenkins/dsl/Releases/Release_iOS_SwiftPackage.groovy index 57a53da96..1232d01f4 100644 --- a/resources/jenkins/dsl/Releases/Release_iOS_SwiftPackage.groovy +++ b/resources/jenkins/dsl/Releases/Release_iOS_SwiftPackage.groovy @@ -45,7 +45,8 @@ j.with { copyArtifacts(build.getSourceJobName('iOS_Framework')) { - targetDirectory('build/arm64') + targetDirectory('arm64') + flatten() buildSelector { buildParameter('iOS_Framework_Build') @@ -54,7 +55,8 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_Framework')) { - targetDirectory('build/x86_64-simulator') + targetDirectory('x86_64-simulator') + flatten() buildSelector { buildParameter('iOS_Simulator_Framework_Build') @@ -63,13 +65,14 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_arm64_Framework')) { - targetDirectory('build/arm64-simulator') + targetDirectory('arm64-simulator') + flatten() buildSelector { buildParameter('iOS_Simulator_arm64_Framework_Build') } } - shell('cd build; cmake -P ../source/cmake/SwiftPackage.cmake') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Android.groovy b/resources/jenkins/dsl/Reviews/Review_Android.groovy index ca6443e13..25d93ec3f 100644 --- a/resources/jenkins/dsl/Reviews/Review_Android.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Android.groovy @@ -8,9 +8,9 @@ for(ARCH in Constants.AndroidArchAPKReview) def j = new Review ( name: 'Android_APK_' + ARCH, - libraries: ['Android_' + ARCH], + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'build/dist/**/AusweisApp-*.apk*,build/debug.symbols/*' + artifacts: 'build/dist/**,build/src/libAusweisApp*' ).generate(this) @@ -18,14 +18,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell("cd source; cmake --preset ci-android-apk-review -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target apk') - shell('cmake --build build --target verify.signature') - shell('cmake --build build --target dump.apk') + shell("cmake -P source/ci.cmake -- -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") } publishers { @@ -36,10 +29,10 @@ j.with } } qualityGates { - qualityGate { + warningsQualityGate { threshold(1) type('TOTAL') - unstable(false) + criticality('UNSTABLE') } } } @@ -50,29 +43,22 @@ j.with // ----------------------------------------------------------------- AAR -def neededLibraries = [] -for(ARCH in Constants.AndroidArchAAR) +for(ARCH in Constants.AndroidArchAARReview) { - neededLibraries.add('Android_' + ARCH) -} def j = new Review ( - name: 'Android_AAR', - libraries: neededLibraries, + name: 'Android_AAR_' + ARCH, + libraries: 'Android_' + ARCH, label: 'Android', - artifacts: 'build/dist/**/ausweisapp-*.aar,build/dist/**/ausweisapp-*.pom,build/dist/**/ausweisapp-*.jar,build/debug.symbols/*' + artifacts: 'build/dist/**,build/debug.symbols/*' ).generate(this) j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - shell('cd source; cmake --preset ci-android-aar-review') - shell('cmake --build build') - shell('cmake --install build') - shell('cmake --build build --target aar') + shell("cmake -P source/ci.cmake -- -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") } publishers { @@ -83,12 +69,52 @@ j.with } } qualityGates { - qualityGate { + warningsQualityGate { threshold(1) type('TOTAL') - unstable(false) + criticality('UNSTABLE') + } + } + } + } +} + +} + + +def build = new Review + ( + name: 'Android_AAR', + label: 'Common', + artifacts: 'build/dist/**' + ) + +def j = build.generate(this) + +j.with +{ + parameters + { + for(ARCH in Constants.AndroidArchAARReview) + { + stringParam(build.getSourceJobNameParam('Android_AAR_' + ARCH), '', 'Build of ' + ARCH) + } + } + + steps + { + for(ARCH in Constants.AndroidArchAARReview) + { + copyArtifacts(build.getSourceJobName('Android_AAR_' + ARCH)) + { + flatten() + buildSelector + { + buildNumber('${' + build.getSourceJobNameParam('Android_AAR_' + ARCH) + '}') } } } + + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Configuration.groovy b/resources/jenkins/dsl/Reviews/Review_Configuration.groovy index f5438f734..8d5d9eb88 100644 --- a/resources/jenkins/dsl/Reviews/Review_Configuration.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Configuration.groovy @@ -4,7 +4,7 @@ import common.Build.JobType def j = new Review ( name: 'Configuration', - libraries: ['Linux'], + libraries: 'Linux', label: 'Linux', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -14,23 +14,8 @@ def j = new Review j.with { - wrappers - { - environmentVariables - { - env("QT_PLUGIN_PATH", '$WORKSPACE/libs/build/dist/plugins') - } - } - steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('cd source; cmake --preset ci-linux') - - shell('cmake --build build --target ALL_Test_configuration') - - shell('ctest --test-dir build --output-on-failure -R Test_configuration') - shell('ctest --test-dir build --output-on-failure -L json') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Container.groovy b/resources/jenkins/dsl/Reviews/Review_Container.groovy index 85319b982..6103607f7 100644 --- a/resources/jenkins/dsl/Reviews/Review_Container.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Container.groovy @@ -13,17 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell(strip('''\ - docker build - -t dev-docker.govkg.de/ausweisapp/sdk:${BUILD_TAG} - --build-arg CCACHE_REMOTE_STORAGE="redis://${CCACHE_REMOTE_STORAGE_HOST}" - source - ''')) - - shell('docker save -o build/AusweisApp-${BUILD_TAG}.tar dev-docker.govkg.de/ausweisapp/sdk:${BUILD_TAG}') - - shell('docker rmi -f dev-docker.govkg.de/ausweisapp/sdk:${BUILD_TAG}') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Docker_VNC.groovy b/resources/jenkins/dsl/Reviews/Review_Docker_VNC.groovy index abfdb2f54..0a32750d8 100644 --- a/resources/jenkins/dsl/Reviews/Review_Docker_VNC.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Docker_VNC.groovy @@ -13,19 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell(strip('''\ - docker build - -t dev-docker.govkg.de/ausweisapp/vnc:${BUILD_TAG} - --build-arg CCACHE_REMOTE_STORAGE="redis://${CCACHE_REMOTE_STORAGE_HOST}" - -f source/resources/jenkins/docker/Dockerfile - source - ''')) - - shell('docker run --rm dev-docker.govkg.de/ausweisapp/vnc:${BUILD_TAG} AusweisApp --help') - shell('docker save -o build/AusweisApp-VNC-${BUILD_TAG}.tar dev-docker.govkg.de/ausweisapp/vnc:${BUILD_TAG}') - - shell('docker rmi -f dev-docker.govkg.de/ausweisapp/vnc:${BUILD_TAG}') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Docs.groovy b/resources/jenkins/dsl/Reviews/Review_Docs.groovy index 37667a586..1be9b04bf 100644 --- a/resources/jenkins/dsl/Reviews/Review_Docs.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Docs.groovy @@ -14,25 +14,6 @@ j.with steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('cd source; cmake --preset ci-tools') - - shell('cmake --build build --target notes') - shell('cmake --build build --target notes.latex.pdf') - shell('cd build/docs/notes; cmake -E tar cfJ ../AusweisApp_ReleaseNotes.tar.xz .') - - shell('cmake --build build --target sdk') - shell('cmake --build build --target sdk.latex.pdf') - shell('cd build/docs/sdk/html; cmake -E tar cfJ ../../AusweisApp_SDK.tar.xz .') - - shell('cmake --build build --target failurecodes') - shell('cmake --build build --target failurecodes.latex.pdf') - - shell('cmake --build build --target installation_integration.latex.pdf') - - shell('cmake --build build --target license') - - shell('cmake --build build --target doc8') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Formatting.groovy b/resources/jenkins/dsl/Reviews/Review_Formatting.groovy index 58f03ebde..f234d8461 100644 --- a/resources/jenkins/dsl/Reviews/Review_Formatting.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Formatting.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'Formatting', - libraries: ['Linux'], + libraries: 'Linux', label: 'Common' ).generate(this) @@ -14,46 +14,7 @@ j.with steps { - shell('''\ - cd source - hg revert -a -C - hg --config extensions.hgext.purge= purge --all - hg --config extensions.hgext.strip= strip -r 'secret() or draft()' --no-backup --force 2>/dev/null || echo "No changeset stripped" - '''.stripIndent().trim()) - - shell('cd source; cmake --preset ci-tools-with-libs') - - shell('''\ - cd source - cmake --build ../build --target format - - STATUS=$(hg status | wc -c) - if [ "$STATUS" != "0" ]; then - echo 'Current repository state is not formatted!' - hg addremove - hg diff - hg commit -m "fix formatting" -s - fi - - (hg --config patch.eol=auto --config phases.new-commit=secret import -m 'jenkins patch formatting' -d 'today' -u 'jenkins' ../patch.diff) - if [ "$?" != "0" ]; then - echo 'FORMATTING FAILED: Patch cannot be applied' - exit 0 - fi - - cmake --build ../build --target rebuild_cache - cmake --build ../build --target format - - STATUS=$(hg status | wc -c) - if [ "$STATUS" != "0" ]; then - echo 'FORMATTING FAILED: Patch is not formatted' - hg diff - hg revert -a -C - exit 0 - fi - '''.stripIndent().trim()) - - shell('cd source; cmake -DCMD=CHECK_FAILURE_CODES -P cmake/cmd.cmake') + shell('cmake -DPENDING=OFF -P source/ci.cmake') } publishers diff --git a/resources/jenkins/dsl/Reviews/Review_FreeBSD.groovy b/resources/jenkins/dsl/Reviews/Review_FreeBSD.groovy index c38fe734f..839d1eb1e 100644 --- a/resources/jenkins/dsl/Reviews/Review_FreeBSD.groovy +++ b/resources/jenkins/dsl/Reviews/Review_FreeBSD.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'FreeBSD', - libraries: ['FreeBSD'], + libraries: 'FreeBSD', label: 'FreeBSD', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -13,29 +13,8 @@ def j = new Review j.with { - wrappers - { - environmentVariables - { - env("QT_PLUGIN_PATH", '$WORKSPACE/libs/build/dist/plugins') - } - } - steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('cd source; cmake --preset ci-bsd') - - shell('''\ - export LD_LIBRARY_PATH=$WORKSPACE/libs/build/dist/lib:$LD_LIBRARY_PATH - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export QML2_IMPORT_PATH=${WORKSPACE}/libs/build/dist/qml - export LD_LIBRARY_PATH=$WORKSPACE/libs/build/dist/lib:$LD_LIBRARY_PATH - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_Android.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_Android.groovy index 804575d00..5de8c98d8 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_Android.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_Android.groovy @@ -1,7 +1,7 @@ import common.LibraryReview import common.Constants -for(ARCH in Constants.AndroidArch) +for(ARCH in Constants.AndroidArchLibsReview) { def j = new LibraryReview @@ -15,7 +15,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell("cd source/libs; cmake --preset ci-android -DCMAKE_ANDROID_ARCH_ABI=${ARCH}") diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_FreeBSD.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_FreeBSD.groovy index 9b8d1fe7e..e85d86847 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_FreeBSD.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_FreeBSD.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('cd source/libs; cmake --preset ci-debug') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_Linux.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_Linux.groovy index a1939c031..39da19093 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_Linux.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_Linux.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('cd source/libs; cmake --preset ci-release') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_MacOS.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_MacOS.groovy index 4facd29cc..a27bdfdaa 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_MacOS.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_MacOS.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('cd source/libs; cmake --preset ci-release') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_GNU.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_GNU.groovy index 06c61ed12..6eb17d50b 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_GNU.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_GNU.groovy @@ -23,7 +23,7 @@ j.with steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + batchFile('cmake -DPATCH_ONLY=ON -P source/ci.cmake') batchFile('cd source/libs & cmake --preset ci-gnu-release') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC.groovy index 636078c66..dfb451b89 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC.groovy @@ -21,7 +21,7 @@ j.with steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + batchFile('cmake -DPATCH_ONLY=ON -P source/ci.cmake') batchFile('''\ call vcvarsall.bat amd64 diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC_dev.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC_dev.groovy index 649b7185b..833ac6c12 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC_dev.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_Win64_MSVC_dev.groovy @@ -21,7 +21,7 @@ j.with steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + batchFile('cmake -DPATCH_ONLY=ON -P source/ci.cmake') batchFile('''\ call vcvarsall.bat amd64 diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_iOS.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_iOS.groovy index bdeb28836..d1a4464e9 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_iOS.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_iOS.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator.groovy index b1b166b34..58659537b 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') diff --git a/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator_arm64.groovy b/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator_arm64.groovy index c3fb08bc5..037e4090a 100644 --- a/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator_arm64.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Libs_iOS_Simulator_arm64.groovy @@ -11,7 +11,7 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') + shell('cmake -DPATCH_ONLY=ON -P source/ci.cmake') shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') diff --git a/resources/jenkins/dsl/Reviews/Review_Linux.groovy b/resources/jenkins/dsl/Reviews/Review_Linux.groovy index 79a43400b..84a0a2ee0 100644 --- a/resources/jenkins/dsl/Reviews/Review_Linux.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Linux.groovy @@ -5,7 +5,7 @@ import static common.Constants.strip def j = new Review ( name: 'Linux', - libraries: ['Linux'], + libraries: 'Linux', label: 'Linux', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -16,40 +16,14 @@ def j = new Review j.with { - wrappers - { - environmentVariables - { - env("QT_PLUGIN_PATH", '$WORKSPACE/libs/build/dist/plugins') - } - } - axes { label('Compiler', 'g++', 'clang++') + label('Agent', 'Linux') } steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell(strip('''\ - cd source; - cmake -Werror=dev --preset ci-linux - -DCMAKE_CXX_COMPILER=${Compiler} - ''')) - - shell('''\ - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export QML2_IMPORT_PATH=${WORKSPACE}/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) - - shell('''\ - DESTDIR=$WORKSPACE/install cmake --install build - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake -- -DCMAKE_CXX_COMPILER=${Compiler}') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Linux_Integrated.groovy b/resources/jenkins/dsl/Reviews/Review_Linux_Integrated.groovy index 349f63bdb..035a4a4c1 100644 --- a/resources/jenkins/dsl/Reviews/Review_Linux_Integrated.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Linux_Integrated.groovy @@ -15,12 +15,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('cd source; cmake --preset ci-integrated') - - shell('cmake --build build') - - shell('ctest --test-dir build --output-on-failure') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_MacOS.groovy b/resources/jenkins/dsl/Reviews/Review_MacOS.groovy index a6b4ad2d8..2be176f96 100644 --- a/resources/jenkins/dsl/Reviews/Review_MacOS.groovy +++ b/resources/jenkins/dsl/Reviews/Review_MacOS.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'MacOS', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -15,24 +15,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - export QT_PLUGIN_PATH=${WORKSPACE}/libs/build/dist/plugins - export QML2_IMPORT_PATH=${WORKSPACE}/libs/build/dist/qml - ctest -C Debug --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_MacOS_DMG_PKG.groovy b/resources/jenkins/dsl/Reviews/Review_MacOS_DMG_PKG.groovy index 38c98f40d..154bbdd11 100644 --- a/resources/jenkins/dsl/Reviews/Review_MacOS_DMG_PKG.groovy +++ b/resources/jenkins/dsl/Reviews/Review_MacOS_DMG_PKG.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'MacOS_DMG_PKG', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', artifacts: 'build/*.dmg,build/*.pkg' ).generate(this) @@ -13,19 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos-release -DOSX_TIMESTAMP=OFF') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build --target package --config MinSizeRel - '''.stripIndent().trim()) - - shell('cd build/_CPack_Packages/Darwin/; codesign -vvvv **/**/*.app') - shell('cd build/_CPack_Packages/Darwin/DragNDrop; spctl -a -vv **/*.app') + shell('cmake -P source/ci.cmake -- -DOSX_TIMESTAMP=OFF') } } diff --git a/resources/jenkins/dsl/Reviews/Review_MacOS_Integrated.groovy b/resources/jenkins/dsl/Reviews/Review_MacOS_Integrated.groovy index 0e2569160..d19209a6a 100644 --- a/resources/jenkins/dsl/Reviews/Review_MacOS_Integrated.groovy +++ b/resources/jenkins/dsl/Reviews/Review_MacOS_Integrated.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'MacOS_Integrated', - libraries: ['MacOS'], + libraries: 'MacOS', label: 'MacOS', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -15,23 +15,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain ${KEYCHAIN_CREDENTIALS} ${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-macos-integrated') - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - cmake --build build - '''.stripIndent().trim()) - - shell('''\ - export DYLD_FRAMEWORK_PATH=${WORKSPACE}/libs/build/dist/lib - export DYLD_LIBRARY_PATH=${WORKSPACE}/libs/build/dist/lib - export QT_PLUGIN_PATH=${WORKSPACE}/libs/build/dist/plugins - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_SonarQube.groovy b/resources/jenkins/dsl/Reviews/Review_SonarQube.groovy index ed8175190..959a38b3d 100644 --- a/resources/jenkins/dsl/Reviews/Review_SonarQube.groovy +++ b/resources/jenkins/dsl/Reviews/Review_SonarQube.groovy @@ -25,36 +25,6 @@ j.with steps { - shell('mkdir -p cache') - - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('cmake -P source/cmake/prepare_sonarqube_env.cmake') - - shell('cd source; cmake --preset ci-linux') - - shell('''\ - cd build; - $WORKSPACE/sonarqubetools/dependency-check/bin/dependency-check.sh --enableExperimental -f HTML -f JSON --scan $WORKSPACE/source/cmake --noupdate --connectionString=jdbc:mariadb://dependency-check-db.govkg.de/dependencycheck --dbUser=${DEPENDENCY_CHECK_USER} --dbPassword=${DEPENDENCY_CHECK_PASSWORD} --dbDriverName=org.mariadb.jdbc.Driver - '''.stripIndent().trim()) - - - shell('$WORKSPACE/sonarqubetools/sonar-build-wrapper/build-wrapper-linux-x86-64 --out-dir build cmake --build build') - - shell('ctest -LE qml -E Test_ui_qml_Qml --test-dir build --output-on-failure') - - shell('cmake --build build --target gcovr.sonar') - - shell(strip('''\ - cd build; - $WORKSPACE/sonarqubetools/sonar-scanner/bin/sonar-scanner - -Dsonar.scanner.metadataFilePath=${WORKSPACE}/tmp/sonar-metadata.txt - -Dsonar.pullrequest.key=${REVIEWBOARD_REVIEW_ID} - -Dsonar.pullrequest.branch=${REVIEWBOARD_REVIEW_ID} - -Dsonar.pullrequest.base=${MERCURIAL_REVISION_BRANCH} - -Dsonar.login=${SONARQUBE_TOKEN} - -Dsonar.qualitygate.wait=true - -Dsonar.qualitygate.timeout=90 - ''')) + shell('cmake -DSPLITTED=OFF -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Source.groovy b/resources/jenkins/dsl/Reviews/Review_Source.groovy index f5b1081fe..ac3c26a25 100644 --- a/resources/jenkins/dsl/Reviews/Review_Source.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Source.groovy @@ -4,7 +4,7 @@ def j = new Review ( name: 'Source', label: 'Common', - artifacts: 'build/*.tar.gz' + artifacts: 'build/*.tar.gz*' ).generate(this) @@ -14,8 +14,6 @@ j.with steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - shell('cd source; cmake --preset ci-tools') - shell('cmake --build build --target package_source') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Trigger.groovy b/resources/jenkins/dsl/Reviews/Review_Trigger.groovy index 66b3ad3d3..d83ff850c 100644 --- a/resources/jenkins/dsl/Reviews/Review_Trigger.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Trigger.groovy @@ -8,14 +8,18 @@ def getJobs() { def list = ['Formatting', 'Source', 'Docs'] - def packages = ['Container', 'MacOS_DMG_PKG', 'Win64_GNU_MSI', 'Win64_MSVC_MSI', 'iOS_IPA', 'iOS_Framework', 'iOS_Simulator_Framework', 'iOS_Simulator_arm64_Framework', 'Android_AAR'] + def packages = ['Container', 'MacOS_DMG_PKG', 'Win64_GNU_MSI', 'Win64_MSVC_MSI', 'iOS_IPA', 'iOS_Framework', 'iOS_Simulator_Framework', 'iOS_Simulator_arm64_Framework'] + for(ARCH in Constants.AndroidArchAARReview) + { + packages << 'Android_AAR_' + ARCH + } for(ARCH in Constants.AndroidArchAPKReview) { packages << 'Android_APK_' + ARCH } list += packages - def subPackages = ['iOS_SwiftPackage'] + def subPackages = ['Android_AAR', 'iOS_SwiftPackage'] list += subPackages def unitTests = ['Linux', 'Linux_Integrated', 'MacOS', 'MacOS_Integrated', 'Win64_GNU', 'Win64_MSVC', 'FreeBSD', 'SonarQube', 'Docker_VNC'] @@ -29,6 +33,11 @@ String getName(String name) return "${MERCURIAL_REVISION_BRANCH}_Review_" + name } +String getNameParam(String name) +{ + return getName(name).replace('-', '_') + '_Build' +} + def reviewMessage = createReviewMessage(getJobs(), this.&getName) + ' | Libraries: ${Libraries}' + ' | SonarQube Analysis: ${SONARQUBE_ANALYSIS_MESSAGE}' @@ -69,7 +78,10 @@ j.with phase('Packages', 'UNSTABLE') { - phaseJob(getName('Android_AAR')) + for(ARCH in Constants.AndroidArchAARReview) + { + phaseJob(getName('Android_AAR_' + ARCH)) + } for(ARCH in Constants.AndroidArchAPKReview) { @@ -95,6 +107,17 @@ j.with phase('Sub-Packages', 'UNSTABLE') { + phaseJob(getName('Android_AAR')) + { + parameters + { + for(ARCH in Constants.AndroidArchAARReview) + { + predefinedProp(getNameParam('Android_AAR_' + ARCH), getEnvNumber(getName('Android_AAR_' + ARCH))) + } + } + } + phaseJob(getName('iOS_SwiftPackage')) { parameters diff --git a/resources/jenkins/dsl/Reviews/Review_Trigger_Libs.groovy b/resources/jenkins/dsl/Reviews/Review_Trigger_Libs.groovy index abb305572..cac548310 100644 --- a/resources/jenkins/dsl/Reviews/Review_Trigger_Libs.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Trigger_Libs.groovy @@ -6,7 +6,7 @@ import static common.Constants.createReviewMessage def getJobs() { def list = ['Linux', 'MacOS', 'Win64_GNU', 'Win64_MSVC', 'Win64_MSVC_dev', 'iOS', 'iOS_Simulator', 'iOS_Simulator_arm64', 'FreeBSD'] - for(ARCH in Constants.AndroidArchAPKReview) + for(ARCH in Constants.AndroidArchLibsReview) { list << 'Android_' + ARCH } @@ -54,7 +54,7 @@ j.with killPhaseCondition('NEVER') } - for(ARCH in Constants.AndroidArchAPKReview) + for(ARCH in Constants.AndroidArchLibsReview) { phaseJob(getName('Android_' + ARCH)) { diff --git a/resources/jenkins/dsl/Reviews/Review_Win64_GNU.groovy b/resources/jenkins/dsl/Reviews/Review_Win64_GNU.groovy index ff6c8863d..59ccad6ed 100644 --- a/resources/jenkins/dsl/Reviews/Review_Win64_GNU.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Win64_GNU.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'Win64_GNU', - libraries: ['Win64_GNU'], + libraries: 'Win64_GNU', label: 'Windows', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -16,18 +16,6 @@ j.with { steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - batchFile('cd source & cmake --preset ci-win') - - batchFile('cmake --build build') - - batchFile('''\ - set PATH=%WORKSPACE%/libs/build/dist/bin;%PATH% - set PATH=%WORKSPACE%/build/src;%WORKSPACE%/build/test/helper;%PATH% - set QT_PLUGIN_PATH=%WORKSPACE%/libs/build/dist/plugins - set QML2_IMPORT_PATH=%WORKSPACE%/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Win64_GNU_MSI.groovy b/resources/jenkins/dsl/Reviews/Review_Win64_GNU_MSI.groovy index e744abe49..6a8b034c8 100644 --- a/resources/jenkins/dsl/Reviews/Review_Win64_GNU_MSI.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Win64_GNU_MSI.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'Win64_GNU_MSI', - libraries: ['Win64_GNU'], + libraries: 'Win64_GNU', label: 'Windows', artifacts: 'build/*.msi', weight: 2 @@ -14,14 +14,6 @@ j.with { steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - batchFile('cd source & cmake --preset ci-win-release') - - batchFile('cmake --build build --target package') - - batchFile('cmake --build build --target package.sign') - - batchFile('cmake -DCMD=CHECK_WIX_WARNING -DFILE=build/_CPack_Packages/win64/WIX/wix.log -P source/cmake/cmd.cmake') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Win64_MSVC.groovy b/resources/jenkins/dsl/Reviews/Review_Win64_MSVC.groovy index 20df3973a..8351f6fb3 100644 --- a/resources/jenkins/dsl/Reviews/Review_Win64_MSVC.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Win64_MSVC.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'Win64_MSVC', - libraries: ['Win64_MSVC_dev'], + libraries: 'Win64_MSVC_dev', label: 'MSVC', artifacts: 'tmp/*.log', allowEmptyArtifacts: true, @@ -15,23 +15,6 @@ j.with { steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build - '''.stripIndent().trim()) - - batchFile('''\ - set PATH=%WORKSPACE%/libs/build/dist/bin;%PATH% - set QT_PLUGIN_PATH=%WORKSPACE%/libs/build/dist/plugins - set QML2_IMPORT_PATH=%WORKSPACE%/libs/build/dist/qml - ctest --test-dir build --output-on-failure - '''.stripIndent().trim()) + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_Win64_MSVC_MSI.groovy b/resources/jenkins/dsl/Reviews/Review_Win64_MSVC_MSI.groovy index f4c958723..6c0f987ea 100644 --- a/resources/jenkins/dsl/Reviews/Review_Win64_MSVC_MSI.groovy +++ b/resources/jenkins/dsl/Reviews/Review_Win64_MSVC_MSI.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'Win64_MSVC_MSI', - libraries: ['Win64_MSVC'], + libraries: 'Win64_MSVC', label: 'MSVC', artifacts: 'build/*.msi' ).generate(this) @@ -13,23 +13,6 @@ j.with { steps { - batchFile('cd source & cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - batchFile('''\ - call vcvarsall.bat amd64 - cd source & cmake --preset ci-win-release - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package - '''.stripIndent().trim()) - - batchFile('''\ - call vcvarsall.bat amd64 - cmake --build build --target package.sign - '''.stripIndent().trim()) - - batchFile('cmake -DCMD=CHECK_WIX_WARNING -DFILE=build/_CPack_Packages/win64/WIX/wix.log -P source/cmake/cmd.cmake') + batchFile('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_iOS_Framework.groovy b/resources/jenkins/dsl/Reviews/Review_iOS_Framework.groovy index 2942af501..d58877b9f 100644 --- a/resources/jenkins/dsl/Reviews/Review_iOS_Framework.groovy +++ b/resources/jenkins/dsl/Reviews/Review_iOS_Framework.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'iOS_Framework', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,13 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_iOS_IPA.groovy b/resources/jenkins/dsl/Reviews/Review_iOS_IPA.groovy index 99cd28ba1..c52d8a894 100644 --- a/resources/jenkins/dsl/Reviews/Review_iOS_IPA.groovy +++ b/resources/jenkins/dsl/Reviews/Review_iOS_IPA.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'iOS_IPA', - libraries: ['iOS'], + libraries: 'iOS', label: 'iOS', artifacts: 'build/*.ipa,build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,13 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target ipa') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_Framework.groovy b/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_Framework.groovy index afe33d924..cb7f264ee 100644 --- a/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_Framework.groovy +++ b/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_Framework.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'iOS_Simulator_Framework', - libraries: ['iOS_Simulator'], + libraries: 'iOS_Simulator', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,13 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_arm64_Framework.groovy b/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_arm64_Framework.groovy index 891ca7f37..69d358204 100644 --- a/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_arm64_Framework.groovy +++ b/resources/jenkins/dsl/Reviews/Review_iOS_Simulator_arm64_Framework.groovy @@ -3,7 +3,7 @@ import common.Review def j = new Review ( name: 'iOS_Simulator_arm64_Framework', - libraries: ['iOS_Simulator_arm64'], + libraries: 'iOS_Simulator_arm64', label: 'iOS', artifacts: 'build/*.zip,build/*.bcsymbolmap' ).generate(this) @@ -13,13 +13,6 @@ j.with { steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - - shell('security unlock-keychain \${KEYCHAIN_CREDENTIALS} \${HOME}/Library/Keychains/login.keychain-db') - - shell('cd source; cmake --preset ci-ios-framework-simulator-arm64') - - shell('cd build; xcodebuild -configuration MinSizeRel') - shell('cd build; xcodebuild -configuration MinSizeRel -target zip') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/Reviews/Review_iOS_SwiftPackage.groovy b/resources/jenkins/dsl/Reviews/Review_iOS_SwiftPackage.groovy index 11b545c3b..c7ed86262 100644 --- a/resources/jenkins/dsl/Reviews/Review_iOS_SwiftPackage.groovy +++ b/resources/jenkins/dsl/Reviews/Review_iOS_SwiftPackage.groovy @@ -21,11 +21,10 @@ j.with steps { - shell('cd source; cmake -DCMD=IMPORT_PATCH -P cmake/cmd.cmake') - copyArtifacts(build.getSourceJobName('iOS_Framework')) { - targetDirectory('build/arm64') + targetDirectory('arm64') + flatten() buildSelector { buildNumber('${iOS_Framework_Build}') @@ -34,7 +33,8 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_Framework')) { - targetDirectory('build/x86_64-simulator') + targetDirectory('x86_64-simulator') + flatten() buildSelector { buildNumber('${iOS_Simulator_Framework_Build}') @@ -43,13 +43,14 @@ j.with copyArtifacts(build.getSourceJobName('iOS_Simulator_arm64_Framework')) { - targetDirectory('build/arm64-simulator') + targetDirectory('arm64-simulator') + flatten() buildSelector { buildNumber('${iOS_Simulator_arm64_Framework_Build}') } } - shell('cd build; cmake -P ../source/cmake/SwiftPackage.cmake') + shell('cmake -P source/ci.cmake') } } diff --git a/resources/jenkins/dsl/common/Build.groovy b/resources/jenkins/dsl/common/Build.groovy index 60bff7b2c..4e62db2a2 100644 --- a/resources/jenkins/dsl/common/Build.groovy +++ b/resources/jenkins/dsl/common/Build.groovy @@ -13,12 +13,12 @@ class Build JobType jobType = JobType.Freestyle String name String namePrefix = '' - String[] libraries + String libraries String artifacts String label String trigger = '@daily' String excludePattern = 'source/**' - List oldBuilds = [7, 30] + List oldBuilds = [7, 10] boolean releaseJob = false boolean xunit = false boolean sendMail = true @@ -56,6 +56,11 @@ class Build return buildName(getNamePrefix(), artifactJob) } + String getSourceJobNameParam(String artifactJob) + { + return getSourceJobName(artifactJob).replace('-', '_') + '_Build' + } + String getLibName(String partialLibName) { def prefix = 'Libs_' @@ -102,11 +107,32 @@ class Build if(getWeight() > 1) weight(getWeight()) + String defaultArtifactJob = 'LIBRARY_ARTIFACT_JOB' + String defaultArtifactJobEval = 'LIBRARY_ARTIFACT_JOB_EVAL' + String defaultArtifactParam = 'LIBRARY_ARTIFACT' + environmentVariables { env('TEMP', '$WORKSPACE/tmp') env('TMP', '$WORKSPACE/tmp') env('TMPDIR', '$WORKSPACE/tmp') + env(defaultArtifactJobEval, '$' + defaultArtifactJob) + } + + if(getLibraries()) + { + parameters + { + stringParam(defaultArtifactJob, getLibName(getLibraries()), "Use job artifact source") + buildSelectorParam(defaultArtifactParam) + { + defaultBuildSelector + { + latestSuccessful(true) + } + description('Use build library job') + } + } } wrappers @@ -158,31 +184,24 @@ class Build steps { - String[] requestedLibs = getLibraries() - String defaultTargetDestDir = 'libs' - - for(String partLibName in requestedLibs) + if(getLibraries()) { - String targetDestDir = defaultTargetDestDir - if(requestedLibs.length > 1) - { - String arch = partLibName.split('_').last() - targetDestDir += '/' + arch - } - - copyArtifacts(getLibName(partLibName)) + String targetDestDir = 'libs' + copyArtifacts('${' + defaultArtifactJobEval + '}') { targetDirectory(targetDestDir) buildSelector { - latestSuccessful(true) + includePatterns('**/Toolchain_*') + flatten() + buildParameter(defaultArtifactParam) } } if(getName().contains('_Win')) - batchFile("cd ${targetDestDir}/build & FOR %%a in (Toolchain_*) DO cmake -E tar xf %%a") + batchFile("cd ${targetDestDir} & FOR %%a in (Toolchain_*) DO cmake -E tar xf %%a") else - shell("cd ${targetDestDir}/build; cmake -E tar xf Toolchain_*") + shell("cd ${targetDestDir}; cmake -E tar xf Toolchain_*") } if(getName().contains('_Win')) diff --git a/resources/jenkins/dsl/common/Constants.groovy b/resources/jenkins/dsl/common/Constants.groovy index da5912437..c2b40196e 100644 --- a/resources/jenkins/dsl/common/Constants.groovy +++ b/resources/jenkins/dsl/common/Constants.groovy @@ -4,10 +4,11 @@ class Constants { static final AndroidArchAPKReview = ["arm64-v8a", "x86_64"] static final AndroidArchAPK = AndroidArchAPKReview + ["armeabi-v7a", "x86"] - static final AndroidArchAAR = ["arm64-v8a"] - static final AndroidArch = (AndroidArchAPK + AndroidArchAAR).unique() + static final AndroidArchAARReview = ["arm64-v8a", "x86_64", "armeabi-v7a"] + static final AndroidArchAAR = AndroidArchAARReview - static final ReviewBoardServer = "rb.governikus.de" + static final AndroidArchLibsReview = (AndroidArchAPKReview + AndroidArchAARReview).unique() + static final AndroidArchLibs = (AndroidArchAPK + AndroidArchAAR).unique() static String strip(String content) { diff --git a/resources/jenkins/dsl/common/LibraryReview.groovy b/resources/jenkins/dsl/common/LibraryReview.groovy index 36af22d6b..31bf07679 100644 --- a/resources/jenkins/dsl/common/LibraryReview.groovy +++ b/resources/jenkins/dsl/common/LibraryReview.groovy @@ -21,7 +21,7 @@ class LibraryReview extends Library parameters { fileParam('patch.diff', 'Patch file that will be applied and tested') - stringParam('REVIEWBOARD_SERVER', Constants.ReviewBoardServer, 'Server') + stringParam('REVIEWBOARD_SERVER', '', 'Server') stringParam('REVIEWBOARD_REVIEW_ID', '', 'ReviewID') stringParam('REVIEWBOARD_DIFF_REVISION', '', 'ReviewDiffRev') stringParam('REVIEWBOARD_STATUS_UPDATE_ID', '', 'StatusUpdateID') diff --git a/resources/jenkins/dsl/common/Release.groovy b/resources/jenkins/dsl/common/Release.groovy index c5000d5ae..9217d3977 100644 --- a/resources/jenkins/dsl/common/Release.groovy +++ b/resources/jenkins/dsl/common/Release.groovy @@ -9,7 +9,7 @@ class Release extends Build { String namePrefix = 'Release_' String trigger = null - List oldBuilds = null + List oldBuilds = [365, -1] boolean releaseJob = true boolean sendMail = false diff --git a/resources/jenkins/dsl/common/Review.groovy b/resources/jenkins/dsl/common/Review.groovy index 7c6ec57df..73a5e3d92 100644 --- a/resources/jenkins/dsl/common/Review.groovy +++ b/resources/jenkins/dsl/common/Review.groovy @@ -7,7 +7,7 @@ class Review extends Trigger String namePrefix = 'Review_' String label = 'Review' String trigger = null - List oldBuilds = [14, -1] + List oldBuilds = [7, -1] int timeout = 90 boolean review = true } diff --git a/resources/jenkins/dsl/common/RootTrigger.groovy b/resources/jenkins/dsl/common/RootTrigger.groovy index b8ea16937..d31e6043e 100644 --- a/resources/jenkins/dsl/common/RootTrigger.groovy +++ b/resources/jenkins/dsl/common/RootTrigger.groovy @@ -21,11 +21,11 @@ class RootTrigger parameters { - stringParam('REVIEWBOARD_SERVER', Constants.ReviewBoardServer, 'Server') + stringParam('REVIEWBOARD_SERVER', '', 'Server') stringParam('REVIEWBOARD_REVIEW_ID', '', 'ReviewID') stringParam('REVIEWBOARD_DIFF_REVISION', '', 'ReviewDiffRev') - stringParam('REVIEWBOARD_REVIEW_BRANCH', '', 'ReviewBranch') stringParam('REVIEWBOARD_STATUS_UPDATE_ID', '', 'StatusUpdateID') + stringParam('REVIEWBOARD_REVIEW_BRANCH', '', 'ReviewBranch') } steps diff --git a/resources/jenkins/dsl/common/Trigger.groovy b/resources/jenkins/dsl/common/Trigger.groovy index f1fc2ddc4..b5fa35b70 100644 --- a/resources/jenkins/dsl/common/Trigger.groovy +++ b/resources/jenkins/dsl/common/Trigger.groovy @@ -24,7 +24,7 @@ class Trigger extends Build parameters { fileParam('patch.diff', 'Patch file that will be applied and tested') - stringParam('REVIEWBOARD_SERVER', Constants.ReviewBoardServer, 'Server') + stringParam('REVIEWBOARD_SERVER', '', 'Server') stringParam('REVIEWBOARD_REVIEW_ID', '', 'ReviewID') stringParam('REVIEWBOARD_DIFF_REVISION', '', 'ReviewDiffRev') stringParam('REVIEWBOARD_STATUS_UPDATE_ID', '', 'StatusUpdateID') diff --git a/resources/jenkins/dsl/install.py b/resources/jenkins/dsl/install.py index d0b6db8c0..30e7b4819 100755 --- a/resources/jenkins/dsl/install.py +++ b/resources/jenkins/dsl/install.py @@ -63,7 +63,7 @@ def installPlugin(plugin): plugins = [] plugins.append('build-timeout') plugins.append('categorized-view') -plugins.append('cobertura') +plugins.append('coverage') plugins.append('copyartifact') plugins.append('cppcheck') plugins.append('depgraph-view') @@ -71,18 +71,17 @@ def installPlugin(plugin): plugins.append('description-setter') plugins.append('envinject') plugins.append('extra-columns') -plugins.append('google-play-android-publisher') -plugins.append('greenballs') plugins.append('heavy-job') plugins.append('htmlpublisher') plugins.append('jenkins-multijob-plugin') plugins.append('jobConfigHistory') plugins.append('job-dsl') plugins.append('mercurial') -plugins.append('msbuild') plugins.append('naginator') plugins.append('nodelabelparameter') plugins.append('parameterized-trigger') +plugins.append('pipeline-stage-view') +plugins.append('pipeline-utility-steps') plugins.append('postbuildscript') plugins.append('show-build-parameters') plugins.append('sloccount') @@ -90,8 +89,9 @@ def installPlugin(plugin): plugins.append('swarm') plugins.append('text-finder') plugins.append('timestamper') -plugins.append('valgrind') +plugins.append('uno-choice') plugins.append('warnings-ng') +plugins.append('workflow-aggregator') plugins.append('ws-cleanup') plugins.append('xunit') diff --git a/resources/jenkins/import.py b/resources/jenkins/import.py index 21c491d10..0d247d5c7 100755 --- a/resources/jenkins/import.py +++ b/resources/jenkins/import.py @@ -3,85 +3,124 @@ import hglib from hglib.util import b +import argparse import os +import glob import sys -patchy = None - -try: - from rbtools.commands.patch import Patch - - class PatchHelper(Patch): - def __init__(self): - super(PatchHelper, self).__init__() - parser = self.create_arg_parser([]) - self.options = parser.parse_args([]) - self._api_root = None - if self.options.server is None: - self.options.server = os.environ.get('REVIEWBOARD_SERVER') - - # RBTools >= 2.0 - self.v1 = not hasattr(self, 'get_patches') - - def download(self, request_id, diff_rev=None): - if request_id is None: - print('ID of review request cannot be undefined') - return None - - if self._api_root is None: - if self.options.server is None: - print('Cannot find Review Board! Provide .reviewboardrc?') - return None - _, self._api_root = self.get_api(self.options.server) - - if not self.v1: - _, self._tool = self.initialize_scm_tool( - require_repository_info=False - ) - self.setup_tool(self._tool, api_root=self._api_root) - - print('Download patch revision {} ' - 'of review request {}'.format(diff_rev, request_id)) - - if self.v1: - diff, _, _ = self.get_patch(request_id, self._api_root, - diff_rev) - else: - self._review_request_id = request_id - diff = self.get_patches(diff_rev, squashed=True)[0]['diff'] - - return diff - - def save(self, file, request_id=None, diff_rev=None): - if request_id is None: - request_id = os.environ.get('REVIEWBOARD_REVIEW_ID') - - if diff_rev is None: - diff_rev = os.environ.get('REVIEWBOARD_DIFF_REVISION') - - diff = self.download(request_id, diff_rev) - - if diff is not None: - with open(file, 'wb') as f: - f.write(diff) - f.flush() - - patchy = PatchHelper() -except Exception: - print('Cannot import rbtools') +from pathlib import Path + + +class CommandLineParser(argparse.ArgumentParser): + def __init__(self): + super().__init__() + self.add_argument('--no-pending', + help='Do not apply patch', action='store_true') + self.add_argument('--clean', + help='Clean up patches', action='store_true') + self.add_argument('--clean-only', + help='Clean up only', action='store_true') + self.add_argument('--splitted', + help='Apply patches splitted', action='store_true') + self.add_argument('--repatch', + help="Repatch previous series", action='store_true') + self.add_argument('--patch', + help="Patch file", default='../patch.diff') + self.args = self.parse_args() + + def pending(self): + return not self.args.no_pending + + def clean(self): + return self.args.clean or self.clean_only() + + def clean_only(self): + return self.args.clean_only + + def splitted(self): + return self.args.splitted + + def repatch(self): + return self.args.repatch + + def patch(self): + return self.args.patch + + +class PatchProcessor(): + def __init__(self, file, repatch): + self.file = file.decode('utf-8') + self.dir = os.path.dirname(os.path.realpath(self.file)) + self.patch_series = sorted(glob.glob(self.dir + os.sep + '*.patch'), + key=lambda x: int(Path(x).stem)) + self.applied = self.dir + os.sep + 'applied' + self.applied_patches = [] + + if os.path.isfile(self.applied): + with open(self.applied, 'r') as f: + self.applied_patches = list(filter(None, f.read().split('\n'))) + if repatch and len(self.applied_patches) > 0: + self.applied_patches.pop() + + def clean(self): + if os.path.isfile(self.applied): + os.remove(self.applied) + for patch in self.patch_series: + os.remove(patch) + + self.patch_series = [] + self.applied_patches = [] + + def split(self): + def nextFilename(): + self.patch_series.append(self.dir + os.sep + + str(len(self.patch_series)) + + '.patch') + return open(self.patch_series[-1], 'wb') + + with open(self.file, 'rb') as f: + file = nextFilename() + for line in f: + if line == b'# HG changeset patch\n' and file.tell() > 0: + file.close() + file = nextFilename() + file.write(line) + file.close() + + def isSplitted(self): + return len(self.patch_series) > 0 + + def apply(self, client, splitted, applyPending): + if self.patch_series == self.applied_patches or not splitted: + print('Apply all patches: %s' % len(self.patch_series)) + client.import_([s.encode('utf-8') for s in self.patch_series], + nocommit=True) + return + + with open(self.applied, 'w') as f: + for patch in self.patch_series: + pending = patch not in self.applied_patches + if not pending or applyPending and pending: + print('Apply patch: {} (pending: {})'.format(patch, + pending)) + client.import_([patch.encode('utf-8')], + user='CI', + date='now', + message=patch, + nocommit=pending) + + f.write(patch) + f.write('\n') + if pending: + print('Pending patch: {}'.format(patch)) + break def main(): - if len(sys.argv) > 2: - print('Unknown parameter: {}'.format(sys.argv)) - return -1 + parser = CommandLineParser() - patch = b(sys.argv[1]) if len(sys.argv) == 2 else b('../patch.diff') + patch = b(parser.patch()) if not os.path.isfile(patch): - if patchy is not None: - print('Try to ask Review Board for patch file') - patchy.save(patch) - if not os.path.isfile(patch): print('Patch file "{}" does not exists'.format(patch)) return -1 @@ -113,9 +152,19 @@ def main(): b('--no-backup'), b('--force')]) - print('Import patch: {}'.format(patch)) - client.import_([patch], nocommit=True) + processor = PatchProcessor(patch, parser.repatch()) + if parser.clean(): + processor.clean() + + if parser.clean_only(): + return 0 + + if not processor.isSplitted(): + print('Split patch: {}'.format(patch)) + processor.split() + print('Wrote {} patch(es)'.format(len(processor.patch_series))) + processor.apply(client, parser.splitted(), parser.pending()) return 0 diff --git a/resources/jenkins/kubernetes/android.yaml b/resources/jenkins/kubernetes/android.yaml index 1edb7127a..c054b891f 100644 --- a/resources/jenkins/kubernetes/android.yaml +++ b/resources/jenkins/kubernetes/android.yaml @@ -64,6 +64,30 @@ spec: key: sonarqube name: dependency-check-credentials optional: false + - name: GPG_PSW + valueFrom: + secretKeyRef: + key: GPG_PSW + name: gpg + optional: false + - name: GPG_ID + valueFrom: + secretKeyRef: + key: GPG_ID + name: gpg + optional: false + - name: CENTRAL_PSW + valueFrom: + secretKeyRef: + key: CENTRAL_PSW + name: android-passwords + optional: false + - name: CENTRAL_USERNAME + valueFrom: + secretKeyRef: + key: CENTRAL_USERNAME + name: android-passwords + optional: false image: dev-docker.governikus.de/ausweisapp2/ubuntu:android imagePullPolicy: Always lifecycle: @@ -74,6 +98,7 @@ spec: - -c - base64 -d /secrets/debug.keystore > /home/governikus/.android/debug.keystore && base64 -d /secrets/release.keystore > /home/governikus/release.keystore + && gpg --batch --passphrase $GPG_PSW --pinentry-mode loopback --import /gpg/GPG_PRIVATE name: android resources: limits: @@ -119,3 +144,8 @@ spec: - name: ccache persistentVolumeClaim: claimName: ccache-android + - name: gpg + secret: + defaultMode: 420 + optional: false + secretName: gpg diff --git a/resources/jenkins/kubernetes/common.yaml b/resources/jenkins/kubernetes/common.yaml index 1322fc2f8..ac082e75f 100644 --- a/resources/jenkins/kubernetes/common.yaml +++ b/resources/jenkins/kubernetes/common.yaml @@ -22,8 +22,28 @@ spec: key: PASSWORD name: android-passwords optional: false + - name: GPG_PSW + valueFrom: + secretKeyRef: + key: GPG_PSW + name: gpg + optional: false + - name: GPG_ID + valueFrom: + secretKeyRef: + key: GPG_ID + name: gpg + optional: false image: dev-docker.governikus.de/ausweisapp2/alpine:common imagePullPolicy: Always + lifecycle: + postStart: + exec: + command: + - sh + - '-c' + - >- + gpg --batch --passphrase $GPG_PSW --pinentry-mode loopback --import /gpg/GPG_PRIVATE name: common resources: limits: @@ -42,3 +62,9 @@ spec: tty: true restartPolicy: Always terminationGracePeriodSeconds: 30 + volumes: + - name: gpg + secret: + defaultMode: 420 + optional: false + secretName: gpg diff --git a/resources/packaging/android/AndroidManifest.xml.apk.in b/resources/packaging/android/AndroidManifest.xml.apk.in index bd1585372..d38f4c37a 100644 --- a/resources/packaging/android/AndroidManifest.xml.apk.in +++ b/resources/packaging/android/AndroidManifest.xml.apk.in @@ -30,6 +30,7 @@ @@ -70,11 +71,10 @@ @@ -102,6 +102,15 @@ android:value="true" /> + + + + + diff --git a/resources/packaging/android/build.gradle.append b/resources/packaging/android/build.gradle.append index 51147ca6e..cf700cac6 100644 --- a/resources/packaging/android/build.gradle.append +++ b/resources/packaging/android/build.gradle.append @@ -4,10 +4,6 @@ task sourcesJar(type: Jar) { archiveClassifier = "sources" } -dependencies { - implementation "androidx.core:core:1.12.0" -} - allprojects { repositories { maven { @@ -20,11 +16,7 @@ allprojects { } android { - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - + compileSdkVersion "android-35" packagingOptions { merges -= ['/META-INF/services/**'] exclude 'META-INF/proguard/androidx-annotations.pro' @@ -43,17 +35,19 @@ android { exclude '**/libplugins_imageformats_qico_*.so' exclude '**/libplugins_imageformats_qtga_*.so' exclude '**/libplugins_imageformats_qtiff_*.so' + exclude '**/libplugins_imageformats_qwebp_*.so' exclude '**/libplugins_imageformats_qwbmp_*.so' - - jniLibs { - useLegacyPackaging = true - } } lintOptions { lintConfig file('lint.xml') } + buildFeatures { + aidl = true + buildConfig = true + } + defaultConfig { buildConfigField("String", "ROOT_LOGGER", "\"${project.root_logger}\"") } diff --git a/resources/packaging/android/build.gradle.append.aar b/resources/packaging/android/build.gradle.append.aar index 6557c1109..aec3a1614 100644 --- a/resources/packaging/android/build.gradle.append.aar +++ b/resources/packaging/android/build.gradle.append.aar @@ -2,6 +2,5 @@ android { packagingOptions { exclude '**/libplugins_imageformats_*.so' exclude '**/libplugins_iconengines_*.so' - exclude '**/libQt6Svg_*.so' } } diff --git a/resources/packaging/android/build.gradle.append.smarteid b/resources/packaging/android/build.gradle.append.smarteid index d445cb3be..3cc7d2a31 100644 --- a/resources/packaging/android/build.gradle.append.smarteid +++ b/resources/packaging/android/build.gradle.append.smarteid @@ -1,3 +1,3 @@ dependencies { - runtimeOnly "de.bundesdruckerei.android.eid-applet-service-lib:eid-applet-service-lib:1.1.0" + runtimeOnly "de.bundesdruckerei.android.eid-applet-service-lib:eid-applet-service-lib:1.2.0" } diff --git a/resources/packaging/android/libAusweisApp.so-deployment-settings.json.in b/resources/packaging/android/libAusweisApp.so-deployment-settings.json.in index 0ccf6281b..823ceb4d8 100644 --- a/resources/packaging/android/libAusweisApp.so-deployment-settings.json.in +++ b/resources/packaging/android/libAusweisApp.so-deployment-settings.json.in @@ -23,7 +23,7 @@ "qtQmlDirectory": { "@CMAKE_ANDROID_ARCH_ABI@": "qml" }, - "sdk": "@ANDROID_SDK@", + "sdk": "@ANDROID_SDK_ROOT@", "sdkBuildToolsRevision": "@ANDROID_BUILD_TOOLS_REVISION@", "ndk": "@CMAKE_ANDROID_NDK@", "toolchain-prefix": "llvm", @@ -34,5 +34,5 @@ "application-binary": "AusweisApp", "qml-importscanner-binary": "@QT_HOST_PATH@/libexec/qmlimportscanner", "rcc-binary": "@QT_HOST_PATH@/libexec/rcc", - "qml-root-path": @QML_ROOT_PATH@ + "qml-root-path": [] } diff --git a/resources/packaging/android/lint.aar.xml b/resources/packaging/android/lint.aar.xml index a2ccff2f4..8bc2d4b59 100644 --- a/resources/packaging/android/lint.aar.xml +++ b/resources/packaging/android/lint.aar.xml @@ -9,6 +9,7 @@ + - - - + + + + + diff --git a/resources/packaging/android/lint.apk.smarteid.xml b/resources/packaging/android/lint.apk.smarteid.xml new file mode 100644 index 000000000..3e0d4b110 --- /dev/null +++ b/resources/packaging/android/lint.apk.smarteid.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/packaging/android/lint.apk.xml b/resources/packaging/android/lint.apk.xml index 90d197def..4b10dc209 100644 --- a/resources/packaging/android/lint.apk.xml +++ b/resources/packaging/android/lint.apk.xml @@ -9,21 +9,7 @@ - - - - - + - - - - - - - - - + - - - + + diff --git a/resources/packaging/android/pom.xml.in b/resources/packaging/android/pom.xml.in index 72171ee4c..5393a14c1 100644 --- a/resources/packaging/android/pom.xml.in +++ b/resources/packaging/android/pom.xml.in @@ -7,7 +7,7 @@ aar AusweisApp The AusweisApp is a software, that you can use to identify yourself online with your electronic residence permit or your eID card. - https://github.com/Governikus/AusweisApp2/ + https://github.com/Governikus/AusweisApp/ EUPL-v1.2 @@ -25,6 +25,6 @@ - https://github.com/Governikus/AusweisApp2 + https://github.com/Governikus/AusweisApp diff --git a/resources/packaging/ios/Info.plist.in b/resources/packaging/ios/Info.plist.in index 8c62594bb..c31d5f2ae 100644 --- a/resources/packaging/ios/Info.plist.in +++ b/resources/packaging/ios/Info.plist.in @@ -7,7 +7,16 @@ E80704007F00070302 CFBundleDevelopmentRegion - English + de_DE + CFBundleLocalizations + + en + de + uk + ru + + CFBundleAllowMixedLocalizations + CFBundleExecutable ${MACOSX_BUNDLE_EXECUTABLE_NAME} CFBundleGetInfoString @@ -46,8 +55,6 @@ ${MACOSX_BUNDLE_GUI_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 - CFBundleLongVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} CFBundleName ${MACOSX_BUNDLE_BUNDLE_NAME} CFBundlePackageType diff --git a/resources/packaging/macos/DS_Store b/resources/packaging/macos/DS_Store new file mode 100644 index 000000000..dd0d91e7b Binary files /dev/null and b/resources/packaging/macos/DS_Store differ diff --git a/resources/packaging/macos/Info.plist.in b/resources/packaging/macos/Info.plist.in index ea3e44d27..42c9d6041 100644 --- a/resources/packaging/macos/Info.plist.in +++ b/resources/packaging/macos/Info.plist.in @@ -13,7 +13,11 @@ en de + uk + ru + CFBundleAllowMixedLocalizations + CFBundleDisplayName @MACOSX_BUNDLE_BUNDLE_NAME@ CFBundleExecutable diff --git a/resources/packaging/macos/container-migration.plist b/resources/packaging/macos/container-migration.plist deleted file mode 100644 index f8a2e212e..000000000 --- a/resources/packaging/macos/container-migration.plist +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Move - - ${Library}/Preferences/com.governikus.AusweisApp2.plist - - - \ No newline at end of file diff --git a/resources/packaging/macos/AusweisApp.entitlements b/resources/packaging/macos/entitlements.development.plist similarity index 100% rename from resources/packaging/macos/AusweisApp.entitlements rename to resources/packaging/macos/entitlements.development.plist diff --git a/resources/packaging/macos/entitlements.distribution.plist.in b/resources/packaging/macos/entitlements.distribution.plist.in new file mode 100644 index 000000000..44122c932 --- /dev/null +++ b/resources/packaging/macos/entitlements.distribution.plist.in @@ -0,0 +1,20 @@ + + + + + com.apple.application-identifier + G7EQCJU4BR.@BUNDLE_IDENTIFIER@ + com.apple.developer.team-identifier + G7EQCJU4BR + com.apple.security.app-sandbox + + com.apple.security.smartcard + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/resources/packaging/macos/prepare-ds_store.applescript b/resources/packaging/macos/prepare-ds_store.applescript index be6a88fdb..f9748f16e 100644 --- a/resources/packaging/macos/prepare-ds_store.applescript +++ b/resources/packaging/macos/prepare-ds_store.applescript @@ -8,7 +8,8 @@ on run argv set current view of container window to icon view set toolbar visible of container window to false set statusbar visible of container window to false - set bounds of container window to {0, 100, 500, 467} + set pathbar visible of container window to true + set bounds of container window to {0, 100, 500, 476} set theViewOptions to the icon view options of container window set arrangement of theViewOptions to not arranged set icon size of theViewOptions to 70 @@ -17,14 +18,11 @@ on run argv set file_list to every file repeat with i in file_list - if the name of i is "Applications" then - set the position of i to {350, 165} - else if the name of i ends with ".app" then - set the position of i to {152, 165} - end if - #-- Change the 7 to change the color: 0 is no label, then red, - #-- orange, yellow, green, blue, purple, or gray. - #set the label index of i to 7 + if the name of i is "Applications" then + set the position of i to {350, 154} + else if the name of i ends with ".app" then + set the position of i to {152, 154} + end if end repeat update without registering applications delay 4 diff --git a/resources/packaging/win/runtime_settings.wxs b/resources/packaging/win/runtime_settings.wxs index ffb54d2f5..ad6fb509f 100644 --- a/resources/packaging/win/runtime_settings.wxs +++ b/resources/packaging/win/runtime_settings.wxs @@ -106,16 +106,6 @@ ) - - - - - - (NOT ONSCREENKEYBOARD) AND ( - (WIX_UPGRADE_DETECTED OR REINSTALL) AND ONSCREENKEYBOARD_FOUND - ) - - @@ -169,7 +159,6 @@ - @@ -242,13 +231,6 @@ - - ONSCREENKEYBOARD - - - - - SHUFFLESCREENKEYBOARD diff --git a/resources/qml/CMakeLists.txt b/resources/qml/CMakeLists.txt deleted file mode 100644 index 47f61726b..000000000 --- a/resources/qml/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -if(IOS) - add_library(AusweisAppQmlPlugins INTERFACE) - qt_import_qml_plugins(AusweisAppQmlPlugins) -endif() diff --git a/resources/qml/Governikus/AuthView/+desktop/DataGroup.qml b/resources/qml/Governikus/AuthView/+desktop/DataGroup.qml deleted file mode 100644 index 8ca094ffc..000000000 --- a/resources/qml/Governikus/AuthView/+desktop/DataGroup.qml +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel - -ColumnLayout { - id: root - - property alias chat: repeater.model - property alias columns: grid.columns - readonly property alias count: repeater.count - property alias title: dataTitle.text - property alias titleStyle: dataTitle.textStyle - property bool writeAccess: false - - spacing: Constants.pane_spacing - visible: count > 0 - - GText { - id: dataTitle - - Accessible.name: dataTitle.text - activeFocusOnTab: true - color: writeAccess ? Style.color.text_warning : titleStyle.textColor - textStyle: Style.text.headline - - FocusFrame { - } - } - Grid { - id: grid - - Layout.fillWidth: true - Layout.preferredWidth: repeater.maxItemWidth * columns + grid.columnSpacing * (columns - 1) - columnSpacing: Constants.pane_spacing - flow: Grid.TopToBottom - verticalItemAlignment: Grid.AlignBottom - - GRepeater { - id: repeater - - visible: count > 0 - - Item { - id: rightItem - - property alias checked: checkBox.checked - - Accessible.name: dataText.text + (optional ? ": " + (selected ? qsTr("selected") : qsTr("not selected")) : "") - Accessible.role: optional ? Accessible.CheckBox : Accessible.StaticText - activeFocusOnTab: true - implicitHeight: dataText.height * 1.5 - implicitWidth: dataText.implicitWidth + (checkBox.visible ? checkBox.implicitWidth : 0) - width: (grid.width - (grid.columnSpacing * (grid.columns - 1))) / grid.columns - - Keys.onSpacePressed: if (optional) - selected = !selected - - GText { - id: dataText - - anchors.left: parent.left - anchors.right: parent.right - anchors.rightMargin: checkBox.visible ? checkBox.width + Constants.pane_spacing : 0 - anchors.verticalCenter: parent.verticalCenter - text: name - textStyle: writeRight ? Style.text.normal_warning : Style.text.normal - - FocusFrame { - marginFactor: 0.7 - scope: rightItem - } - } - GSeparator { - anchors.bottom: parent.bottom - visible: !(index === repeater.count - 1 || ((index + 1) % Math.ceil(repeater.count / grid.columns)) === 0) - width: parent.width - } - GCheckBox { - id: checkBox - - activeFocusOnTab: false - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - checked: selected - visible: optional - } - MouseArea { - anchors.fill: parent - enabled: optional - - onClicked: selected = !selected - - Rectangle { - anchors.fill: parent - color: Style.color.control - opacity: parent.pressed ? 0.5 : 0 - - Behavior on opacity { - NumberAnimation { - duration: 100 - } - } - } - } - } - } - } -} diff --git a/resources/qml/Governikus/AuthView/+desktop/ProviderInfoSection.qml b/resources/qml/Governikus/AuthView/+desktop/ProviderInfoSection.qml deleted file mode 100644 index 0d9456208..000000000 --- a/resources/qml/Governikus/AuthView/+desktop/ProviderInfoSection.qml +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel - -MouseArea { - id: baseItem - - property alias image: icon.source - property string name: "" - property alias title: text.label - - Accessible.name: text.Accessible.name - Accessible.role: Accessible.StaticText - cursorShape: Qt.PointingHandCursor - implicitHeight: contentRow.height - - GridLayout { - id: contentRow - - anchors.verticalCenter: parent.verticalCenter - columnSpacing: Constants.text_spacing - columns: 3 - rowSpacing: columnSpacing - rows: 2 - width: parent.width - - TintableIcon { - id: icon - - Layout.alignment: Qt.AlignVCenter - Layout.rightMargin: Constants.groupbox_spacing - sourceSize.height: Style.dimens.icon_size - tintColor: Style.text.subline.textColor - tintEnabled: true - } - LabeledText { - id: text - - Layout.fillWidth: true - activeFocusOnTab: false - bodyElide: Text.ElideRight - maximumBodyLineCount: 1 - - //: LABEL DESKTOP - text: name.length > 0 ? name : qsTr("See details under \"more...\"") - } - TintableIcon { - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - Layout.rowSpan: 2 - source: "qrc:///images/material_arrow_right.svg" - sourceSize.height: Style.dimens.icon_size - tintColor: Style.color.text - } - GText { - //: LABEL DESKTOP - Accessible.description: qsTr("Show more information about the service provider") - Layout.column: 1 - Layout.row: 1 - Layout.topMargin: Constants.component_spacing - activeFocusOnTab: true - font.pixelSize: plugin.scaleFactor * 24 - //: LABEL DESKTOP - text: qsTr("Details about the provider") - textStyle: Style.text.subline - } - } - FocusFrame { - } -} diff --git a/resources/qml/Governikus/AuthView/+desktop/SelfAuthenticationData.qml b/resources/qml/Governikus/AuthView/+desktop/SelfAuthenticationData.qml deleted file mode 100644 index 67b81598d..000000000 --- a/resources/qml/Governikus/AuthView/+desktop/SelfAuthenticationData.qml +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.SelfAuthModel -import Governikus.Type.UiModule - -SectionPage { - id: baseItem - - signal accept - - titleBarAction: TitleBarAction { - rootEnabled: false - showHelp: false - //: LABEL DESKTOP Title of the self authentication result data view - text: qsTr("Read self-authentication data") - } - - Keys.onEnterPressed: okButton.onClicked() - Keys.onEscapePressed: okButton.onClicked() - Keys.onReturnPressed: okButton.onClicked() - - Connections { - function onFireCancelWorkflow() { - if (SelfAuthModel.workflowCancelled) { - accept(); - } - } - - enabled: visible - target: SelfAuthModel - } - ColumnLayout { - anchors.fill: parent - anchors.margins: Constants.pane_padding * 2 - spacing: Constants.component_spacing - - Row { - id: statusRow - - Layout.preferredHeight: baseItem.height / 4 - spacing: Constants.component_spacing - - TintableIcon { - anchors.verticalCenter: parent.verticalCenter - height: Style.dimens.status_icon_medium - source: "qrc:///images/desktop/status_ok_%1.svg".arg(Style.currentTheme.name) - tintEnabled: false - } - GText { - id: successText - - Accessible.name: successText.text - activeFocusOnTab: true - anchors.verticalCenter: parent.verticalCenter - - //: INFO DESKTOP Status message that the self authentication successfully completed. - text: qsTr("Successfully read data") - textStyle: Style.text.headline - - FocusFrame { - } - } - } - ScrollablePane { - id: pane - - Layout.fillHeight: true - Layout.fillWidth: true - Layout.maximumHeight: implicitHeight - activeFocusOnTab: true - enableDropShadow: true - - //: LABEL DESKTOP Title of the self authentication result data view - title: qsTr("Read data") - - Grid { - id: grid - - columns: 3 - spacing: Constants.groupbox_spacing - verticalItemAlignment: Grid.AlignTop - - Repeater { - id: dataRepeater - - model: SelfAuthModel - - LabeledText { - label: name - text: value === "" ? "---" : value - width: (pane.width - 2 * Constants.pane_padding - (grid.columns - 1) * grid.spacing) / grid.columns - } - } - } - } - GButton { - id: okButton - - Layout.alignment: Qt.AlignHCenter - - //: LABEL DESKTOP - text: qsTr("OK") - - onClicked: baseItem.accept() - } - GSpacer { - Layout.fillHeight: true - } - } -} diff --git a/resources/qml/Governikus/AuthView/+mobile/DataGroup.qml b/resources/qml/Governikus/AuthView/+mobile/DataGroup.qml deleted file mode 100644 index 24d724dc8..000000000 --- a/resources/qml/Governikus/AuthView/+mobile/DataGroup.qml +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global -import Governikus.Style - -Item { - id: root - - property var chat - property int columns: 1 - readonly property alias count: repeater.count - property alias title: dataTitle.text - property alias titleStyle: dataTitle.textStyle - property bool writeAccess: false - - signal scrollPageDown - signal scrollPageUp - - height: column.height - visible: repeater.count > 0 - width: parent.width - - Column { - id: column - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - - PaneTitle { - id: dataTitle - - color: writeAccess ? Style.color.text_warning : titleStyle.textColor - height: implicitHeight * 1.5 - verticalAlignment: Text.AlignTop - width: parent.width - } - Grid { - id: grid - - columnSpacing: Constants.pane_spacing - columns: root.columns - flow: Grid.TopToBottom - verticalItemAlignment: Grid.AlignBottom - width: parent.width - - Repeater { - id: repeater - - model: chat - visible: repeater.count > 0 - - Item { - Accessible.checkable: optional - Accessible.checked: checkBox.checked - Accessible.name: name - Accessible.role: Accessible.ListItem - height: text.implicitHeight + 2 * Constants.text_spacing - width: (grid.width - ((grid.columns - 1) * grid.columnSpacing)) / grid.columns - - Accessible.onPressAction: if (optional) - selected = !selected - Accessible.onScrollDownAction: baseItem.scrollPageDown() - Accessible.onScrollUpAction: baseItem.scrollPageUp() - - GText { - id: text - - Accessible.ignored: true - anchors.left: parent.left - anchors.right: checkBox.left - anchors.verticalCenter: parent.verticalCenter - text: name - textStyle: writeRight ? Style.text.normal_warning : Style.text.normal - } - GSeparator { - anchors.top: parent.bottom - anchors.topMargin: -height - visible: !(index === repeater.count - 1 || ((index + 1) % Math.ceil(repeater.count / grid.columns)) === 0) - width: parent.width - } - GCheckBox { - id: checkBox - - Accessible.ignored: true - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - checked: selected - visible: optional - } - MouseArea { - anchors.fill: parent - enabled: optional - - onClicked: selected = !selected - - Rectangle { - anchors.centerIn: parent - color: Style.color.control - height: parent.height - opacity: parent.pressed ? 0.5 : 0 - width: root.width - - Behavior on opacity { - NumberAnimation { - duration: 100 - } - } - } - } - } - } - } - } -} diff --git a/resources/qml/Governikus/AuthView/+mobile/ProviderInfoSection.qml b/resources/qml/Governikus/AuthView/+mobile/ProviderInfoSection.qml deleted file mode 100644 index c000e56ba..000000000 --- a/resources/qml/Governikus/AuthView/+mobile/ProviderInfoSection.qml +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style - -Item { - property string imageSource - property string name - property string title - - clip: true - height: Math.max(image.height, providerTitle.height) - width: parent.width - - TintableIcon { - id: image - - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - fillMode: Image.PreserveAspectFit - height: Style.dimens.small_icon_size - source: imageSource - tintColor: Style.color.text_subline - width: Style.dimens.small_icon_size - } - LabeledText { - id: providerTitle - - Accessible.ignored: true - anchors.left: image.right - anchors.leftMargin: Constants.groupbox_spacing - anchors.right: parent.right - anchors.verticalCenter: image.verticalCenter - label: title - text: name - } -} diff --git a/resources/qml/Governikus/AuthView/qmldir b/resources/qml/Governikus/AuthView/qmldir deleted file mode 100644 index 73cf4f9dd..000000000 --- a/resources/qml/Governikus/AuthView/qmldir +++ /dev/null @@ -1,14 +0,0 @@ -module AuthView - -internal AuthController AuthController.qml -internal CertificateDescriptionPage CertificateDescriptionPage.qml -internal DataGroup DataGroup.qml -internal ProviderInfoSection ProviderInfoSection.qml -internal SelfAuthenticationData SelfAuthenticationData.qml - -AbortedProgressView 1.0 AbortedProgressView.qml -AuthView 1.0 AuthView.qml -CardPositionView 1.0 CardPositionView.qml -CheckConnectivityView 1.0 CheckConnectivityView.qml -EditRights 1.0 EditRights.qml -TransportPinReminderView 1.0 TransportPinReminderView.qml diff --git a/resources/qml/Governikus/ChangePinView/qmldir b/resources/qml/Governikus/ChangePinView/qmldir deleted file mode 100644 index 68fde0b88..000000000 --- a/resources/qml/Governikus/ChangePinView/qmldir +++ /dev/null @@ -1,6 +0,0 @@ -module ChangePinView - -internal ChangePinController ChangePinController.qml -internal ChangePinViewContent ChangePinViewContent.qml - -ChangePinView 1.0 ChangePinView.qml diff --git a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardView.qml b/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardView.qml deleted file mode 100644 index 4678a4b5e..000000000 --- a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardView.qml +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.SelfAuthenticationView -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.CheckIDCardModel -import Governikus.Type.ReaderPlugIn -import Governikus.Type.UiModule - -FlickableSectionPage { - id: root - - signal startAuth - - spacing: Constants.component_spacing - - //: LABEL ANDROID IOS - title: qsTr("Check device and ID card") - - navigationAction: NavigationAction { - action: NavigationAction.Action.Back - - onClicked: show(UiModule.DEFAULT) - } - - onStartAuth: { - popAll(); - push(selfAuthView); - } - - Component { - id: selfAuthView - - SelfAuthenticationView { - hideTechnologySwitch: true - initialPlugIn: ReaderPlugIn.NFC - - onBack: { - setLockedAndHidden(false); - pop(); - show(UiModule.DEFAULT); - } - } - } - QtObject { - id: d - - function cancel() { - setLockedAndHidden(false); - popAll(); - } - function restartCheck() { - popAll(); - startCheck(); - } - function startCheck() { - setLockedAndHidden(); - push(checkIDCardWorkflow); - } - } - Component { - id: checkIDCardResultView - - CheckIDCardResultView { - title: root.title - - onCancelClicked: d.cancel() - onRestartCheck: d.restartCheck() - onStartAuth: root.startAuth() - } - } - Component { - id: checkIDCardWorkflow - - CheckIDCardWorkflow { - onCancel: d.cancel() - onRestartCheck: d.restartCheck() - onStartAuth: root.startAuth() - } - } - TintableIcon { - Layout.alignment: Qt.AlignHCenter - source: "qrc:///images/mobile/device.svg" - sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control - } - GText { - Layout.alignment: Qt.AlignHCenter - Layout.margins: Constants.pane_padding - horizontalAlignment: Text.AlignHCenter - //: LABEL ANDROID IOS - text: qsTr("To use the eID function, your device must meet certain technical requirements. Furthermore, the eID function must be activated.") - } - GText { - Layout.alignment: Qt.AlignHCenter - Layout.margins: Constants.pane_padding - horizontalAlignment: Text.AlignHCenter - //: LABEL ANDROID IOS - text: qsTr("Check if your smartphone and ID card are ready for use.") - } - GSpacer { - Layout.fillHeight: true - } - GButton { - Layout.alignment: Qt.AlignHCenter - icon.source: "qrc:///images/mobile/device_button.svg" - - //: LABEL ANDROID IOS - text: qsTr("Start check") - tintIcon: true - - onClicked: { - if (ApplicationModel.nfcState === ApplicationModel.NFC_UNAVAILABLE) { - setLockedAndHidden(); - push(checkIDCardResultView, { - "result": CheckIDCardModel.NO_NFC - }); - } else { - d.startCheck(); - } - } - } -} diff --git a/resources/qml/Governikus/CheckIDCardView/qmldir b/resources/qml/Governikus/CheckIDCardView/qmldir deleted file mode 100644 index c60fd3f23..000000000 --- a/resources/qml/Governikus/CheckIDCardView/qmldir +++ /dev/null @@ -1,7 +0,0 @@ -module CheckIDCardView - -internal CheckIDCardResultView CheckIDCardResultView.qml -internal CheckIDCardSuggestionView CheckIDCardSuggestionView.qml -internal CheckIDCardWorkflow CheckIDCardWorkflow.qml - -CheckIDCardView 1.0 CheckIDCardView.qml diff --git a/resources/qml/Governikus/CheckResultView/qmldir b/resources/qml/Governikus/CheckResultView/qmldir deleted file mode 100644 index 031ebb2a4..000000000 --- a/resources/qml/Governikus/CheckResultView/qmldir +++ /dev/null @@ -1,6 +0,0 @@ -module CheckResultView - -CheckResultSuggestionView 1.0 CheckResultSuggestionView.qml -CheckResultView 1.0 CheckResultView.qml -ResultEntry 1.0 ResultEntry.qml -SuggestionData 1.0 SuggestionData.qml diff --git a/resources/qml/Governikus/EnterPasswordView/+desktop/EnterPasswordView.qml b/resources/qml/Governikus/EnterPasswordView/+desktop/EnterPasswordView.qml deleted file mode 100644 index c1be16178..000000000 --- a/resources/qml/Governikus/EnterPasswordView/+desktop/EnterPasswordView.qml +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.RemoteServiceModel - -SectionPage { - id: baseItem - - property string accessibleContinueText - property alias moreInformationText: moreInformation.text - property int passwordType: NumberModel.passwordType - - signal passwordEntered(var pPasswordType) - signal requestPasswordInfo - - Keys.onPressed: event => { - event.accepted = numberField.handleKeyEvent(event.key, event.modifiers); - } - onVisibleChanged: if (!visible) - numberField.number = "" - - QtObject { - id: d - - function setPassword() { - let currentPasswordType = passwordType; // The passwordType binding changes once we set any PIN/CAN/whatever - switch (currentPasswordType) { - case PasswordType.PIN: - case PasswordType.TRANSPORT_PIN: - case PasswordType.SMART_PIN: - NumberModel.pin = numberField.number; - baseItem.passwordEntered(currentPasswordType); - break; - case PasswordType.NEW_SMART_PIN: - case PasswordType.NEW_PIN: - NumberModel.newPin = numberField.number; - mainText.forceActiveFocus(Qt.MouseFocusReason); - baseItem.passwordEntered(currentPasswordType); - break; - case PasswordType.NEW_SMART_PIN_CONFIRMATION: - case PasswordType.NEW_PIN_CONFIRMATION: - NumberModel.newPinConfirmation = numberField.number; - mainText.forceActiveFocus(Qt.MouseFocusReason); - baseItem.passwordEntered(currentPasswordType); - break; - case PasswordType.CAN: - NumberModel.can = numberField.number; - baseItem.passwordEntered(currentPasswordType); - break; - case PasswordType.PUK: - NumberModel.puk = numberField.number; - baseItem.passwordEntered(currentPasswordType); - break; - case PasswordType.REMOTE_PIN: - RemoteServiceModel.connectToRememberedServer(numberField.number); - baseItem.passwordEntered(currentPasswordType); - break; - } - numberField.number = ""; - if (!visible) - mainText.forceActiveFocus(Qt.MouseFocusReason); - } - } - GText { - Accessible.ignored: true - anchors.bottom: retryCounter.top - anchors.bottomMargin: Constants.component_spacing - anchors.horizontalCenter: retryCounter.horizontalCenter - font.bold: true - //: LABEL DESKTOP - text: qsTr("Attempts") - visible: retryCounter.visible - } - RetryCounter { - id: retryCounter - - anchors.left: parent.left - anchors.margins: height - anchors.top: parent.top - visible: NumberModel.retryCounter >= 0 && (passwordType === PasswordType.PIN || passwordType === PasswordType.SMART_PIN) - } - TintableAnimation { - id: animatedIcon - - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.top - anchors.verticalCenterOffset: parent.height / 4 - height: Style.dimens.header_icon_size - source: switch (passwordType) { - case PasswordType.TRANSPORT_PIN: - return "qrc:///images/transportpin_%1.webp".arg(Style.currentTheme.name); - case PasswordType.CAN: - return "qrc:///images/can.webp"; - case PasswordType.SMART_PIN: - case PasswordType.NEW_SMART_PIN: - case PasswordType.NEW_SMART_PIN_CONFIRMATION: - case PasswordType.NEW_PIN_CONFIRMATION: - case PasswordType.NEW_PIN: - case PasswordType.PIN: - return "qrc:///images/pin_person.webp"; - case PasswordType.PUK: - return "qrc:///images/puk_%1.webp".arg(Style.currentTheme.name); - case PasswordType.REMOTE_PIN: - return "qrc:///images/pairingCode.webp"; - default: - return ""; - } - tintColor: Style.color.control - tintEnabled: passwordType !== PasswordType.PUK && passwordType !== PasswordType.TRANSPORT_PIN - visible: source.toString() !== "" - } - GText { - id: mainText - - activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: animatedIcon.bottom - anchors.topMargin: Constants.component_spacing - horizontalAlignment: Text.AlignHCenter - - //: LABEL DESKTOP - text: passwordType === PasswordType.CAN ? qsTr("Enter CAN") : - //: LABEL DESKTOP - passwordType === PasswordType.PUK ? qsTr("Enter PUK") : - //: LABEL DESKTOP - passwordType === PasswordType.REMOTE_PIN ? qsTr("Enter pairing code") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_PIN ? qsTr("Enter new ID card PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Confirm new ID card PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.TRANSPORT_PIN ? qsTr("Enter Transport PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.SMART_PIN ? qsTr("Enter Smart-eID PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_SMART_PIN ? qsTr("Enter new Smart-eID PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Confirm new Smart-eID PIN") : - //: LABEL DESKTOP - qsTr("Enter ID card PIN") - textStyle: Style.text.headline - visible: text !== "" - width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) - - FocusFrame { - } - } - GText { - id: subText - - activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: mainText.bottom - anchors.topMargin: Constants.text_spacing - color: NumberModel.inputError !== "" ? Style.color.text_warning : Style.color.text - horizontalAlignment: Text.AlignHCenter - text: { - if (NumberModel.inputError !== "") { - return NumberModel.inputError; - } - if (passwordType === PasswordType.TRANSPORT_PIN) { - //: INFO DESKTOP The AA2 expects the Transport PIN with five digits. - return qsTr("Please enter the five-digit Transport PIN."); - } - if (passwordType === PasswordType.PIN) { - return ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN ? - //: INFO DESKTOP The AA2 expects the current ID card PIN with six digits in a PIN change. - qsTr("Please enter your current six-digit ID card PIN.") : - //: INFO DESKTOP The AA2 expects a ID card PIN with six digits in an authentication. - qsTr("Please enter your six-digit ID card PIN."); - } - if (passwordType === PasswordType.SMART_PIN) { - if (NumberModel.retryCounter === 1) { - //: INFO DESKTOP The wrong Smart-eID PIN was entered twice on the Smart-eID - return qsTr("You have entered an incorrect, six-digit Smart-eID PIN twice. An incorrect third attempt will invalidate your Smart-eID and you will have to set it up again."); - } - return ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN ? - //: INFO DESKTOP The AA2 expects the current Smart-eID PIN with six digits in a PIN change. - qsTr("Please enter your current six-digit Smart-eID PIN.") : - //: INFO DESKTOP The AA2 expects a Smart-eID PIN with six digits in an authentication. - qsTr("Please enter your six-digit Smart-eID PIN."); - } - if (passwordType === PasswordType.CAN) { - return NumberModel.isCanAllowedMode ? - //: INFO DESKTOP The user is required to enter the six-digit CAN in CAN-allowed authentication. - qsTr("Please enter the six-digit Card Access Number (CAN). You can find it in the bottom right on the front of the ID card.") : - //: INFO DESKTOP The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. - qsTr("A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); - } - if (passwordType === PasswordType.PUK) { - //: INFO DESKTOP The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. - return qsTr("You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first."); - } - if (passwordType === PasswordType.NEW_PIN) { - //: INFO DESKTOP A new six-digit ID card PIN needs to be supplied. - return qsTr("Please enter a new six-digit ID card PIN now."); - } - if (passwordType === PasswordType.NEW_PIN_CONFIRMATION) { - //: INFO DESKTOP The new ID card PIN needs to be entered again for verification. - return qsTr("Please confirm your new six-digit ID card PIN."); - } - if (passwordType === PasswordType.NEW_SMART_PIN) { - //: INFO DESKTOP A new six-digit Smart-eID PIN needs to be supplied. - return qsTr("Please enter a new six-digit Smart-eID PIN now."); - } - if (passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION) { - //: INFO DESKTOP The new Smart-eID PIN needs to be confirmed. - return qsTr("Please confirm your new six-digit Smart-eID PIN."); - } - if (passwordType === PasswordType.REMOTE_PIN) { - //: INFO DESKTOP The pairing code needs to be supplied. - return qsTr("Enter the pairing code shown on your smartphone."); - } - - //: INFO DESKTOP Error message during PIN/CAN/PUK input procedure, the requested password type is unknown; internal error. - return qsTr("Unknown password type:") + " " + passwordType; - } - visible: text !== "" - width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) - - FocusFrame { - } - } - MoreInformationLink { - id: moreInformation - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: subText.bottom - anchors.topMargin: Constants.component_spacing * 3 - visible: text !== "" && passwordType !== PasswordType.REMOTE_PIN - - onClicked: baseItem.requestPasswordInfo() - } - Item { - RoundedRectangle { - id: numberFieldContainer - - anchors.centerIn: parent - borderColor: Style.color.border - height: numberField.height + Constants.component_spacing - width: numberField.width + 2 * Constants.component_spacing - - NumberField { - id: numberField - - anchors.centerIn: parent - passwordLength: passwordType === PasswordType.TRANSPORT_PIN ? 5 : passwordType === PasswordType.PUK ? 10 : passwordType === PasswordType.REMOTE_PIN ? 4 : 6 - - onAccepted: d.setPassword() - } - } - anchors { - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - top: moreInformation.bottom - } - NavigationButton { - id: button - - accessibleText: baseItem.accessibleContinueText !== "" ? baseItem.accessibleContinueText : - //: LABEL DESKTOP - passwordType === PasswordType.CAN ? qsTr("Send CAN") : - //: LABEL DESKTOP - passwordType === PasswordType.PUK ? qsTr("Send PUK") : - //: LABEL DESKTOP - passwordType === PasswordType.REMOTE_PIN ? qsTr("Send pairing code") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_PIN ? qsTr("Send new ID card PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Confirm new ID card PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.TRANSPORT_PIN ? qsTr("Send Transport PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.SMART_PIN ? qsTr("Send Smart-eID PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_SMART_PIN ? qsTr("Send new Smart-eID PIN") : - //: LABEL DESKTOP - passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Confirm new Smart-eID PIN") : - //: LABEL DESKTOP - qsTr("Send ID card PIN") - activeFocusOnTab: true - buttonType: NavigationButton.Type.Forward - enabled: numberField.validInput - size: Style.dimens.huge_icon_size - - onClicked: { - d.setPassword(); - } - - anchors { - left: numberFieldContainer.right - leftMargin: Constants.component_spacing * 2 - verticalCenter: numberFieldContainer.verticalCenter - } - } - } - NumberPad { - anchors.bottom: parent.bottom - anchors.left: parent.left - deleteEnabled: numberField.number.length > 0 - submitAccessibleText: button.accessibleText - submitEnabled: numberField.validInput - - onDeletePressed: { - numberField.removeLast(); - if (numberField.number.length === 0) - numberField.forceActiveFocus(); - } - onDigitPressed: digit => numberField.append(digit) - onSubmitPressed: d.setPassword() - } -} diff --git a/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPad.qml b/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPad.qml deleted file mode 100644 index ab73e2b05..000000000 --- a/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPad.qml +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style -import Governikus.Type.SettingsModel - -Item { - id: baseItem - - property alias deleteEnabled: deleteButton.enabled - property string submitAccessibleText - property alias submitEnabled: submitButton.enabled - - signal deletePressed - signal digitPressed(string digit) - signal submitPressed - - QtObject { - id: d - - readonly property var numbers: { - let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - if (visible && SettingsModel.shuffleScreenKeyboard) { - Utils.shuffle(numbers); - } - return numbers; - } - } - Rectangle { - id: numPadContainer - - anchors.bottom: parent.bottom - anchors.left: parent.left - border.color: Style.color.control - border.width: Math.max(1, plugin.scaleFactor * 3) - color: Style.color.pane - height: grid.height + 2 * Constants.pane_padding - visible: SettingsModel.useScreenKeyboard - width: grid.width + 2 * Constants.pane_padding - - Grid { - id: grid - - anchors.centerIn: parent - columns: 3 - spacing: Constants.component_spacing - - Repeater { - id: numberRepeater - - model: 9 - - NumberPadButton { - text: d.numbers[index] - - onClicked: baseItem.digitPressed(text) - } - } - NumberPadButton { - id: deleteButton - - enabled: baseItem.deleteEnabled - fontScale: 0.75 - text: "C" - - onClicked: baseItem.deletePressed() - } - NumberPadButton { - id: zeroButton - - text: d.numbers[9] - - onClicked: baseItem.digitPressed(text) - } - NumberPadButton { - id: submitButton - - Accessible.name: submitAccessibleText !== "" ? submitAccessibleText : text - enabled: baseItem.submitEnabled - fontScale: 0.75 - text: "OK" - - onClicked: baseItem.submitPressed() - } - } - } -} diff --git a/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPadButton.qml b/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPadButton.qml deleted file mode 100644 index fb833fdd1..000000000 --- a/resources/qml/Governikus/EnterPasswordView/+desktop/NumberPadButton.qml +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.SettingsModel - -Button { - id: control - - property real fontScale: 1 - property bool visualPrivacy: SettingsModel.visualPrivacy - - height: (1.5 * contentItem.font.pixelSize) / fontScale - padding: 0 - width: height / d.aspectRatio - - background: Rectangle { - id: circle - - border.color: Style.text.headline.textColor - border.width: !visualPrivacy && control.focus ? Math.max(1, plugin.scaleFactor * 2) : 0 - color: control.enabled ? (control.down && !visualPrivacy ? Style.color.control : Style.color.pane_sublevel) : Style.color.control_disabled - radius: Style.dimens.control_radius - - MouseArea { - anchors.fill: parent - cursorShape: enabled ? Qt.PointingHandCursor : undefined - } - } - contentItem: GText { - color: control.down && !visualPrivacy ? Style.color.control_pressed : textStyle.textColor - font.pixelSize: fontScale * Style.dimens.text_headline - horizontalAlignment: Text.AlignHCenter - text: control.text - textStyle: Style.text.headline - } - - FocusFrame { - } - QtObject { - id: d - - readonly property real aspectRatio: 0.7 - } -} diff --git a/resources/qml/Governikus/EnterPasswordView/+mobile/EnterPasswordView.qml b/resources/qml/Governikus/EnterPasswordView/+mobile/EnterPasswordView.qml deleted file mode 100644 index 6dbd7aaa8..000000000 --- a/resources/qml/Governikus/EnterPasswordView/+mobile/EnterPasswordView.qml +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.RemoteServiceModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType - -FlickableSectionPage { - id: baseItem - - property string accessibleContinueText - property alias enableTransportPinLink: transportPinLink.visible - property string inputError - property alias moreInformationText: moreInformation.text - required property int passwordType - - signal changePinLength - signal passwordEntered(var pPasswordType) - signal requestPasswordInfo - - fillWidth: true - - Keys.onPressed: event => { - event.accepted = pinField.handleKeyEvent(event.key, event.modifiers); - } - onVisibleChanged: pinField.number = "" - - QtObject { - id: d - - function setPassword() { - switch (passwordType) { - case PasswordType.PIN: - case PasswordType.TRANSPORT_PIN: - case PasswordType.SMART_PIN: - NumberModel.pin = pinField.number; - baseItem.passwordEntered(passwordType); - break; - case PasswordType.NEW_SMART_PIN: - case PasswordType.NEW_PIN: - NumberModel.newPin = pinField.number; - baseItem.passwordEntered(passwordType); - break; - case PasswordType.NEW_SMART_PIN_CONFIRMATION: - case PasswordType.NEW_PIN_CONFIRMATION: - NumberModel.newPinConfirmation = pinField.number; - baseItem.passwordEntered(passwordType); - break; - case PasswordType.CAN: - NumberModel.can = pinField.number; - baseItem.passwordEntered(passwordType); - break; - case PasswordType.PUK: - NumberModel.puk = pinField.number; - baseItem.passwordEntered(passwordType); - break; - case PasswordType.REMOTE_PIN: - RemoteServiceModel.connectToRememberedServer(pinField.number); - baseItem.passwordEntered(passwordType); - break; - } - pinField.number = ""; - } - } - GridLayout { - id: grid - - readonly property bool isLandscape: width > Math.max(infoLayout.Layout.minimumWidth, pinField.Layout.preferredWidth) + separator.effectiveImplicitWidth + numberPad.implicitWidth - - Layout.maximumHeight: Number.POSITIVE_INFINITY - Layout.maximumWidth: Number.POSITIVE_INFINITY - Layout.minimumWidth: Math.max(infoLayout.Layout.minimumWidth, numberPad.Layout.minimumWidth) - columnSpacing: 0 - flow: isLandscape ? GridLayout.LeftToRight : GridLayout.TopToBottom - rowSpacing: Constants.component_spacing - - ColumnLayout { - id: infoLayout - - Layout.alignment: Qt.AlignCenter - Layout.maximumWidth: Style.dimens.max_text_width - spacing: 0 - - GText { - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - - //: LABEL ANDROID IOS - text: passwordType === PasswordType.CAN ? qsTr("Enter CAN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.PUK ? qsTr("Enter PUK") : - //: LABEL ANDROID IOS - passwordType === PasswordType.REMOTE_PIN ? qsTr("Enter pairing code") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_PIN ? qsTr("Enter new ID card PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Confirm new ID card PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.TRANSPORT_PIN ? qsTr("Enter Transport PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.SMART_PIN ? qsTr("Enter Smart-eID PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_SMART_PIN ? qsTr("Enter new Smart-eID PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Confirm new Smart-eID PIN") : - //: LABEL ANDROID IOS - qsTr("Enter ID card PIN") - textStyle: Style.text.headline - } - GText { - id: infoText - - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Constants.text_spacing - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - maximumLineCount: 3 - text: { - if (!!inputError) { - return inputError; - } - if (passwordType === PasswordType.SMART_PIN && NumberModel.retryCounter === 1) { - //: INFO ANDROID IOS The wrong Smart-eID PIN was entered twice on the Smart-eID - return qsTr("You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again."); - } - if (passwordType === PasswordType.CAN) { - if (NumberModel.isCanAllowedMode) { - //: INFO ANDROID IOS The user is required to enter the six-digit CAN in CAN-allowed authentication. - return qsTr("Please enter the six-digit Card Access Number (CAN). You can find it in the bottom right on the front of the ID card."); - } - //: INFO ANDROID IOS The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. - return qsTr("A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); - } - if (passwordType === PasswordType.PUK) { - //: INFO ANDROID IOS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. - return qsTr("You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first."); - } - if (passwordType === PasswordType.NEW_PIN) { - //: INFO ANDROID IOS A new six-digit ID card PIN needs to be supplied. - return qsTr("Please enter a new six-digit ID card PIN now."); - } - if (passwordType === PasswordType.NEW_PIN_CONFIRMATION) { - //: INFO ANDROID IOS The new ID card PIN needs to be confirmed. - return qsTr("Please confirm your new six-digit ID card PIN."); - } - if (passwordType === PasswordType.NEW_SMART_PIN) { - //: INFO ANDROID IOS A new six-digit Smart-eID PIN needs to be supplied. - return qsTr("Please enter a new six-digit Smart-eID PIN now."); - } - if (passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION) { - //: INFO ANDROID IOS The new Smart-eID PIN needs to be confirmed. - return qsTr("Please confirm your new six-digit Smart-eID PIN."); - } - if (passwordType === PasswordType.TRANSPORT_PIN) { - //: INFO ANDROID IOS The Transport PIN is required by AA2, it needs to be change to an actual PIN. - return qsTr("Please enter the five-digit Transport PIN."); - } - if (passwordType === PasswordType.REMOTE_PIN) { - //: INFO ANDROID IOS The pairing code for the smartphone is required. - return qsTr("Enter the pairing code shown on the device you want to pair."); - } - if (passwordType === PasswordType.SMART_PIN) { - return ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN ? - //: INFO ANDROID IOS The AA2 expects the current Smart-eID PIN with six digits in a PIN change. - qsTr("Please enter your current six-digit Smart-eID PIN.") : - //: INFO ANDROID IOS The AA2 expects a Smart-eID PIN with six digits in an authentication. - qsTr("Please enter your six-digit Smart-eID PIN."); - } - return ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN ? - //: INFO ANDROID IOS The AA2 expects the current ID card PIN with six digits in a PIN change. - qsTr("Please enter your current six-digit ID card PIN.") : - //: INFO ANDROID IOS The AA2 expects a ID card PIN with six digits in an authentication. - qsTr("Please enter your six-digit ID card PIN."); - } - textStyle: { - if (!!inputError || (passwordType === PasswordType.CAN && !NumberModel.isCanAllowedMode) || passwordType === PasswordType.PUK) { - return Style.text.normal_warning; - } else { - return Style.text.normal; - } - } - - MouseArea { - anchors.fill: parent - anchors.margins: -12 - enabled: infoText.truncated - - onClicked: completeTextPopup.open() - } - } - GSpacer { - Layout.fillHeight: true - visible: !grid.isLandscape - } - MoreInformationLink { - id: transportPinLink - - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Constants.text_spacing - text: (passwordType === PasswordType.TRANSPORT_PIN ? - //: LABEL ANDROID IOS Button to switch to a six-digit ID card PIN. - qsTr("Do you have a six-digit ID card PIN?") : - //: LABEL ANDROID IOS Button to start a change of the Transport PIN. - qsTr("Do you have a five-digit Transport PIN?")) - visible: false - - onClicked: baseItem.changePinLength() - } - MoreInformationLink { - id: moreInformation - - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Constants.text_spacing - visible: text !== "" && passwordType !== PasswordType.REMOTE_PIN - - onClicked: baseItem.requestPasswordInfo() - } - NumberField { - id: pinField - - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - Layout.topMargin: Constants.component_spacing - padding: Constants.component_spacing / 2 - passwordLength: passwordType === PasswordType.REMOTE_PIN ? 4 : passwordType === PasswordType.TRANSPORT_PIN ? 5 : passwordType === PasswordType.PUK ? 10 : 6 - - background: Rectangle { - border.color: Style.color.border - border.width: Style.dimens.separator_size - color: Style.color.transparent - radius: Style.dimens.control_radius - } - - onAccepted: d.setPassword() - } - } - GSeparator { - id: separator - - readonly property real effectiveImplicitWidth: Layout.leftMargin + implicitWidth + Layout.rightMargin - - Layout.alignment: Qt.AlignCenter - Layout.leftMargin: Constants.component_spacing - Layout.preferredHeight: grid.height * 0.75 - Layout.rightMargin: Constants.component_spacing - orientation: Qt.Vertical - visible: grid.isLandscape - } - GSpacer { - Layout.fillWidth: true - visible: grid.isLandscape - } - NumberPad { - id: numberPad - - Layout.alignment: grid.isLandscape ? Qt.AlignCenter : Qt.AlignHCenter | Qt.AlignTop - deleteEnabled: pinField.number.length > 0 - submitAccessibleText: baseItem.accessibleContinueText !== "" ? baseItem.accessibleContinueText : - //: LABEL ANDROID IOS - passwordType === PasswordType.CAN ? qsTr("Send CAN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.PUK ? qsTr("Send PUK") : - //: LABEL ANDROID IOS - passwordType === PasswordType.REMOTE_PIN ? qsTr("Send pairing code") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_PIN ? qsTr("Send new ID card PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Send confirmation of new ID card PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.TRANSPORT_PIN ? qsTr("Send Transport PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.SMART_PIN ? qsTr("Send Smart-eID PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_SMART_PIN ? qsTr("Send new Smart-eID PIN") : - //: LABEL ANDROID IOS - passwordType === PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Send confirmation of new Smart-eID PIN") : - //: LABEL ANDROID IOS - qsTr("Send ID card PIN") - submitEnabled: pinField.validInput - - onDeletePressed: { - pinField.removeLast(); - if (pinField.number.length === 0) - pinField.forceActiveFocus(); - } - onDigitPressed: digit => pinField.append(digit) - onSubmitPressed: d.setPassword() - } - GSpacer { - Layout.fillWidth: true - visible: grid.isLandscape - } - } - ConfirmationPopup { - id: completeTextPopup - - style: ConfirmationPopup.PopupStyle.OkButton - text: infoText.text - } -} diff --git a/resources/qml/Governikus/EnterPasswordView/+mobile/NumberPadButton.qml b/resources/qml/Governikus/EnterPasswordView/+mobile/NumberPadButton.qml deleted file mode 100644 index c541dfe6b..000000000 --- a/resources/qml/Governikus/EnterPasswordView/+mobile/NumberPadButton.qml +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.Type.SettingsModel - -Button { - id: numberPadButton - - property string a11yDisabledText: qsTr("Disabled") - property string a11yText - property bool visualPrivacy: SettingsModel.visualPrivacy - - Accessible.name: numberPadButton.enabled ? a11yText !== "" ? a11yText : text : a11yDisabledText - Layout.maximumHeight: implicitHeight - Layout.maximumWidth: implicitWidth - Layout.minimumHeight: Layout.minimumWidth * d.aspectRatio - Layout.minimumWidth: 36 - implicitHeight: implicitWidth * d.aspectRatio - implicitWidth: 75 - - background: Rectangle { - anchors.fill: numberPadButton - color: numberPadButton.enabled ? (numberPadButton.down && !visualPrivacy ? Style.color.control : Style.color.pane_sublevel) : Style.color.control_disabled - radius: Style.dimens.control_radius - - TintableIcon { - anchors.centerIn: parent - fillMode: Image.Pad - source: numberPadButton.icon.source - sourceSize.height: contentItem.font.pixelSize * 1.5 - tintColor: numberPadButton.down && !visualPrivacy ? Style.color.control_pressed : contentText.textStyle.textColor - tintEnabled: true - visible: numberPadButton.icon.source != "" - } - } - contentItem: GText { - id: contentText - - Accessible.ignored: true - color: numberPadButton.down && !visualPrivacy ? Style.color.control_pressed : textStyle.textColor - horizontalAlignment: Text.AlignHCenter - text: numberPadButton.text - textStyle: Style.text.headline - visible: numberPadButton.icon.source == "" - } - - Accessible.onPressAction: if (numberPadButton.enabled) - clicked() - - QtObject { - id: d - - readonly property real aspectRatio: 0.7 - } -} diff --git a/resources/qml/Governikus/EnterPasswordView/qmldir b/resources/qml/Governikus/EnterPasswordView/qmldir deleted file mode 100644 index 70bece12a..000000000 --- a/resources/qml/Governikus/EnterPasswordView/qmldir +++ /dev/null @@ -1,6 +0,0 @@ -module EnterPasswordView - -internal NumberPad NumberPad.qml -internal NumberPadButton NumberPadButton.qml - -EnterPasswordView 1.0 EnterPasswordView.qml diff --git a/resources/qml/Governikus/FeedbackView/+desktop/LogView.qml b/resources/qml/Governikus/FeedbackView/+desktop/LogView.qml deleted file mode 100644 index 3fe52b51a..000000000 --- a/resources/qml/Governikus/FeedbackView/+desktop/LogView.qml +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.Type.LogModel - -SectionPage { - id: root - - signal keyPressed(int key) - - titleBarAction: TitleBarAction { - //: LABEL DESKTOP - text: qsTr("Logs") - } - - Keys.onPressed: event => { - keyPressed(event.key); - } - - TabbedPane { - id: tabbedPane - - anchors.fill: parent - contentDelegate: logContentDelegate - contentRightMargin: 0 - sectionsModel: LogModel.logFileNames - - footerItem: Item { - height: buttonLayout.implicitHeight - - ColumnLayout { - id: buttonLayout - - spacing: Constants.groupbox_spacing - - anchors { - left: parent.left - right: parent.right - rightMargin: Constants.groupbox_spacing - } - GButton { - id: saveLog - - Layout.maximumWidth: Number.POSITIVE_INFINITY - enabled: tabbedPane.sectionsModel.length > 0 - icon.source: "qrc:///images/desktop/save_icon.svg" - //: LABEL DESKTOP - text: qsTr("Save log") - tintIcon: true - - onClicked: { - let filenameSuggestion = LogModel.createLogFileName(LogModel.getCurrentLogFileDate()); - fileDialog.selectFile(filenameSuggestion); - } - - GFileDialog { - id: fileDialog - - defaultSuffix: "log" - //: LABEL DESKTOP - nameFilters: qsTr("Logfiles (*.log)") - - //: LABEL DESKTOP - title: qsTr("Save log") - - onAccepted: LogModel.saveCurrentLogFile(file) - } - } - GButton { - id: removeLog - - Layout.maximumWidth: Number.POSITIVE_INFINITY - disabledTooltipText: qsTr("The current log will be automatically deleted at exit.") - enableButton: tabbedPane.currentIndex > 0 - icon.source: "qrc:///images/desktop/trash_icon_white.svg" - //: LABEL DESKTOP - text: qsTr("Delete log") - tintIcon: true - - onClicked: { - confirmationPopup.deleteAll = false; - confirmationPopup.open(); - } - } - GButton { - id: removeAllLogs - - Layout.maximumWidth: Number.POSITIVE_INFINITY - enableButton: tabbedPane.sectionsModel.length > 1 - icon.source: "qrc:///images/trash_icon_old.svg" - //: LABEL DESKTOP - text: qsTr("Delete old logs") - tintIcon: true - - onClicked: { - confirmationPopup.deleteAll = true; - confirmationPopup.open(); - } - } - GButton { - property QtObject detachedLogViewItem: null - - Layout.maximumWidth: Number.POSITIVE_INFINITY - icon.source: "qrc:///images/desktop/material_open_in_browser.svg" - text: qsTr("Detach log viewer") - tintIcon: true - - onClicked: ApplicationWindow.window.showDetachedLogView() - } - } - } - - onCurrentIndexChanged: LogModel.setLogFile(currentIndex) - } - Component { - id: logContentDelegate - - GListView { - id: logView - - activeFocusOnTab: true - displayMarginBeginning: Constants.pane_padding - displayMarginEnd: Constants.pane_padding - implicitHeight: tabbedPane.availableHeight - model: LogModel - - delegate: FocusScope { - readonly property bool isFirstItem: index === 0 - readonly property bool isLastItem: index === ListView.view.count - 1 - - implicitHeight: logDelegate.implicitHeight + logDelegate.anchors.topMargin + logDelegate.anchors.bottomMargin - width: logView.width - Constants.pane_padding - - RoundedRectangle { - anchors.fill: parent - bottomLeftCorner: isLastItem - bottomRightCorner: isLastItem - color: Style.color.pane - topLeftCorner: isFirstItem - topRightCorner: isFirstItem - } - LogViewDelegate { - id: logDelegate - - focus: true - - anchors { - bottomMargin: isLastItem ? Constants.pane_padding : 0 - fill: parent - leftMargin: Constants.pane_padding - rightMargin: Constants.pane_padding - topMargin: isFirstItem ? Constants.pane_padding : Constants.text_spacing - } - } - } - - layer { - enabled: GraphicsInfo.api !== GraphicsInfo.Software - - effect: GDropShadow { - } - } - Connections { - function onFireNewLogMsg() { - if (logView.atYEnd) - logView.positionViewAtEnd(); - } - - target: LogModel - } - Connections { - function onKeyPressed(pKey) { - logView.handleKeyPress(pKey); - } - - target: root - } - } - } - ConfirmationPopup { - id: confirmationPopup - - property bool deleteAll: true - - //: INFO DESKTOP All logfiles are about to be removed, user confirmation required. - text: (deleteAll ? qsTr("All old logs will be deleted.") : - //: INFO DESKTOP The current logfile is about to be removed, user confirmation required. - qsTr("The log will be deleted.")) - title: (deleteAll ? - //: LABEL DESKTOP - qsTr("Delete old logs") : - //: LABEL DESKTOP - qsTr("Delete selected log")) - width: plugin.scaleFactor * 600 - - onConfirmed: deleteAll ? LogModel.removeOtherLogFiles() : LogModel.removeCurrentLogFile() - } -} diff --git a/resources/qml/Governikus/FeedbackView/qmldir b/resources/qml/Governikus/FeedbackView/qmldir deleted file mode 100644 index 35b13ba16..000000000 --- a/resources/qml/Governikus/FeedbackView/qmldir +++ /dev/null @@ -1,8 +0,0 @@ -module FeedbackView - -internal LogTitleBarControls LogTitleBarControls.qml -internal LogViewDelegate LogViewDelegate.qml - -DetachedLogView 1.0 DetachedLogView.qml -LogView 1.0 LogView.qml -StoreFeedbackPopup 1.0 StoreFeedbackPopup.qml diff --git a/resources/qml/Governikus/Global/+desktop/NavigationButton.qml b/resources/qml/Governikus/Global/+desktop/NavigationButton.qml deleted file mode 100644 index 6277ca865..000000000 --- a/resources/qml/Governikus/Global/+desktop/NavigationButton.qml +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Style -import Governikus.View - -Button { - id: control - - enum Type { - Forward, - Back, - Check, - Cancel - } - - property string accessibleText - property int buttonType: NavigationButton.Type.Forward - property string iconSource - property string iconText - property double size: plugin.scaleFactor * 160 - property string subText - - Accessible.name: accessibleText !== "" ? accessibleText : text - Accessible.role: Accessible.Button - implicitHeight: column.implicitHeight - implicitWidth: column.implicitWidth - text: subText !== "" ? subText : (buttonType === NavigationButton.Type.Check ? qsTr("Yes") : buttonType === NavigationButton.Type.Cancel ? qsTr("No") : buttonType === NavigationButton.Type.Forward ? qsTr("Continue") : qsTr("Back")) - - background: Item { - } - contentItem: Item { - } - - ColumnLayout { - id: column - - anchors.fill: parent - spacing: Constants.component_spacing - - Rectangle { - id: icon - - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: Layout.preferredWidth - Layout.preferredWidth: control.size - color: enabled ? Style.color.control : Style.color.control_disabled - radius: height / 2 - - TintableIcon { - anchors.centerIn: parent - rotation: iconSource === "" && buttonType === NavigationButton.Type.Back ? 180 : 0 - source: { - if (iconSource !== "") { - return iconSource; - } - if (iconText !== "") { - return ""; - } - return buttonType === NavigationButton.Type.Check ? "qrc:///images/material_check.svg" : buttonType === NavigationButton.Type.Cancel ? "qrc:///images/material_clear.svg" : "qrc:///images/desktop/material_arrow_forward.svg"; - } - sourceSize.height: Style.dimens.large_icon_size - tintColor: Style.color.control_content - } - GText { - anchors.centerIn: parent - text: iconText - textStyle: Style.text.headline - visible: iconText !== "" - } - } - GText { - id: buttonText - - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - text: control.subText - textStyle: Style.text.headline - visible: control.subText !== "" - } - } - FocusFrame { - } - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - - onPressed: mouse => { - mouse.accepted = false; - } - } -} diff --git a/resources/qml/Governikus/Global/+desktop/PlatformConstants.qml b/resources/qml/Governikus/Global/+desktop/PlatformConstants.qml deleted file mode 100644 index 4f862f71e..000000000 --- a/resources/qml/Governikus/Global/+desktop/PlatformConstants.qml +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -Item { - readonly property int component_spacing: plugin.scaleFactor * 30 - readonly property int groupbox_spacing: plugin.scaleFactor * 20 - readonly property bool is_desktop: true - readonly property int pane_padding: plugin.scaleFactor * 30 - readonly property int pane_spacing: plugin.scaleFactor * 30 - readonly property int subtext_spacing: Math.max(1, plugin.scaleFactor * 3) - readonly property int text_spacing: plugin.scaleFactor * 10 -} diff --git a/resources/qml/Governikus/Global/+desktop/RetryCounter.qml b/resources/qml/Governikus/Global/+desktop/RetryCounter.qml deleted file mode 100644 index 50cddcdbd..000000000 --- a/resources/qml/Governikus/Global/+desktop/RetryCounter.qml +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global -import Governikus.Style -import Governikus.Type.NumberModel -import Governikus.View - -Rectangle { - //: LABEL DESKTOP - Accessible.name: qsTr("Remaining ID card PIN attempts: %1").arg(iconText.text) - Accessible.role: Accessible.StaticText - activeFocusOnTab: true - border.color: Style.color.control - border.width: height / 40 - color: Style.color.transparent - implicitHeight: Style.dimens.status_icon_small - implicitWidth: implicitHeight - radius: height / 2 - width: height - - Rectangle { - id: content - - anchors.fill: parent - anchors.margins: parent.height / 8 - border.color: Style.color.pane_border - border.width: Style.dimens.border_width - color: Style.color.control - radius: height / 2 - - GText { - id: iconText - - Accessible.ignored: true - anchors.centerIn: parent - color: Style.color.control_content - text: NumberModel.retryCounter - textStyle: Style.text.headline - visible: text !== "" - } - } - FocusFrame { - } -} diff --git a/resources/qml/Governikus/Global/+desktop/ScrollablePane.qml b/resources/qml/Governikus/Global/+desktop/ScrollablePane.qml deleted file mode 100644 index 392cedc29..000000000 --- a/resources/qml/Governikus/Global/+desktop/ScrollablePane.qml +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel - -Item { - id: root - - property alias backgroundColor: background.color - property alias content: paneContent - default property alias data: paneContent.data - property bool enableDropShadow: false - property real minimumVisibleContentHeight: 0 - property alias title: titleText.text - - function scrollYPositionIntoView(pYposition) { - let availableFlickableHeight = flickable.height - paneContent.anchors.margins; - let dy = pYposition - flickable.contentY - availableFlickableHeight; - if (dy > 0 || flickable.contentY > 0) { - flickable.contentY += dy; - if (flickable.contentY < 0) - flickable.contentY = 0; - else if (flickable.contentY + availableFlickableHeight > flickable.contentHeight) - flickable.contentY = flickable.contentHeight - availableFlickableHeight; - } - } - - Accessible.focusable: true - Accessible.name: titleText.text - Accessible.role: Accessible.Grouping - Layout.minimumHeight: content.Layout.minimumHeight + 2 * content.anchors.margins - implicitHeight: content.implicitHeight + 2 * content.anchors.margins - implicitWidth: content.implicitWidth + 2 * content.anchors.margins - - GPaneBackground { - id: background - - anchors.fill: parent - - layer { - enabled: GraphicsInfo.api !== GraphicsInfo.Software && enableDropShadow - - effect: GDropShadow { - } - } - } - ColumnLayout { - id: content - - anchors.fill: parent - anchors.margins: Style.dimens.border_width - clip: true - - GFlickable { - id: flickable - - readonly property real reservedTitleHeight: (root.title === "" ? 0 : titleText.height + Constants.pane_spacing) - - Layout.alignment: Qt.AlignTop - Layout.bottomMargin: Constants.pane_padding - Layout.fillHeight: true - Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.maximumHeight: contentHeight - Layout.minimumHeight: root.minimumVisibleContentHeight ? reservedTitleHeight + root.minimumVisibleContentHeight : -1 - Layout.preferredHeight: contentColumn.implicitHeight - Layout.topMargin: Constants.pane_padding - contentHeight: contentColumn.implicitHeight - - ColumnLayout { - id: contentColumn - - anchors.fill: parent - anchors.rightMargin: Constants.pane_padding - spacing: Constants.pane_spacing - - GText { - id: titleText - - elide: Text.ElideRight - textStyle: Style.text.headline - visible: text !== "" - - FocusFrame { - scope: root - } - } - ColumnLayout { - id: paneContent - - Layout.fillWidth: true - spacing: Constants.pane_spacing - } - } - } - } - ScrollGradients { - anchors.fill: parent - anchors.margins: Style.dimens.border_width - color: background.color - } -} diff --git a/resources/qml/Governikus/Global/+mobile/+android/ConfirmationPopup.qml b/resources/qml/Governikus/Global/+mobile/+android/ConfirmationPopup.qml deleted file mode 100644 index 707653b97..000000000 --- a/resources/qml/Governikus/Global/+mobile/+android/ConfirmationPopup.qml +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global -import Governikus.Style - -BaseConfirmationPopup { - id: root - - buttons: Flow { - layoutDirection: Qt.RightToLeft - spacing: 0 - width: parent.width - - GButton { - background: null - text: root.okButtonText - textStyle: Style.text.normal - visible: style & ConfirmationPopup.PopupStyle.OkButton - - onClicked: root.accept() - } - GButton { - background: null - text: root.cancelButtonText - textStyle: Style.text.normal - visible: style & ConfirmationPopup.PopupStyle.CancelButton - - onClicked: root.cancel() - } - } -} diff --git a/resources/qml/Governikus/Global/+mobile/+ios/ConfirmationPopup.qml b/resources/qml/Governikus/Global/+mobile/+ios/ConfirmationPopup.qml deleted file mode 100644 index 7c0bc2a26..000000000 --- a/resources/qml/Governikus/Global/+mobile/+ios/ConfirmationPopup.qml +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style - -BaseConfirmationPopup { - id: root - - horizontalTextAlignment: Text.AlignHCenter - - buttons: ColumnLayout { - spacing: 0 - width: parent.width - - GSeparator { - Layout.fillWidth: true - visible: style !== ConfirmationPopup.PopupStyle.NoButtons - } - RowLayout { - Layout.fillWidth: true - spacing: 0 - - GButton { - Layout.fillWidth: true - background: null - text: root.cancelButtonText - textStyle: Style.text.normal - visible: style & ConfirmationPopup.PopupStyle.CancelButton - - onClicked: root.cancel() - } - GSeparator { - Layout.fillHeight: true - orientation: Qt.Vertical - visible: style & ConfirmationPopup.PopupStyle.CancelButton && style & ConfirmationPopup.PopupStyle.OkButton - } - GButton { - Layout.fillWidth: true - background: null - text: root.okButtonText - textStyle: Style.text.normal - visible: style & ConfirmationPopup.PopupStyle.OkButton - - onClicked: root.accept() - } - } - } -} diff --git a/resources/qml/Governikus/Global/+mobile/MenuItem.qml b/resources/qml/Governikus/Global/+mobile/MenuItem.qml deleted file mode 100644 index 57833df3e..000000000 --- a/resources/qml/Governikus/Global/+mobile/MenuItem.qml +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style - -RoundedRectangle { - id: baseItem - - property alias description: descriptionText.text - property bool drawBottomCorners: false - property bool drawTopCorners: false - property var icon: "qrc:///images/material_arrow_right.svg" - property alias tintIcon: iconItem.tintEnabled - property alias title: titleText.text - - signal clicked - - Accessible.name: title + ". " + description - Accessible.role: Accessible.Button - bottomLeftCorner: drawBottomCorners - bottomRightCorner: drawBottomCorners - color: mouseArea.pressed ? Style.color.pane_active : Style.color.transparent - implicitHeight: layout.implicitHeight + layout.anchors.topMargin + layout.anchors.bottomMargin - implicitWidth: layout.implicitWidth + layout.anchors.leftMargin + layout.anchors.rightMargin - topLeftCorner: drawTopCorners - topRightCorner: drawTopCorners - - Accessible.onPressAction: clicked() - - RowLayout { - id: layout - - anchors.fill: parent - anchors.margins: Constants.pane_padding - spacing: 0 - - ColumnLayout { - GText { - id: titleText - - Accessible.ignored: true - color: mouseArea.pressed ? Style.color.text_subline_pressed : textStyle.textColor - textStyle: Style.text.subline - visible: text !== "" - } - GText { - id: descriptionText - - Accessible.ignored: true - color: mouseArea.pressed ? Style.color.text_pressed : textStyle.textColor - visible: text !== "" - } - } - TintableIcon { - id: iconItem - - Accessible.ignored: true - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - Layout.preferredWidth: Style.dimens.icon_size - source: baseItem.icon - sourceSize.height: Style.dimens.small_icon_size - tintColor: Style.color.text - } - } - MouseArea { - id: mouseArea - - anchors.fill: parent - - onClicked: baseItem.clicked() - } -} diff --git a/resources/qml/Governikus/Global/+mobile/SwipeActionDelegate.qml b/resources/qml/Governikus/Global/+mobile/SwipeActionDelegate.qml deleted file mode 100644 index 566527ea4..000000000 --- a/resources/qml/Governikus/Global/+mobile/SwipeActionDelegate.qml +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Global - -Item { - id: baseItem - - property string actionAccessibleName - property alias actionColor: actionBackground.color - property alias actionIcon: actionImage.source - property alias actionIconTintColor: actionImage.tintColor - property alias contentItem: content.children - property alias pressed: mouseArea.downOnContent - - signal actionClicked - signal clicked - - height: content.childrenRect.height - width: content.childrenRect.width - - Rectangle { - id: actionBackground - - width: Math.abs(mouseArea.contentX) - - anchors { - bottom: parent.bottom - right: parent.right - top: parent.top - } - } - TintableIcon { - id: actionImage - - Accessible.name: actionAccessibleName - Accessible.role: Accessible.Button - width: Math.abs(mouseArea.actionOpenOffset) - anchors.margins * 2 - - Accessible.onPressAction: baseItem.actionClicked() - - anchors { - bottom: parent.bottom - margins: Constants.component_spacing - right: parent.right - top: parent.top - } - } - Item { - id: content - - height: parent.height - width: parent.width - - Behavior on x { - NumberAnimation { - duration: Constants.animation_duration - - onRunningChanged: { - if (!running && content.x <= -content.width) { - baseItem.actionClicked(); - } - } - } - } - } - MouseArea { - id: mouseArea - - readonly property real actionOpenOffset: -parent.width / 4 - property real contentStartX: 0.0 - property alias contentX: content.x - readonly property bool deleteOffsetReached: contentX < 2 * actionOpenOffset - property bool didDrag: false - readonly property bool downOnAction: pressed && !downOnContent - readonly property bool downOnContent: pressed && startX < contentStartX + content.width - readonly property bool isActionOpen: contentX === actionOpenOffset - property real startX: 0.0 - - anchors.fill: parent - - onPressed: mouse => { - startX = mouse.x; - contentStartX = content.x; - didDrag = false; - } - onReleased: { - if (didDrag) { - if (contentX > actionOpenOffset / 2) { - contentX = 0; - } else if (deleteOffsetReached) { - contentX = drag.minimumX; - } else { - contentX = actionOpenOffset; - } - } else if (downOnContent) { - if (isActionOpen) { - contentX = 0; - } else { - baseItem.clicked(); - } - } else if (downOnAction) { - baseItem.actionClicked(); - } - } - - drag { - axis: Drag.XAxis - filterChildren: true - maximumX: 0 - minimumX: -content.width - target: content - threshold: 10 - - onActiveChanged: didDrag = true - } - } -} diff --git a/resources/qml/Governikus/Global/+qt5/RegExpValidatorCompat.qml b/resources/qml/Governikus/Global/+qt5/RegExpValidatorCompat.qml deleted file mode 100644 index a3db7f245..000000000 --- a/resources/qml/Governikus/Global/+qt5/RegExpValidatorCompat.qml +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -RegExpValidator { - property var expression - - regExp: expression -} diff --git a/resources/qml/Governikus/Global/+qt6/RegExpValidatorCompat.qml b/resources/qml/Governikus/Global/+qt6/RegExpValidatorCompat.qml deleted file mode 100644 index 6ef644281..000000000 --- a/resources/qml/Governikus/Global/+qt6/RegExpValidatorCompat.qml +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -RegularExpressionValidator { - property var expression - - regularExpression: expression -} diff --git a/resources/qml/Governikus/Global/GButton.qml b/resources/qml/Governikus/Global/GButton.qml deleted file mode 100644 index a550cc1ab..000000000 --- a/resources/qml/Governikus/Global/GButton.qml +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel - -AbstractButton { - id: root - - property alias buttonColor: d.color - property alias cursorShape: mouseArea.cursorShape - property string disabledTooltipText - - // Similar to "enabled", but tooltips will continue to work - property bool enableButton: true - property string enabledTooltipText - property alias iconSize: buttonIcon.sourceSize.height - property alias maximumLineCount: buttonText.maximumLineCount - property color textDisabledColor: Style.color.control_content_disabled - property color textHighlightColor: Style.color.control_content_pressed - property TextStyle textStyle: Style.text.button - property bool tintIcon: false - - Accessible.name: text - Layout.fillWidth: true - Layout.maximumWidth: Math.ceil(implicitWidth) - Layout.minimumWidth: Style.dimens.min_button_width - ToolTip.delay: Constants.toolTipDelay - ToolTip.text: enableButton ? enabledTooltipText : disabledTooltipText - ToolTip.visible: hovered && ToolTip.text !== "" - activeFocusOnTab: enableButton - font.pixelSize: textStyle.textSize - horizontalPadding: 8 - verticalPadding: 6 - - background: Rectangle { - border.color: d.borderColor - border.width: Style.dimens.border_width - color: d.color - radius: Style.dimens.control_radius - - FocusFrame { - borderColor: Style.color.control_border - marginFactor: 0.8 - radius: parent.radius * 1.2 - scope: root - } - } - contentItem: RowLayout { - RowLayout { - id: contentLayout - - Layout.maximumWidth: Number.POSITIVE_INFINITY - Layout.minimumHeight: root.font.pixelSize + topPadding + bottomPadding - Layout.minimumWidth: Style.dimens.min_button_width - leftPadding - rightPadding - spacing: 0 - z: 1 - - TintableIcon { - id: buttonIcon - - Layout.rightMargin: Constants.text_spacing - source: root.icon.source - sourceSize.height: contentLayout.Layout.minimumHeight - tintColor: d.contentColor - tintEnabled: tintIcon - visible: source != "" - width: height - } - GText { - id: buttonText - - Accessible.ignored: true - Layout.alignment: Qt.AlignHCenter - color: d.contentColor - elide: Text.ElideRight - font: root.font - lineHeight: root.textStyle.lineHeight - maximumLineCount: 1 - text: root.text - visible: text !== "" - - FocusFrame { - marginFactor: 0.7 - scope: root - visible: !root.background - } - } - GSpacer { - Layout.fillWidth: true - visible: buttonIcon.visible - } - } - } - - Accessible.onPressAction: clicked() - onActiveFocusOnTabChanged: if (!activeFocusOnTab) - focus = false - - Item { - id: d - - property color borderColor: color === Style.color.control ? Style.color.control_border : color - property color color: Style.color.control - property color contentColor: root.textStyle === Style.text.button ? Style.color.control_content : root.textStyle.textColor - - states: [ - State { - name: "disabled" - when: !root.enabled || !root.enableButton - - PropertyChanges { - borderColor: Style.color.control_border_disabled - color: Style.color.control_disabled - contentColor: root.textDisabledColor - target: d - } - }, - State { - name: "pressed" - when: root.pressed - - PropertyChanges { - borderColor: Style.color.control_border_pressed - color: Style.color.control_pressed - contentColor: root.textHighlightColor - target: d - } - }, - State { - name: "hover" - when: root.hovered - - PropertyChanges { - borderColor: Style.color.control_border_hover - color: Style.color.control_hover - contentColor: root.textStyle === Style.text.button ? Style.color.control_content_hover : root.textHighlightColor - target: d - } - }, - State { - name: "unchecked" - when: !root.checked && checkable - - PropertyChanges { - borderColor: Style.color.control_border_unchecked - color: Style.color.control_unchecked - contentColor: Style.color.control_content_unchecked - target: d - } - } - ] - } - MouseArea { - id: mouseArea - - anchors.fill: parent - z: 2 - - onPressed: mouse => { - mouse.accepted = !enableButton; - } - } -} diff --git a/resources/qml/Governikus/Global/GCheckBox.qml b/resources/qml/Governikus/Global/GCheckBox.qml deleted file mode 100644 index 96772169e..000000000 --- a/resources/qml/Governikus/Global/GCheckBox.qml +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View - -CheckBox { - id: control - - property alias descriptionItem: descriptionItemLoader.sourceComponent - property alias maximumLineCount: description.maximumLineCount - property alias textStyle: description.textStyle - - padding: 0 - - contentItem: ColumnLayout { - spacing: Constants.text_spacing - - GText { - id: description - - Accessible.ignored: true - elide: Text.ElideRight - leftPadding: control.indicator.implicitWidth + control.spacing - maximumLineCount: 1 - text: control.text - textStyle: enabled ? Style.text.normal : Style.text.normal - } - Loader { - id: descriptionItemLoader - - Layout.fillWidth: true - Layout.leftMargin: description.leftPadding - visible: sourceComponent - } - } - indicator: Rectangle { - border.color: enabled ? Style.color.control : Style.color.control_disabled - border.width: Math.max(plugin.scaleFactor * 4, 1) - color: enabled ? (control.checked ? Style.color.control : Style.color.transparent) : Style.color.control_disabled - implicitHeight: plugin.scaleFactor * 33 - implicitWidth: implicitHeight - radius: Math.max(plugin.scaleFactor * 4, 1) - - TintableIcon { - anchors.fill: parent - anchors.margins: Math.max(plugin.scaleFactor * 4, 1) - fillMode: Image.PreserveAspectFit - source: "qrc:///images/checkbox_indicator.svg" - tintColor: Style.color.control_content - visible: control.checked - } - } - - Accessible.onPressAction: { - toggle(); - toggled(); - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - - onClicked: control.toggle() - } - FocusFrame { - anchors.fill: null - height: indicator.height - 2 * anchors.margins - width: description.x + description.width - 2 * anchors.margins - x: indicator.x + anchors.margins - y: indicator.y + anchors.margins - } -} diff --git a/resources/qml/Governikus/Global/GComboBox.qml b/resources/qml/Governikus/Global/GComboBox.qml deleted file mode 100644 index 48b3bcd55..000000000 --- a/resources/qml/Governikus/Global/GComboBox.qml +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.View -import Governikus.Style -import Governikus.Type.ApplicationModel - -ComboBox { - id: control - - property TextStyle textStyle: Style.text.normal - - Accessible.name: displayText - Accessible.role: Accessible.ComboBox - font.pixelSize: textStyle.textSize - popup.bottomMargin: plugin.safeAreaMargins.bottom - popup.leftMargin: plugin.safeAreaMargins.left - popup.rightMargin: plugin.safeAreaMargins.right - popup.topMargin: plugin.safeAreaMargins.top - spacing: Constants.groupbox_spacing - - background: GPaneBackground { - border.color: control.textStyle.textColor - border.width: Style.dimens.border_width - color: Style.color.transparent - } - contentItem: GText { - elide: Text.ElideRight - leftPadding: Constants.pane_padding - maximumLineCount: 1 - padding: control.spacing - rightPadding: control.spacing - text: control.displayText - textStyle: control.textStyle - } - delegate: ItemDelegate { - highlighted: control.highlightedIndex === index - width: control.width - - background: Rectangle { - color: highlighted ? Style.color.control : Style.color.pane_sublevel - implicitHeight: Style.dimens.list_item_height - implicitWidth: 100 - - GSeparator { - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } - } - } - contentItem: GText { - color: highlighted ? Style.color.control_content_hover : control.textStyle.textColor - elide: Text.ElideRight - text: modelData - textStyle: control.textStyle - } - } - indicator: TintableIcon { - height: control.height * 0.75 - source: down ? "qrc:///images/material_expand_less.svg" : "qrc:///images/material_expand_more.svg" - tintColor: control.textStyle.textColor - width: height - x: Math.round(control.width - width - control.spacing) - y: Math.round(control.topPadding + (control.availableHeight - height) / 2) - } - - FocusFrame { - marginFactor: 1.5 - scope: control - } -} diff --git a/resources/qml/Governikus/Global/GControl.qml b/resources/qml/Governikus/Global/GControl.qml deleted file mode 100644 index ca7e07d52..000000000 --- a/resources/qml/Governikus/Global/GControl.qml +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls - -Control { - implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding) - implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding) -} diff --git a/resources/qml/Governikus/Global/GDropShadow.qml b/resources/qml/Governikus/Global/GDropShadow.qml deleted file mode 100644 index 2c743e5d3..000000000 --- a/resources/qml/Governikus/Global/GDropShadow.qml +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Effects - -MultiEffect { - property real verticalOffset: 7 - - shadowEnabled: true - shadowOpacity: 0.15 - shadowScale: 1.025 - - // Timer is necessary because shadowVerticalOffset does not get updated - // after initialization. Only an external update after the whole UI has - // been loaded leads to the expected result, else the drop shadow will - // be drawn too low. - Timer { - interval: 1 - running: true - - onTriggered: shadowVerticalOffset = Qt.binding(function () { - return verticalOffset; - }) - } -} diff --git a/resources/qml/Governikus/Global/GDropShadow_6.5.qml b/resources/qml/Governikus/Global/GDropShadow_6.5.qml deleted file mode 100644 index b10061e6b..000000000 --- a/resources/qml/Governikus/Global/GDropShadow_6.5.qml +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (c) 2023 Governikus GmbH & Co. KG, Germany -*/ -import QtQuick - -ShaderEffect { - property bool autoPaddingEnabled - property rect paddingRect - property real shadowOpacity - property real verticalOffset -} diff --git a/resources/qml/Governikus/Global/GInformativeButton.qml b/resources/qml/Governikus/Global/GInformativeButton.qml deleted file mode 100644 index f5ba63acd..000000000 --- a/resources/qml/Governikus/Global/GInformativeButton.qml +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Style -import Governikus.View - -GButton { - id: root - - property alias description: subText.text - property real scaleIcon: 1.0 - - Accessible.name: text + ". " + description - Layout.maximumWidth: Number.POSITIVE_INFINITY - horizontalPadding: Constants.component_spacing - verticalPadding: Constants.text_spacing - - contentItem: RowLayout { - readonly property color color: root.pressed ? Style.color.control_content_pressed : root.textStyle.textColor - - spacing: Constants.component_spacing - z: 1 - - TintableIcon { - Layout.preferredHeight: Layout.preferredWidth - Layout.preferredWidth: Style.dimens.icon_size - fillMode: Image.Pad - source: root.icon.source - sourceSize.width: Layout.preferredWidth * scaleIcon - tintColor: contentItem.color - tintEnabled: root.tintIcon - } - Item { - Layout.fillWidth: true - implicitHeight: textColumn.implicitHeight - implicitWidth: textColumn.implicitWidth - - ColumnLayout { - id: textColumn - - anchors.fill: parent - spacing: Constants.text_spacing / 2 - - GText { - Accessible.ignored: true - Layout.alignment: Qt.AlignBottom - color: contentItem.color - elide: Text.ElideRight - font.bold: true - maximumLineCount: 1 - text: root.text - textStyle: root.textStyle - } - GText { - id: subText - - Accessible.ignored: true - Layout.alignment: Qt.AlignTop - color: contentItem.color - elide: Text.ElideRight - maximumLineCount: 2 - textStyle: root.textStyle - } - } - } - } -} diff --git a/resources/qml/Governikus/Global/GPaneBackground.qml b/resources/qml/Governikus/Global/GPaneBackground.qml deleted file mode 100644 index b0b510b41..000000000 --- a/resources/qml/Governikus/Global/GPaneBackground.qml +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Style - -Rectangle { - id: root - - border.color: Style.color.pane_border - border.width: Style.dimens.border_width - color: Style.color.pane - radius: Style.dimens.pane_radius -} diff --git a/resources/qml/Governikus/Global/GRadioButton.qml b/resources/qml/Governikus/Global/GRadioButton.qml deleted file mode 100644 index dc8f264da..000000000 --- a/resources/qml/Governikus/Global/GRadioButton.qml +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View - -RadioButton { - id: root - - readonly property int indicatorHeight: Math.ceil((textStyle.textSize + horizontalPadding) / 2) * 2 - property var textStyle: Style.text.normal - property bool tintIcon: false - - Accessible.name: text - Layout.maximumWidth: contentItem ? contentItem.implicitWidth + leftPadding + rightPadding : -1 - indicator: null - spacing: Constants.groupbox_spacing - - contentItem: RowLayout { - spacing: root.spacing - - Rectangle { - Layout.preferredHeight: root.indicatorHeight - Layout.preferredWidth: root.indicatorHeight - border.color: Style.color.control - border.width: Math.max(plugin.scaleFactor * 3, 1) - radius: height / 2 - - Rectangle { - anchors.alignWhenCentered: false - anchors.centerIn: parent - color: Style.color.control - height: parent.height / 2 - radius: height / 2 - visible: root.checked - width: height - } - } - TintableIcon { - Layout.preferredHeight: sourceSize.height - source: root.icon.source - sourceSize.height: root.indicatorHeight - tintColor: root.textStyle.textColor - tintEnabled: tintIcon - visible: source.toString() !== "" - } - GText { - Accessible.ignored: true - text: root.text - textStyle: root.textStyle - } - } - - FocusFrame { - scope: root - } - MouseArea { - acceptedButtons: Qt.NoButton - anchors.fill: parent - cursorShape: root.checked ? Qt.ArrowCursor : Qt.PointingHandCursor - } -} diff --git a/resources/qml/Governikus/Global/GRepeater.qml b/resources/qml/Governikus/Global/GRepeater.qml deleted file mode 100644 index 57e088444..000000000 --- a/resources/qml/Governikus/Global/GRepeater.qml +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQml -import QtQuick - -Repeater { - id: root - - property real maxItemWidth: 0 - property real tmpWidth: 0 - - onItemAdded: (pIndex, pItem) => { - if (pIndex === 0 || tmpWidth < pItem.implicitWidth) - tmpWidth = pItem.implicitWidth; - if (root.count === pIndex + 1) { - maxItemWidth = tmpWidth; - } - } -} diff --git a/resources/qml/Governikus/Global/GSpacer.qml b/resources/qml/Governikus/Global/GSpacer.qml deleted file mode 100644 index 629577fbb..000000000 --- a/resources/qml/Governikus/Global/GSpacer.qml +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -Item { -} diff --git a/resources/qml/Governikus/Global/GSwitch.qml b/resources/qml/Governikus/Global/GSwitch.qml deleted file mode 100644 index e0a9d7727..000000000 --- a/resources/qml/Governikus/Global/GSwitch.qml +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import Governikus.Style -import Governikus.View - -Switch { - id: control - - property bool overwriteHovered: false - property bool overwritePressed: false - - implicitHeight: indicator.implicitHeight - implicitWidth: indicator.implicitWidth - padding: 0 - - // Empty item since we don't want the text - contentItem: Item { - } - indicator: Rectangle { - border.color: d.borderColor - color: d.controlColor - implicitHeight: implicitWidth / 2 - implicitWidth: Style.dimens.switch_width - radius: height / 2 - - Rectangle { - id: ball - - readonly property int distanceBallBorder: 3 - - anchors.verticalCenter: parent.verticalCenter - color: d.contentColor - height: parent.height - 2 * distanceBallBorder - radius: height / 2 - width: height - x: control.checked ? parent.width - width - distanceBallBorder : distanceBallBorder - - Behavior on x { - NumberAnimation { - duration: 200 - easing.type: Easing.InOutQuad - } - } - } - } - - Accessible.onPressAction: toggle() - - FocusFrame { - radius: height / 2 - } - Item { - id: d - - property color borderColor: Style.color.control_border - property color contentColor: Style.color.control_content - property color controlColor: Style.color.control - - states: [ - State { - name: "disabled" - when: !control.enabled - - PropertyChanges { - borderColor: Style.color.control_border_disabled - contentColor: Style.color.control_content_disabled - controlColor: Style.color.control_disabled - target: d - } - }, - State { - name: "hovered" - when: control.overwriteHovered || control.hovered - - PropertyChanges { - borderColor: Style.color.control_border_hover - contentColor: Style.color.control_content_hover - controlColor: Style.color.control_hover - target: d - } - }, - State { - name: "pressed" - when: control.overwritePressed || control.pressed - - PropertyChanges { - borderColor: Style.color.control_border_pressed - contentColor: Style.color.control_content_pressed - controlColor: Style.color.control_pressed - target: d - } - }, - State { - name: "unchecked" - when: !control.checked - - PropertyChanges { - borderColor: Style.color.control_border_unchecked - contentColor: Style.color.control_content_unchecked - controlColor: Style.color.control_unchecked - target: d - } - } - ] - } -} diff --git a/resources/qml/Governikus/Global/LabeledSwitch.qml b/resources/qml/Governikus/Global/LabeledSwitch.qml deleted file mode 100644 index 821c549ea..000000000 --- a/resources/qml/Governikus/Global/LabeledSwitch.qml +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style - -FocusScope { - property alias checked: entrySwitch.checked - readonly property real contentMargin: Constants.is_desktop ? 0 : Constants.component_spacing - property alias description: descriptionText.text - property bool drawBottomCorners: false - property bool drawTopCorners: false - property alias title: titleText.text - - Accessible.checkable: enabled - Accessible.checked: checked - Accessible.name: title + ". " + description - Accessible.role: Accessible.CheckBox - Layout.fillWidth: true - activeFocusOnTab: true - height: implicitHeight - implicitHeight: contentItem.implicitHeight + 2 * contentMargin - implicitWidth: contentItem.implicitWidth - - Accessible.onPressAction: entrySwitch.toggle() - Accessible.onToggleAction: entrySwitch.toggle() - - RoundedRectangle { - anchors.fill: parent - bottomLeftCorner: parent.drawBottomCorners - bottomRightCorner: parent.drawBottomCorners - color: mouseArea.pressed ? Style.color.pane_active : Style.color.transparent - topLeftCorner: parent.drawTopCorners - topRightCorner: parent.drawTopCorners - - RowLayout { - id: contentItem - - anchors.fill: parent - anchors.leftMargin: contentMargin - anchors.rightMargin: contentMargin - layoutDirection: Constants.is_desktop ? Qt.RightToLeft : Qt.LeftToRight - spacing: Constants.component_spacing - - ColumnLayout { - spacing: Constants.subtext_spacing - - GText { - id: titleText - - Accessible.ignored: true - Layout.maximumWidth: Number.POSITIVE_INFINITY - Layout.preferredHeight: Constants.is_desktop ? Math.max(entrySwitch.implicitHeight, implicitHeight) : -1 - color: entrySwitch.enabled ? (mouseArea.pressed ? Style.color.text_subline_pressed : textStyle.textColor) : Style.color.text_subline_disabled - textStyle: Style.text.subline - } - GText { - id: descriptionText - - Accessible.ignored: true - Layout.maximumWidth: Number.POSITIVE_INFINITY - color: entrySwitch.enabled ? (mouseArea.pressed ? Style.color.text_pressed : textStyle.textColor) : Style.color.text_disabled - visible: text !== "" - } - } - GSwitch { - id: entrySwitch - - Accessible.ignored: true - Layout.alignment: Constants.is_desktop ? Qt.AlignTop : Qt.AlignVCenter - activeFocusOnTab: false - focus: true - overwriteHovered: mouseArea.containsMouse - overwritePressed: mouseArea.pressed - text: titleText.text - } - } - MouseArea { - id: mouseArea - - anchors.fill: parent - hoverEnabled: true - - onClicked: entrySwitch.toggle() - } - } -} diff --git a/resources/qml/Governikus/Global/TintableAnimation.qml b/resources/qml/Governikus/Global/TintableAnimation.qml deleted file mode 100644 index 2fd6f8891..000000000 --- a/resources/qml/Governikus/Global/TintableAnimation.qml +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Style - -Item { - id: root - - property alias asynchronous: image.asynchronous - property bool desaturate: false - property alias fillMode: image.fillMode - property alias paintedHeight: image.paintedHeight - property alias paintedWidth: image.paintedWidth - property alias playAnimation: animation.enabled - property alias source: image.source - property color tintColor: Style.color.text - property bool tintEnabled: true - - implicitHeight: image.implicitHeight - implicitWidth: image.implicitWidth - width: height * implicitWidth / implicitHeight - - AnimatedImage { - id: image - - anchors.fill: parent - fillMode: Image.PreserveAspectFit - layer.enabled: root.tintEnabled && GraphicsInfo.api !== GraphicsInfo.Software - - layer.effect: ShaderEffect { - property color color: root.tintColor - - fragmentShader: root.desaturate ? "qrc:/shader/DesaturateShader.frag" : "qrc:/shader/ColorOverlayShader.frag" - } - Behavior on source { - id: animation - - enabled: false - - SequentialAnimation { - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.InCubic - property: "opacity" - targets: image - to: 0 - } - PropertyAction { - property: "source" - target: image - } - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.OutCubic - property: "opacity" - targets: image - to: 1 - } - } - } - } -} diff --git a/resources/qml/Governikus/Global/TintableIcon.qml b/resources/qml/Governikus/Global/TintableIcon.qml deleted file mode 100644 index a9912175f..000000000 --- a/resources/qml/Governikus/Global/TintableIcon.qml +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Style - -Item { - id: root - - property alias asynchronous: image.asynchronous - property bool desaturate: false - property alias fillMode: image.fillMode - property alias paintedHeight: image.paintedHeight - property alias paintedWidth: image.paintedWidth - property alias playAnimation: animation.enabled - property alias source: image.source - property alias sourceSize: image.sourceSize - property color tintColor: Style.color.text - property bool tintEnabled: true - - implicitHeight: image.implicitHeight - implicitWidth: image.implicitWidth - - Image { - id: image - - anchors.fill: parent - fillMode: Image.PreserveAspectFit - layer.enabled: root.tintEnabled && GraphicsInfo.api !== GraphicsInfo.Software - - layer.effect: ShaderEffect { - property color color: root.tintColor - - fragmentShader: root.desaturate ? "qrc:/shader/DesaturateShader.frag" : "qrc:/shader/ColorOverlayShader.frag" - } - Behavior on source { - id: animation - - enabled: false - - SequentialAnimation { - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.InCubic - property: "opacity" - targets: image - to: 0 - } - PropertyAction { - property: "source" - target: image - } - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.OutCubic - property: "opacity" - targets: image - to: 1 - } - } - } - } -} diff --git a/resources/qml/Governikus/Global/qmldir b/resources/qml/Governikus/Global/qmldir deleted file mode 100644 index 8b20cd24b..000000000 --- a/resources/qml/Governikus/Global/qmldir +++ /dev/null @@ -1,66 +0,0 @@ -module Global - -internal BaseConfirmationPopup BaseConfirmationPopup.qml -internal BrandConstants BrandConstants.qml -internal DeviceConstants DeviceConstants.qml -internal PlatformConstants PlatformConstants.qml - -singleton Constants 1.0 Constants.qml -singleton Utils 1.0 Utils.qml - -ConfirmationPopup 1.0 ConfirmationPopup.qml -Crossed 1.0 Crossed.qml -DecisionView 1.0 DecisionView.qml - -GBusyIndicator 1.0 GBusyIndicator.qml -GButton 1.0 GButton.qml -GInformativeButton 1.0 GInformativeButton.qml -GCheckBox 1.0 GCheckBox.qml -GComboBox 1.0 GComboBox.qml -GConicalGradient 1.0 GConicalGradient.qml -GControl 1.0 GControl.qml -GFileDialog 1.0 GFileDialog.qml -GFlickable 1.0 GFlickable.qml -GFlickableColumnLayout 1.0 GFlickableColumnLayout.qml -GGridView 1.0 GGridView.qml -GListView 1.0 GListView.qml -GPane 1.0 GPane.qml -GPaneBackground 1.0 GPaneBackground.qml -GPaneBackgroundDelegate 1.0 GPaneBackgroundDelegate.qml -GProgressBar 1.0 GProgressBar.qml -GRadioButton 1.0 GRadioButton.qml -GRepeater 1.0 GRepeater.qml -GScrollBar 1.0 GScrollBar.qml -GSeparator 1.0 GSeparator.qml -GSpacer 1.0 GSpacer.qml -GSwitch 1.0 GSwitch.qml -GText 1.0 GText.qml -GTextField 1.0 GTextField.qml -IosBackGestureMouseArea 1.0 IosBackGestureMouseArea.qml -LabeledSwitch 1.0 LabeledSwitch.qml -LabeledText 1.0 LabeledText.qml -ListItem 1.0 ListItem.qml -LocationButton 1.0 LocationButton.qml -MenuItem 1.0 MenuItem.qml -NavigationButton 1.0 NavigationButton.qml -NumberField 1.0 NumberField.qml -PaneTitle 1.0 PaneTitle.qml -ProxyCredentialsPopup 1.0 ProxyCredentialsPopup.qml -RetryCounter 1.0 RetryCounter.qml -RoundedRectangle 1.0 RoundedRectangle.qml -RegExpValidatorCompat 1.0 RegExpValidatorCompat.qml -ScrollGradients 1.0 ScrollGradients.qml -ScrollablePane 1.0 ScrollablePane.qml -SwipeActionDelegate 1.0 SwipeActionDelegate.qml -TabbedPane 1.0 TabbedPane.qml -PkiSwitch 1.0 PkiSwitch.qml -TintableAnimation 1.0 TintableAnimation.qml -TintableIcon 1.0 TintableIcon.qml -TitledSeparator 1.0 TitledSeparator.qml -PrivacyStatement 1.0 PrivacyStatement.qml -Hint 1.0 Hint.qml -MoreInformationLink 1.0 MoreInformationLink.qml -GDropShadow 1.0 GDropShadow.qml -GCollapsible 1.0 GCollapsible.qml -GCollapsibleSubButton 1.0 GCollapsibleSubButton.qml -GOptionsContainer 1.0 GOptionsContainer.qml diff --git a/resources/qml/Governikus/InformationView/+desktop/VersionInformation.qml b/resources/qml/Governikus/InformationView/+desktop/VersionInformation.qml deleted file mode 100644 index ad8dd94d6..000000000 --- a/resources/qml/Governikus/InformationView/+desktop/VersionInformation.qml +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.VersionInformationModel - -Item { - id: baseItem - - implicitHeight: column.implicitHeight - implicitWidth: column.implicitWidth - - GPane { - id: column - - anchors.fill: parent - spacing: Constants.component_spacing - - Repeater { - id: repeater - - model: VersionInformationModel - - delegate: LabeledText { - id: delegate - - Accessible.name: model.label + ": " + model.text - label: model.label - text: model.text - width: baseItem.width - } - } - } - MouseArea { - property int counter: 0 - - anchors.fill: parent - - onClicked: { - counter += 1; - if (counter === 10) { - SettingsModel.developerOptions = !SettingsModel.developerOptions; - ApplicationModel.showFeedback(SettingsModel.developerOptions ? - //: LABEL DESKTOP - qsTr("Developer options activated.") : - //: LABEL DESKTOP - qsTr("Developer options deactivated.")); - counter = 0; - } - } - } -} diff --git a/resources/qml/Governikus/InformationView/ReleaseNotesView.qml b/resources/qml/Governikus/InformationView/ReleaseNotesView.qml deleted file mode 100644 index eb60a096d..000000000 --- a/resources/qml/Governikus/InformationView/ReleaseNotesView.qml +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.View -import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.FormattedTextModel - -GListView { - id: root - - property real maximumContentWidth: Number.POSITIVE_INFINITY - - activeFocusOnTab: true - displayMarginBeginning: Constants.pane_padding - displayMarginEnd: Constants.pane_padding - - delegate: Item { - height: row.implicitHeight - width: root.width - - GPaneBackgroundDelegate { - id: delegate - - anchors.centerIn: parent - anchors.horizontalCenterOffset: -Constants.pane_padding / 2 - count: root.count - idx: index - implicitHeight: row.implicitHeight - implicitWidth: Math.min(root.width - Constants.pane_padding, root.maximumContentWidth) - - RowLayout { - id: row - - readonly property int horizontalPadding: Constants.pane_padding - readonly property alias text: contentText.text - - Accessible.ignored: contentText.text === "" - Accessible.name: ApplicationModel.stripHtmlTags(contentText.text) - Accessible.role: Accessible.StaticText - anchors.fill: parent - implicitHeight: Math.max(prefix.implicitHeight, contentText.implicitHeight) - - GText { - id: prefix - - Accessible.ignored: true - Layout.fillHeight: true - fontSizeMode: Text.Fit - leftPadding: row.horizontalPadding - text: "•" - textStyle: contentText.textStyle - verticalAlignment: Text.AlignTop - visible: lineType === LineType.LISTITEM - } - GText { - id: contentText - - Accessible.ignored: true - Layout.maximumWidth: Number.POSITIVE_INFINITY - bottomPadding: delegate.isLast ? Constants.pane_padding : 0 - font.underline: lineType === LineType.SECTION - leftPadding: prefix.visible ? 0 : row.horizontalPadding - rightPadding: row.horizontalPadding - text: content - textStyle: { - switch (lineType) { - case LineType.HEADER: - return Style.text.title; - case LineType.SECTION: - return Style.text.headline; - case LineType.SUBSECTION: - return Style.text.subline; - default: - return Style.text.normal; - } - } - topPadding: delegate.isFirst ? Constants.pane_padding : 0 - } - } - } - } - highlight: Item { - FocusFrame { - scope: root - } - } - - Keys.onDownPressed: { - do { - root.incrementCurrentIndex(); - } while (currentItem.text === "") - } - Keys.onUpPressed: { - do { - root.decrementCurrentIndex(); - } while (currentItem.text === "") - } - - layer { - enabled: true - - effect: GDropShadow { - } - } -} diff --git a/resources/qml/Governikus/InformationView/qmldir b/resources/qml/Governikus/InformationView/qmldir deleted file mode 100644 index 73919d641..000000000 --- a/resources/qml/Governikus/InformationView/qmldir +++ /dev/null @@ -1,8 +0,0 @@ -module InformationView - - -DiagnosisView 1.0 DiagnosisView.qml -LicenseInformation 1.0 LicenseInformation.qml -ReleaseNotes 1.0 ReleaseNotes.qml -ReleaseNotesView 1.0 ReleaseNotesView.qml -VersionInformation 1.0 VersionInformation.qml diff --git a/resources/qml/Governikus/MainView/+desktop/Tile.qml b/resources/qml/Governikus/MainView/+desktop/Tile.qml deleted file mode 100644 index 32f4bce85..000000000 --- a/resources/qml/Governikus/MainView/+desktop/Tile.qml +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel - -RoundedRectangle { - id: root - - property alias image: image.source - property alias title: text.text - - signal clicked - - Accessible.name: ApplicationModel.stripHtmlTags(title) - Accessible.role: Accessible.Button - borderColor: Style.color.pane_border - color: mouseArea.pressed ? Style.color.control : Style.color.pane - layer.enabled: GraphicsInfo.api !== GraphicsInfo.Software - opacity: SettingsModel.showBetaTesting ? 0.9 : 1.0 - - layer.effect: GDropShadow { - } - - Keys.onSpacePressed: clicked() - - MouseArea { - id: mouseArea - - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - - onClicked: root.clicked() - } - FocusFrame { - } - Column { - spacing: Constants.component_spacing - - anchors { - left: parent.left - margins: 2 * Constants.pane_padding - right: parent.right - top: parent.top - } - TintableIcon { - id: image - - readonly property int imageHeight: Style.dimens.huge_icon_size - - sourceSize.height: imageHeight - tintColor: mouseArea.pressed ? Style.color.mainbutton_content_pressed : Style.color.text_subline - } - GText { - id: text - - color: mouseArea.pressed ? Style.color.mainbutton_content_pressed : Style.color.text_title - horizontalAlignment: Text.AlignLeft - textStyle: Style.text.navigation - width: parent.width - } - } -} diff --git a/resources/qml/Governikus/MainView/qmldir b/resources/qml/Governikus/MainView/qmldir deleted file mode 100644 index 91f4e6323..000000000 --- a/resources/qml/Governikus/MainView/qmldir +++ /dev/null @@ -1,5 +0,0 @@ -module MainView - -internal Tile Tile.qml - -MainView 1.0 MainView.qml diff --git a/resources/qml/Governikus/MoreView/qmldir b/resources/qml/Governikus/MoreView/qmldir deleted file mode 100644 index 00dc94f12..000000000 --- a/resources/qml/Governikus/MoreView/qmldir +++ /dev/null @@ -1,7 +0,0 @@ -module MoreView - -internal MoreViewDiagnosis MoreViewDiagnosis.qml -internal MoreViewGeneral MoreViewGeneral.qml -internal MoreViewMenuItem MoreViewMenuItem.qml - -MoreView 1.0 MoreView.qml diff --git a/resources/qml/Governikus/Navigation/qmldir b/resources/qml/Governikus/Navigation/qmldir deleted file mode 100644 index 6503c13cc..000000000 --- a/resources/qml/Governikus/Navigation/qmldir +++ /dev/null @@ -1,6 +0,0 @@ -module Navigation - -internal NavigationItem NavigationItem.qml -internal NavigationView NavigationView.qml - -Navigation 1.0 Navigation.qml diff --git a/resources/qml/Governikus/PasswordInfoView/+desktop/PasswordInfoView.qml b/resources/qml/Governikus/PasswordInfoView/+desktop/PasswordInfoView.qml deleted file mode 100644 index 9b19c3eaa..000000000 --- a/resources/qml/Governikus/PasswordInfoView/+desktop/PasswordInfoView.qml +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.PinResetInformationModel - -SectionPage { - id: root - - readonly property url buttonLink: infoContent.buttonLink - readonly property string buttonText: infoContent.buttonText - readonly property var contentList: infoContent.contentList - readonly property string hint: infoContent.hint - readonly property string hintButtonText: infoContent.hintButtonText - property var infoContent: PasswordInfoContent { - } - property alias rootEnabled: titleBarAction.rootEnabled - readonly property string title: infoContent.title - - signal abortCurrentWorkflow - signal close - - titleBarAction: TitleBarAction { - id: titleBarAction - - rootEnabled: ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE - showHelp: false - showSettings: false - text: root.title - } - - Keys.onEnterPressed: close() - Keys.onEscapePressed: close() - Keys.onReturnPressed: close() - - GFlickableColumnLayout { - anchors.fill: parent - anchors.margins: Constants.pane_padding - maximumContentWidth: Style.dimens.max_text_width - spacing: Constants.pane_spacing - - Repeater { - model: root.contentList - - delegate: RowLayout { - Layout.alignment: headline ? Qt.AlignHCenter : Qt.AlignLeft - spacing: 2 * Constants.component_spacing - - PasswordInfoImage { - Layout.alignment: Qt.AlignTop - imageType: blockHeaderImageType - scaleFactorGeneral: plugin.scaleFactor - visible: blockHeaderImageType !== PasswordInfoImage.Type.NONE - } - ColumnLayout { - Layout.alignment: Qt.AlignTop - spacing: Constants.groupbox_spacing - - GText { - Layout.alignment: headline ? Qt.AlignHCenter : Qt.AlignLeft - activeFocusOnTab: true - font.bold: true - horizontalAlignment: headline ? Text.AlignHCenter : Text.AlignLeft - text: blockTitle - textStyle: headline ? Style.text.headline : Style.text.subline - visible: text !== "" - - FocusFrame { - } - } - Repeater { - model: paragraphList - - delegate: GText { - Layout.alignment: headline ? Qt.AlignHCenter : Qt.AlignLeft - activeFocusOnTab: true - horizontalAlignment: headline ? Text.AlignHCenter : Text.AlignLeft - text: modelData - - FocusFrame { - } - } - } - } - } - } - GButton { - Layout.alignment: Qt.AlignRight - Layout.topMargin: Constants.component_spacing - icon.source: "qrc:///images/open_website.svg" - text: root.buttonText - visible: text !== "" - - onClicked: Qt.openUrlExternally(root.buttonLink) - } - GSpacer { - Layout.fillHeight: true - } - Hint { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - buttonText: root.hintButtonText - buttonTooltip: PinResetInformationModel.pinResetUrl - text: root.hint - visible: text !== "" - - onClicked: { - abortCurrentWorkflow(); - Qt.openUrlExternally(PinResetInformationModel.pinResetUrl); - } - } - NavigationButton { - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom - buttonType: NavigationButton.Type.Back - - onClicked: root.close() - } - } -} diff --git a/resources/qml/Governikus/PasswordInfoView/PasswordInfoContentBlock.qml b/resources/qml/Governikus/PasswordInfoView/PasswordInfoContentBlock.qml deleted file mode 100644 index f55cf04f9..000000000 --- a/resources/qml/Governikus/PasswordInfoView/PasswordInfoContentBlock.qml +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -QtObject { - property int blockHeaderImageType: PasswordInfoImage.Type.NONE - property string blockTitle - property bool headline: false - property var paragraphList -} diff --git a/resources/qml/Governikus/PasswordInfoView/PasswordInfoData.qml b/resources/qml/Governikus/PasswordInfoView/PasswordInfoData.qml deleted file mode 100644 index 678b2e731..000000000 --- a/resources/qml/Governikus/PasswordInfoView/PasswordInfoData.qml +++ /dev/null @@ -1,402 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Type.PasswordType -import Governikus.Type.PinResetInformationModel -import Governikus.Type.WorkflowModel - -Item { - id: root - - readonly property url buttonLink: infoContent.buttonLink - readonly property string buttonText: infoContent.buttonText - readonly property var contentList: infoContent.contentList - property int contentType - readonly property string hint: infoContent.hint - readonly property string hintButtonText: infoContent.hintButtonText - readonly property PasswordInfoContent infoContent: { - switch (contentType) { - case PasswordInfoContent.Type.PIN: - return pinInfo; - case PasswordInfoContent.Type.SMART_PIN: - return smartPinInfo; - case PasswordInfoContent.Type.CHOOSE_PIN: - return choosePinInfo; - case PasswordInfoContent.Type.CHOOSE_SMART_PIN: - return chooseSmartPinInfo; - case PasswordInfoContent.Type.TRANSPORT_PIN: - return transportPinInfo; - case PasswordInfoContent.Type.PUK: - return pukInfo; - case PasswordInfoContent.Type.CAN: - return canInfo; - case PasswordInfoContent.Type.CAN_ALLOWED: - return canAllowedInfo; - case PasswordInfoContent.Type.CHANGE_PIN: - return changePinInfo; - case PasswordInfoContent.Type.SMART_BLOCKING_CODE: - return smartBlockingCodeInfo; - case PasswordInfoContent.Type.NO_PIN: - return noPin; - case PasswordInfoContent.Type.EMPTY: - return empty; - default: - return pinInfo; - } - } - readonly property string linkText: infoContent.linkText - readonly property string title: infoContent.title - - function fromPasswordType(pPasswordType, pIsCanAllowedMode = false) { - switch (pPasswordType) { - case PasswordType.PIN: - return PasswordInfoContent.Type.PIN; - case PasswordType.SMART_PIN: - return PasswordInfoContent.Type.SMART_PIN; - case PasswordType.CAN: - return pIsCanAllowedMode ? PasswordInfoContent.Type.CAN_ALLOWED : PasswordInfoContent.Type.CAN; - case PasswordType.PUK: - return PasswordInfoContent.Type.PUK; - case PasswordType.NEW_PIN: - return PasswordInfoContent.Type.CHOOSE_PIN; - case PasswordType.NEW_SMART_PIN: - return PasswordInfoContent.Type.CHOOSE_SMART_PIN; - case PasswordType.NEW_PIN_CONFIRMATION: - case PasswordType.NEW_SMART_PIN_CONFIRMATION: - return PasswordInfoContent.Type.EMPTY; - case PasswordType.TRANSPORT_PIN: - return PasswordInfoContent.Type.TRANSPORT_PIN; - case PasswordType.SMART_BLOCKING_CODE: - return PasswordInfoContent.Type.SMART_BLOCKING_CODE; - default: - return PasswordInfoContent.Type.PIN; - } - } - - PasswordInfoContent { - id: empty - - linkText: "" - } - PasswordInfoContent { - id: pinInfo - - //: LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - hint: qsTr("If you have forgotten your card PIN, you can request a new PIN free of charge using the PIN Reset Service.") - hintButtonText: PinResetInformationModel.pinResetActionText - - //: LABEL ALL_PLATFORMS - linkText: qsTr("What is the card PIN?") - //: LABEL ALL_PLATFORMS - title: qsTr("PIN information") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.PIN - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("What is the card PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' - qsTr("The card PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use the eID function with your ID card.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Where can I find the card PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) - qsTr("You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the five-digit Transport PIN. Only when you have set a six-digit PIN of your own choice can you use the eID function and set up a Smart-eID.").arg(Qt.application.name)] - } - ] - } - PasswordInfoContent { - id: smartPinInfo - - //: LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - hint: qsTr("If you have forgotten your Smart-eID PIN, you can renew your Smart-eID and thereby set a new PIN.") - //: LABEL ALL_PLATFORMS - linkText: qsTr("What is the Smart-eID PIN?") - //: LABEL ALL_PLATFORMS - title: qsTr("PIN information") - - contentList: [ - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("What is the Smart-eID PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' - qsTr("The Smart-eID PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Where can I find the Smart-eID PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the Smart-eID PIN?' - qsTr("You have set the Smart-eID PIN while setting up the Smart-eID.")] - } - ] - } - PasswordInfoContent { - id: choosePinInfo - - //: LABEL ALL_PLATFORMS - linkText: qsTr("How do I choose a secure PIN?") - - //: LABEL ALL_PLATFORMS - title: qsTr("PIN information") - - contentList: [ - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("How do I choose a secure PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 1/3 - qsTr("For your six-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither \"123456\", nor your date of birth, nor any other numbers printed on your ID card."), - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 2/3 - qsTr("You can change your six-digit PIN at any time and an unlimited number of times as long as you know your valid PIN."), - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 3/3 - qsTr("Keep your PIN secret and change it if another person becomes aware of it.")] - } - ] - } - PasswordInfoContent { - id: chooseSmartPinInfo - - //: LABEL ALL_PLATFORMS - linkText: qsTr("What is the Smart-eID PIN?") - - //: LABEL ALL_PLATFORMS - title: qsTr("Set up Smart-eID") - - contentList: [ - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("What is the Smart-eID PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' - qsTr("The Smart-eID PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("How do I choose a secure PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 - qsTr("For your six-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither \"123456\", nor your date of birth, nor any other numbers printed on your ID card."), - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 - qsTr("You can change your six-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN."), - //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 3/3 - qsTr("Keep your PIN secret and change it if another person becomes aware of it.")] - } - ] - } - PasswordInfoContent { - id: transportPinInfo - - //: LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. - hint: qsTr("If you do not know either your Transport PIN or your card PIN, you can request a new PIN free of charge using the PIN Reset Service.") - hintButtonText: PinResetInformationModel.pinResetActionText - - //: LABEL ALL_PLATFORMS - linkText: qsTr("What is the Transport PIN?") - //: LABEL ALL_PLATFORMS - title: qsTr("Transport PIN information") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.LETTER - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("What is the Transport PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 1/3 - qsTr("The five-digit Transport PIN was sent to you in the PIN letter by mail after you applied for your ID card."), - //: INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 2/3 - qsTr("If you did not set a self-selected six-digit card PIN when you picked up your ID card, you can do so using the Transport PIN."), - //: INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 3/3 - qsTr("Once you have set a card PIN, the Transport PIN loses its validity.")] - } - ] - } - PasswordInfoContent { - id: pukInfo - - hint: PinResetInformationModel.noPinAndNoPukHint - hintButtonText: PinResetInformationModel.pinResetActionText - - //: LABEL ALL_PLATFORMS - linkText: qsTr("Where do I find the PUK?") - //: LABEL ALL_PLATFORMS - title: qsTr("PUK information") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.LETTER_PUK - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Where do I find the PUK?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' - qsTr("The PUK is a ten-digit number that you can find in the PIN letter that was sent to you by mail after you applied for your ID card.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Why is the PUK required?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Why is the PUK required?' - qsTr("The PUK is required if the card PIN has been entered incorrectly three times in a row. As a result, the card PIN is blocked.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("What is the PUK's purpose?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'What is the PUK's purpose?' - qsTr("By entering the PUK, you unblock the card PIN and have another three chances to enter the correct PIN.")] - } - ] - } - PasswordInfoContent { - id: canInfo - - //: LABEL ALL_PLATFORMS - linkText: qsTr("Why is the CAN required?") - //: LABEL ALL_PLATFORMS - title: qsTr("CAN information") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.CAN - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("When is the card access number (CAN) required?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'When is the card access number (CAN) required?' - qsTr("The card access number (CAN) is required when the card PIN has been entered incorrectly twice.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Why do I have to enter the CAN before a third attempt?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a third attempt?' - qsTr("A third incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that a third incorrect entry can only be made with direct access to your ID card.")] - }, - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Where can I find the CAN?") - paragraphList: [ - //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the CAN?' - qsTr("The CAN is a six-digit number that can be found on the bottom right of the front of the ID card.")] - } - ] - } - PasswordInfoContent { - id: canAllowedInfo - - //: LABEL ALL_PLATFORMS - linkText: qsTr("Why is the CAN required?") - //: LABEL ALL_PLATFORMS - title: qsTr("CAN information") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.CAN - - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("CAN information") - paragraphList: [ - //: INFO ALL_PLATFORMS Description text of CAN-allowed authentication - qsTr("The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a six-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in red).")] - } - ] - } - PasswordInfoContent { - id: changePinInfo - - //: LABEL ALL_PLATFORMS - linkText: qsTr("Learn more about the two types of PIN") - //: LABEL ALL_PLATFORMS - title: qsTr("Types of PIN") - - contentList: [ - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Learn more about the two types of PIN") - headline: true - paragraphList: [ - //: INFO ALL_PLATFORMS Description text explaining the PINs 1/7 - qsTr("Your ID card comes with a five-digit 'Transport PIN' which you need to replace with a six-digit PIN that you choose yourself.")] - }, - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.Type.LETTER - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Five-digit Transport PIN") - paragraphList: [ - //: INFO ALL_PLATFORMS Description text explaining the PINs 2/7 - qsTr("The five-digit Transport PIN was sent to you by mail after you applied for your ID card."), - //: INFO ALL_PLATFORMS Description text explaining the PINs 3/7 - qsTr("The PIN can only be used once. When you set up the eID function, you will replace this five-digit Transport PIN with a six-digit card PIN that you choose yourself.")] - }, - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.Type.PIN - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Six-digit PIN") - paragraphList: WorkflowModel.isSmartSupported ? [ - - //: INFO ALL_PLATFORMS Description text explaining the PINs 4/7 - qsTr("The six-digit card PIN is a number that you choose yourself when you set up the eID function for the first time. It replaces your five-digit Transport PIN."), - //: INFO ALL_PLATFORMS Description text explaining the PINs 5/7 - qsTr("The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time."), - //: INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - qsTr("With this six-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN."), - //: INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 - qsTr("You can change your card PIN and your Smart-eID PIN at any time in %1.").arg(Qt.application.name)] : [ - - //: INFO ALL_PLATFORMS Description text explaining the PINs 4/7 - qsTr("The six-digit card PIN is a number that you choose yourself when you set up the eID function for the first time. It replaces your five-digit Transport PIN."), - //: INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - qsTr("With this six-digit PIN you prove online that the ID card belongs to you. No one can use the eID function without this PIN."), - //: INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 - qsTr("You can change your card PIN at any time in %1.").arg(Qt.application.name)] - } - ] - } - PasswordInfoContent { - id: smartBlockingCodeInfo - - //: LABEL ANDROID IOS - title: qsTr("Smart-eID blocking code") - - contentList: [ - PasswordInfoContentBlock { - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("Smart-eID blocking code") - paragraphList: [ - //: INFO ANDROID IOS Description text of Smart-eID PIN - qsTr("Just like the physical ID card, the Smart-eID stored on your Smartphone can be blocked. This might be required if you ever lose your device."), - //: INFO ANDROID IOS Description text of Smart-eID PIN - qsTr("To revoke an active Smart-eID, a blocking code is required. The blocking code will be displayed after successfully creating the Smart-eID. Furthermore, it is contained in the letter you will receive after creation.")] - } - ] - } - PasswordInfoContent { - id: noPin - - //: LABEL ALL_PLATFORMS - hint: qsTr("You can use the PIN Reset Service to request a new card PIN free of charge.") - hintButtonText: PinResetInformationModel.pinResetActionText - - //: LABEL ALL_PLATFORMS - title: qsTr("No PIN known") - - contentList: [ - PasswordInfoContentBlock { - blockHeaderImageType: PasswordInfoImage.NO_PIN - - //: LABEL ALL_PLATFORMS - blockTitle: qsTr("You do not know your PIN?") - paragraphList: [ - //: INFO ALL_PLATFORMS - qsTr("You have not yet set a six-digit card PIN and cannot find the PIN letter with the Transport PIN?"), - //: INFO ALL_PLATFORMS - qsTr("You set a card PIN when picking up your ID card or later by yourself, but you can no longer remember it?")] - } - ] - } -} diff --git a/resources/qml/Governikus/PasswordInfoView/PasswordInfoImage.qml b/resources/qml/Governikus/PasswordInfoView/PasswordInfoImage.qml deleted file mode 100644 index 630634b1a..000000000 --- a/resources/qml/Governikus/PasswordInfoView/PasswordInfoImage.qml +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style - -Item { - id: root - - enum Type { - NONE, - LETTER, - LETTER_PUK, - CAN, - SMART, - NO_PIN, - PIN - } - - property int imageType: PasswordInfoImage.Type.LETTER - property real scaleFactorGeneral: 0.8 - - height: root.implicitHeight - implicitHeight: infoImageContainer.height - implicitWidth: infoImageContainer.width - visible: infoImage.source.toString() !== "" - width: root.implicitWidth - - Item { - id: infoImageContainer - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - height: infoImage.implicitHeight - width: infoImage.implicitWidth - - TintableIcon { - id: infoImage - - anchors.fill: parent - source: switch (imageType) { - case PasswordInfoImage.Type.CAN: - return "qrc:///images/can.svg"; - case PasswordInfoImage.Type.SMART: - return ""; - case PasswordInfoImage.Type.LETTER_PUK: - return "qrc:///images/puk_%1.svg".arg(Style.currentTheme.name); - case PasswordInfoImage.Type.NO_PIN: - return "qrc:///images/pin_unknown.svg"; - case PasswordInfoImage.Type.PIN: - return "qrc:///images/pin_person.svg"; - default: - return "qrc:///images/transportpin_%1.svg".arg(Style.currentTheme.name); - } - sourceSize.width: 200 * scaleFactorGeneral - tintColor: Style.color.control - tintEnabled: imageType === PasswordInfoImage.Type.NO_PIN || imageType === PasswordInfoImage.Type.CAN || imageType === PasswordInfoImage.Type.PIN - width: parent.width - } - } -} diff --git a/resources/qml/Governikus/PasswordInfoView/qmldir b/resources/qml/Governikus/PasswordInfoView/qmldir deleted file mode 100644 index bfc911355..000000000 --- a/resources/qml/Governikus/PasswordInfoView/qmldir +++ /dev/null @@ -1,8 +0,0 @@ -module PasswordInfoView - -internal PasswordInfoContentBlock PasswordInfoContentBlock.qml -internal PasswordInfoContentParagraph PasswordInfoContentParagraph.qml - -PasswordInfoData 1.0 PasswordInfoData.qml -PasswordInfoContent 1.0 PasswordInfoContent.qml -PasswordInfoView 1.0 PasswordInfoView.qml diff --git a/resources/qml/Governikus/ProgressView/qmldir b/resources/qml/Governikus/ProgressView/qmldir deleted file mode 100644 index 098fb3f1e..000000000 --- a/resources/qml/Governikus/ProgressView/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module ProgressView - -ProgressView 1.0 ProgressView.qml diff --git a/resources/qml/Governikus/RemoteServiceView/qmldir b/resources/qml/Governikus/RemoteServiceView/qmldir deleted file mode 100644 index a17751a56..000000000 --- a/resources/qml/Governikus/RemoteServiceView/qmldir +++ /dev/null @@ -1,13 +0,0 @@ -module RemoteServiceView - -internal DevicesListDelegate DevicesListDelegate.qml -internal PairingCodeInfoView PairingCodeInfoView.qml -internal PairingProcessInfo PairingProcessInfo.qml -internal RemoteServiceController RemoteServiceController.qml -internal RemoteServiceViewRemote RemoteServiceViewRemote.qml -internal RemoteServiceWifiInfo RemoteServiceWifiInfo.qml - -LinkQuality 1.0 LinkQuality.qml -LocalNetworkInfo 1.0 LocalNetworkInfo.qml -RemoteServiceSettings 1.0 RemoteServiceSettings.qml -RemoteServiceView 1.0 RemoteServiceView.qml diff --git a/resources/qml/Governikus/ResultView/+desktop/ResultView.qml b/resources/qml/Governikus/ResultView/+desktop/ResultView.qml deleted file mode 100644 index 1d2f2a2f7..000000000 --- a/resources/qml/Governikus/ResultView/+desktop/ResultView.qml +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import Governikus.Global -import Governikus.TitleBar -import Governikus.Style -import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.LogModel -import Governikus.Type.UiModule - -SectionPage { - id: baseItem - - property alias animatedIcon: animation.source - property alias buttonText: button.text - property alias buttonType: button.buttonType - property alias header: resultHeader.text - property alias hintButtonText: hintItem.buttonText - property alias hintText: hintItem.text - property alias icon: customIcon.source - property alias mailButtonVisible: mailButton.visible - property string popupText - property string popupTitle - property alias text: resultText.text - - signal emailButtonPressed - signal hintClicked - - Keys.onEnterPressed: button.onClicked() - Keys.onEscapePressed: button.onClicked() - Keys.onReturnPressed: button.onClicked() - - GFlickableColumnLayout { - anchors.fill: parent - anchors.margins: Constants.pane_padding - maximumContentWidth: Style.dimens.max_text_width - spacing: Constants.pane_spacing - - TintableAnimation { - id: animation - - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: Style.dimens.header_icon_size - tintEnabled: false - visible: source.toString() !== "" - } - TintableIcon { - id: customIcon - - Layout.alignment: Qt.AlignHCenter - sourceSize.height: Style.dimens.header_icon_size - tintEnabled: false - visible: source.toString() !== "" - } - GSpacer { - Layout.fillHeight: true - } - GText { - id: resultHeader - - Layout.alignment: Qt.AlignHCenter - activeFocusOnTab: true - horizontalAlignment: Text.AlignHCenter - textStyle: Style.text.headline - visible: text !== "" - - FocusFrame { - } - } - GText { - id: resultText - - Layout.alignment: Qt.AlignHCenter - activeFocusOnTab: true - horizontalAlignment: Text.AlignHCenter - visible: text !== "" - - FocusFrame { - } - } - RowLayout { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - spacing: Constants.component_spacing - visible: popupTitle !== "" || popupText !== "" - - GButton { - id: mailButton - - icon.source: "qrc:///images/material_mail.svg" - //: LABEL DESKTOP - text: qsTr("Send email") - tintIcon: true - visible: false - - onClicked: baseItem.emailButtonPressed() - } - GButton { - icon.source: "qrc:/images/desktop/save_icon.svg" - //: LABEL DESKTOP - text: qsTr("Save log") - tintIcon: true - - onClicked: { - LogModel.setLogFile(0); - let filenameSuggestion = LogModel.createLogFileName(LogModel.getCurrentLogFileDate()); - fileDialog.selectFile(filenameSuggestion); - } - - GFileDialog { - id: fileDialog - - defaultSuffix: "log" - //: LABEL DESKTOP - nameFilters: qsTr("Logfiles (*.log)") - - //: LABEL DESKTOP - title: qsTr("Save log") - - onAccepted: LogModel.saveCurrentLogFile(file) - } - } - GButton { - icon.source: "qrc:/images/desktop/info_white.svg" - //: LABEL DESKTOP - text: qsTr("See details") - tintIcon: true - visible: popupTitle !== "" || popupText !== "" - - onClicked: { - let popup = detailedResultPopup.createObject(baseItem, { - "text": popupText, - "title": popupTitle - }); - popup.open(); - } - } - } - GSpacer { - Layout.fillHeight: true - } - Hint { - id: hintItem - - Layout.fillWidth: true - visible: text !== "" - - onClicked: baseItem.hintClicked() - } - NavigationButton { - id: button - - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: height - Layout.preferredWidth: width - activeFocusOnTab: true - visible: buttonType !== NavigationButton.Type.Forward - - onClicked: baseItem.nextView(UiModule.DEFAULT) - } - GButton { - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: height - Layout.preferredWidth: width - activeFocusOnTab: true - text: qsTr("OK") - visible: !button.visible - - onClicked: baseItem.nextView(UiModule.DEFAULT) - } - } - Component { - id: detailedResultPopup - - ConfirmationPopup { - style: ConfirmationPopup.PopupStyle.OkButton - } - } -} diff --git a/resources/qml/Governikus/ResultView/qmldir b/resources/qml/Governikus/ResultView/qmldir deleted file mode 100644 index b03a3f931..000000000 --- a/resources/qml/Governikus/ResultView/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module ResultView - -ResultErrorView 1.0 ResultErrorView.qml -ResultView 1.0 ResultView.qml diff --git a/resources/qml/Governikus/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml b/resources/qml/Governikus/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml deleted file mode 100644 index fe2944a8f..000000000 --- a/resources/qml/Governikus/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.AuthView -import Governikus.Global -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.Type.ReaderPlugIn -import Governikus.Type.SettingsModel -import Governikus.Type.SelfAuthModel -import Governikus.Type.UiModule - -FlickableSectionPage { - id: root - - property bool autoInsertCard: false - property bool hideTechnologySwitch: false - property var initialPlugIn - - signal back - - spacing: Constants.pane_spacing - //: LABEL ANDROID IOS - title: qsTr("Identify") - - navigationAction: NavigationAction { - action: NavigationAction.Action.Back - - onClicked: root.back() - } - - Component { - id: authView - - AuthView { - autoInsertCard: root.autoInsertCard - hideTechnologySwitch: root.hideTechnologySwitch - initialPlugIn: root.initialPlugIn - - Component.onCompleted: SelfAuthModel.startWorkflow(false) - onShowChangePinView: { - show(UiModule.PINMANAGEMENT); - popAll(); - } - onWorkflowFinished: popAll() - } - } - TintableIcon { - Layout.alignment: Qt.AlignHCenter - source: "qrc:///images/mydata.svg" - sourceSize.height: Style.dimens.large_icon_size - tintColor: Style.color.control - - PkiSwitch { - anchors.fill: parent - //: LABEL ANDROID IOS - functionName: qsTr("Self-authentication") - } - } - GText { - Layout.alignment: Qt.AlignHCenter - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Constants.pane_padding - horizontalAlignment: Text.AlignHCenter - //: LABEL ANDROID IOS - text: qsTr("Use the button \"See my personal data\" to start the self-authentication service of the manufacturer of the %1 to display the data stored in the chip of your ID card.").arg(Qt.application.name) - width: parent.width - wrapMode: Text.WordWrap - } - PrivacyStatement { - Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Constants.pane_padding - horizontalAlignment: Text.AlignHCenter - } - GSeparator { - Layout.fillWidth: true - } - GridLayout { - Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Layout.leftMargin - columnSpacing: rowSpacing - columns: 2 - rowSpacing: Constants.groupbox_spacing - rows: 2 - - GText { - Layout.columnSpan: 2 - //: LABEL ANDROID IOS - text: qsTr("Hint") - textStyle: Style.text.subline - } - Image { - fillMode: Image.PreserveAspectFit - source: "qrc:///images/siteWithLogo_%1.svg".arg(Style.currentTheme.name) - sourceSize.height: Style.dimens.large_icon_size - } - GText { - //: LABEL ANDROID IOS A11y description of eID logo displayed next to the logo itself - Accessible.name: qsTr("You can use your ID card anywhere you find the logo of the electronic identification function.") - - //: LABEL ANDROID IOS - text: qsTr("You can use your ID card anywhere you see this logo.") - } - } - GSeparator { - Layout.fillWidth: true - } - GButton { - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Constants.component_spacing - buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.text_warning : Style.color.control - icon.source: "qrc:///images/identify.svg" - //: LABEL ANDROID IOS - text: qsTr("See my personal data") - tintIcon: true - - onClicked: push(authView) - } -} diff --git a/resources/qml/Governikus/SelfAuthenticationView/qmldir b/resources/qml/Governikus/SelfAuthenticationView/qmldir deleted file mode 100644 index 27343877f..000000000 --- a/resources/qml/Governikus/SelfAuthenticationView/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module SelfAuthenticationView - -SelfAuthenticationView 1.0 SelfAuthenticationView.qml diff --git a/resources/qml/Governikus/SettingsView/+desktop/DebugSettings.qml b/resources/qml/Governikus/SettingsView/+desktop/DebugSettings.qml deleted file mode 100644 index ef35d68e8..000000000 --- a/resources/qml/Governikus/SettingsView/+desktop/DebugSettings.qml +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick.Layouts -import Governikus.Global -import Governikus.View -import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.LogModel -import Governikus.Type.SettingsModel - -ColumnLayout { - spacing: Constants.component_spacing - - GPane { - Layout.fillWidth: true - spacing: Constants.component_spacing - - //: LABEL DESKTOP - title: qsTr("Create dummy entries") - - RowLayout { - GButton { - //: LABEL DESKTOP - text: qsTr("Logfile") - - onClicked: { - LogModel.saveDummyLogFile(); - ApplicationModel.showFeedback("Created new logfile."); - } - } - } - LabeledSwitch { - checked: SettingsModel.showBetaTesting - //: LABEL DESKTOP - title: qsTr("Show beta testing image") - - onCheckedChanged: SettingsModel.showBetaTesting = checked - } - LabeledSwitch { - checked: SettingsModel.enableCanAllowed - //: LABEL DESKTOP - title: qsTr("Support CAN allowed mode") - - onCheckedChanged: SettingsModel.enableCanAllowed = checked - } - LabeledSwitch { - checked: SettingsModel.skipRightsOnCanAllowed - enabled: SettingsModel.enableCanAllowed - //: LABEL DESKTOP - title: qsTr("Skip rights page in CAN allowed mode") - - onCheckedChanged: SettingsModel.skipRightsOnCanAllowed = checked - } - GButton { - //: LABEL DESKTOP - text: qsTr("Reset hideable dialogs") - - onClicked: { - SettingsModel.resetHideableDialogs(); - } - } - GText { - activeFocusOnTab: true - //: LABEL DESKTOP - text: qsTr("Show Transport PIN reminder, store feedback and close reminder dialogs.") - - FocusFrame { - } - } - } -} diff --git a/resources/qml/Governikus/SettingsView/+desktop/GeneralSettings.qml b/resources/qml/Governikus/SettingsView/+desktop/GeneralSettings.qml deleted file mode 100644 index e0d9550e9..000000000 --- a/resources/qml/Governikus/SettingsView/+desktop/GeneralSettings.qml +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.View -import Governikus.Type.SettingsModel - -ColumnLayout { - spacing: Constants.component_spacing - - GPane { - Layout.fillWidth: true - spacing: Constants.component_spacing - //: LABEL DESKTOP - title: qsTr("Language selection") - - LanguageButtons { - columns: 4 - } - } - GPane { - Layout.fillWidth: true - spacing: Constants.component_spacing - //: LABEL DESKTOP - title: qsTr("Appearance") - - DarkModeButtons { - } - LabeledSwitch { - checked: SettingsModel.useSystemFont - - //: LABEL DESKTOP - description: qsTr("Toggling will restart the %1").arg(Qt.application.name) - //: LABEL DESKTOP - title: qsTr("Use the system font") - - onCheckedChanged: SettingsModel.useSystemFont = checked - } - } - GPane { - Layout.fillWidth: true - spacing: Constants.component_spacing - //: LABEL DESKTOP - title: qsTr("Behavior") - - LabeledSwitch { - checked: SettingsModel.autoStartApp - enabled: !SettingsModel.autoStartSetByAdmin && SettingsModel.autoStartAvailable - title: Qt.platform.os === "osx" ? - //: LABEL MACOS Text for auto-start option - qsTr("Auto-start %1 after boot and add to menu bar").arg(Qt.application.name) : - //: LABEL WINDOWS Text for auto-start option - qsTr("Auto-start %1 after boot and add a tray icon").arg(Qt.application.name) - - onCheckedChanged: SettingsModel.autoStartApp = checked - } - LabeledSwitch { - checked: SettingsModel.autoCloseWindowAfterAuthentication - - //: LABEL DESKTOP - title: qsTr("Close %1 after authentication").arg(Qt.application.name) - - onCheckedChanged: SettingsModel.autoCloseWindowAfterAuthentication = checked - } - LabeledSwitch { - checked: SettingsModel.showInAppNotifications - - //: LABEL DESKTOP Only visible when the user activates the developer mode in the settings. - description: SettingsModel.developerMode ? qsTr("Using the developer mode forces the notifications to be enabled.") : "" - enabled: !SettingsModel.developerMode - - //: LABEL DESKTOP - title: qsTr("Show notifications inside of %1").arg(Qt.application.name) - - onCheckedChanged: SettingsModel.showInAppNotifications = checked - } - } - GPane { - Layout.fillWidth: true - spacing: Constants.component_spacing - //: LABEL DESKTOP - title: qsTr("Network") - visible: SettingsModel.customProxyAttributesPresent - - LabeledSwitch { - checked: SettingsModel.useCustomProxy - - //: LABEL DESKTOP - title: qsTr("Use the proxy (%1) specified during the installation.").arg(SettingsModel.customProxyUrl) - - onCheckedChanged: SettingsModel.useCustomProxy = checked - } - } -} diff --git a/resources/qml/Governikus/SettingsView/+mobile/SettingsView.qml b/resources/qml/Governikus/SettingsView/+mobile/SettingsView.qml deleted file mode 100644 index f0b3896bf..000000000 --- a/resources/qml/Governikus/SettingsView/+mobile/SettingsView.qml +++ /dev/null @@ -1,470 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import Governikus.Global -import Governikus.Style -import Governikus.TitleBar -import Governikus.View -import Governikus.RemoteServiceView -import Governikus.SmartView -import Governikus.Type.SettingsModel -import Governikus.Type.ApplicationModel -import Governikus.Type.RemoteServiceModel -import Governikus.Type.LogModel -import Governikus.Type.ModeOption -import Governikus.Type.WorkflowModel -import Governikus.Type.SmartModel - -FlickableSectionPage { - id: baseItem - - function platformId(pName) { - return "mobile," + pName.replace(" ", "").toLowerCase(); - } - - //: LABEL ANDROID IOS - title: qsTr("Settings") - - ColumnLayout { - Layout.fillWidth: true - spacing: Constants.component_spacing - - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("General") - - GCollapsible { - id: languageCollapsible - - contentBottomMargin: 0 - contentSpacing: 0 - contentTopMargin: 0 - drawTopCorners: true - selectionIcon: "qrc:///images/location_flag_%1.svg".arg(SettingsModel.language) - selectionTitle: { - switch (SettingsModel.language) { - case "de": - return "Deutsch"; - case "ru": - return "Русский"; - case "uk": - return "Українська"; - default: - return "English"; - } - } - //: LABEL ANDROID IOS - title: qsTr("Change language") - width: parent.width - - GRepeater { - id: repeater - - delegate: GCollapsibleSubButton { - Accessible.description: model.a11yDescription - Accessible.name: model.a11yName - Layout.fillWidth: true - image: model.image - title: model.text - - onClicked: { - SettingsModel.language = model.language; - languageCollapsible.expanded = false; - } - } - model: LanguageButtonData { - } - } - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - GCollapsible { - id: appearanceCollapsible - - contentBottomMargin: 0 - contentSpacing: 0 - contentTopMargin: 0 - selectionIcon: modeButtons.selectedIconPath - selectionTitle: modeButtons.selectedText - tintIcon: true - //: LABEL ANDROID IOS - title: qsTr("Appearance") - width: parent.width - - DarkModeButtons { - id: modeButtons - - width: parent.width - - onButtonClicked: appearanceCollapsible.expanded = false - } - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - //: LABEL ANDROID IOS - description: qsTr("Toggling will restart the %1").arg(Qt.application.name) - drawBottomCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Use system font") - width: parent.width - - Component.onCompleted: { - checked = SettingsModel.useSystemFont; - } - onCheckedChanged: { - if (checked !== SettingsModel.useSystemFont) { - SettingsModel.useSystemFont = checked; - plugin.doRefresh(); - } - } - } - } - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("Smartphone as card reader") - - GCollapsible { - alwaysReserveSelectionTitleHight: true - contentBottomMargin: 0 - contentTopMargin: 0 - drawTopCorners: true - selectionTitle: expanded ? "" : SettingsModel.serverName - //: LABEL ANDROID IOS - title: qsTr("Device name") - width: parent.width - - GTextField { - id: serverName - - function saveInput() { - focus = false; - SettingsModel.serverName = text; - } - - Layout.fillWidth: true - Layout.margins: Constants.component_spacing - maximumLength: Constants.maximumDeviceNameLength - text: SettingsModel.serverName - - onAccepted: saveInput() - onFocusChanged: if (!focus) - saveInput() - } - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - checked: SettingsModel.pinPadMode - - //: LABEL ANDROID IOS - title: qsTr("Enter PIN on this device") - width: parent.width - - onCheckedChanged: SettingsModel.pinPadMode = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - checked: SettingsModel.showAccessRights - enabled: SettingsModel.pinPadMode - - //: LABEL ANDROID IOS - title: qsTr("Show requested rights on this device as well") - width: parent.width - - onCheckedChanged: SettingsModel.showAccessRights = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - MenuItem { - //: LABEL ANDROID IOS - description: qsTr("Add and remove devices") - drawBottomCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Manage pairings") - width: parent.width - - onClicked: push(remoteServiceSettings) - - Component { - id: remoteServiceSettings - - RemoteServiceSettings { - Component.onCompleted: RemoteServiceModel.detectRemoteDevices = true - Component.onDestruction: RemoteServiceModel.detectRemoteDevices = false - } - } - } - } - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("Security and privacy") - - LabeledSwitch { - checked: SettingsModel.shuffleScreenKeyboard - drawTopCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Randomize the order of the on screen keypad buttons") - width: parent.width - - onCheckedChanged: SettingsModel.shuffleScreenKeyboard = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - checked: !SettingsModel.visualPrivacy - //: LABEL ANDROID IOS - description: qsTr("Visually highlight key presses on screen keypad") - drawBottomCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Keypad animations") - width: parent.width - - onCheckedChanged: SettingsModel.visualPrivacy = !checked - } - } - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("Smart-eID") - visible: WorkflowModel.isSmartSupported - - MenuItem { - //: LABEL ANDROID IOS - description: qsTr("Reset Smart-eID data on your device") - //: LABEL ANDROID IOS - title: qsTr("Reset Smart-eID") - width: parent.width - - onClicked: push(smartDeleteView) - - Component { - id: smartDeleteView - - SmartResetView { - } - } - } - } - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("On-site reading") - visible: SettingsModel.advancedSettings - - LabeledSwitch { - checked: SettingsModel.enableCanAllowed - drawTopCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Support CAN allowed mode for on-site reading") - width: parent.width - - onCheckedChanged: SettingsModel.enableCanAllowed = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - checked: SettingsModel.skipRightsOnCanAllowed - drawBottomCorners: true - enabled: SettingsModel.enableCanAllowed - - //: LABEL ANDROID IOS - title: qsTr("Skip rights page") - width: parent.width - - onCheckedChanged: SettingsModel.skipRightsOnCanAllowed = checked - } - } - GOptionsContainer { - Layout.fillWidth: true - //: LABEL ANDROID IOS - title: qsTr("Developer options") - visible: SettingsModel.advancedSettings - - LabeledSwitch { - id: testUriSwitch - - checked: SettingsModel.useSelfauthenticationTestUri - //: LABEL ANDROID IOS - description: qsTr("Allow test sample card usage") - drawTopCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Testmode for the self-authentication") - width: parent.width - - onCheckedChanged: SettingsModel.useSelfauthenticationTestUri = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - LabeledSwitch { - checked: SettingsModel.enableSimulator - //: LABEL ANDROID IOS - description: qsTr("Simulate a test sample card in authentications") - drawBottomCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Internal card simulator") - width: parent.width - - onCheckedChanged: SettingsModel.enableSimulator = checked - } - } - GOptionsContainer { - Layout.fillWidth: true - - //: LABEL ANDROID IOS - title: qsTr("Debug options") - visible: plugin.debugBuild - - LabeledSwitch { - checked: SettingsModel.developerMode - //: LABEL ANDROID IOS - description: qsTr("Use a more tolerant mode") - drawTopCorners: true - - //: LABEL ANDROID IOS - title: qsTr("Developer mode") - width: parent.width - - onCheckedChanged: SettingsModel.developerMode = checked - } - GSeparator { - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing - anchors.right: parent.right - anchors.rightMargin: Constants.component_spacing - } - MenuItem { - //: LABEL ANDROID IOS - description: qsTr("Show Transport PIN reminder, store feedback and close reminder dialogs.") - drawBottomCorners: true - icon: "qrc:///images/material_refresh.svg" - //: LABEL ANDROID IOS - title: qsTr("Reset hideable dialogs") - width: parent.width - - onClicked: { - SettingsModel.resetHideableDialogs(); - } - } - } - GOptionsContainer { - Layout.fillWidth: true - - //: LABEL ANDROID IOS - title: qsTr("Layout style") - visible: plugin.debugBuild - - Column { - padding: Constants.pane_padding - width: parent.width - - GRadioButton { - checked: plugin.platformStyle === baseItem.platformId(text) - text: "iOS" - - onCheckedChanged: if (checked) { - plugin.applyPlatformStyle(baseItem.platformId(text)); - } - } - GRadioButton { - checked: plugin.platformStyle === baseItem.platformId(text) - text: "Android" - - onCheckedChanged: if (checked) { - plugin.applyPlatformStyle(baseItem.platformId(text)); - } - } - } - } - GOptionsContainer { - Layout.fillWidth: true - - //: LABEL ANDROID IOS - title: qsTr("Create dummy entries") - visible: plugin.debugBuild - - ColumnLayout { - spacing: Constants.component_spacing - width: parent.width - - GButton { - Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Constants.pane_padding - Layout.topMargin: Constants.pane_padding - - //: LABEL ALL_PLATFORMS - text: qsTr("New Logfile") - - onClicked: { - LogModel.saveDummyLogFile(); - ApplicationModel.showFeedback("Created new logfile."); - } - } - GButton { - Layout.bottomMargin: Constants.pane_padding - Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Constants.pane_padding - - //: LABEL ALL_PLATFORMS - text: qsTr("15 days old Logfile") - - onClicked: { - let date = new Date(); - date.setDate(new Date().getDate() - 15); - LogModel.saveDummyLogFile(date); - ApplicationModel.showFeedback("Created old logfile."); - } - } - } - } - } -} diff --git a/resources/qml/Governikus/SettingsView/qmldir b/resources/qml/Governikus/SettingsView/qmldir deleted file mode 100644 index d81631a29..000000000 --- a/resources/qml/Governikus/SettingsView/qmldir +++ /dev/null @@ -1,17 +0,0 @@ -module SettingsView - -internal CardReaderDelegate CardReaderDelegate.qml -internal ConnectSacView ConnectSacView.qml -internal DebugSettings DebugSettings.qml -internal DeveloperSettings DeveloperSettings.qml -internal GeneralSettings GeneralSettings.qml -internal RemoteReaderDelegate RemoteReaderDelegate.qml -internal ScreenOrientationSelectionPopup ScreenOrientationSelectionPopup.qml -internal SecurityAndPrivacySettings SecurityAndPrivacySettings.qml - -CardReaderView 1.0 CardReaderView.qml -DarkModeButtons 1.0 DarkModeButtons.qml -LanguageButtons 1.0 LanguageButtons.qml -RemoteReaderView 1.0 RemoteReaderView.qml -SettingsView 1.0 SettingsView.qml -TabbedReaderView 1.0 TabbedReaderView.qml diff --git a/resources/qml/Governikus/SetupAssistantView/qmldir b/resources/qml/Governikus/SetupAssistantView/qmldir deleted file mode 100644 index 337820c89..000000000 --- a/resources/qml/Governikus/SetupAssistantView/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module SetupAssistantView - -SetupAutostartView 1.0 SetupAutostartView.qml diff --git a/resources/qml/Governikus/SmartView/qmldir b/resources/qml/Governikus/SmartView/qmldir deleted file mode 100644 index 5a1328108..000000000 --- a/resources/qml/Governikus/SmartView/qmldir +++ /dev/null @@ -1,17 +0,0 @@ -module SmartView - -internal CheckSmartResultView CheckSmartResultView.qml -internal PersonalizationController PersonalizationController.qml -internal PersonalizationLegalInformationView PersonalizationLegalInformationView.qml -internal PersonalizationProgressView PersonalizationProgressView.qml -internal PersonalizationResultView PersonalizationResultView.qml -internal SmartCardView SmartCardView.qml -internal SmartDeleteBaseView SmartDeleteBaseView.qml -internal SmartMainView SmartMainView.qml -internal SmartSettingsView SmartSettingsView.qml -internal SmartSetupStartView SmartSetupStartView.qml -internal SmartUpdateStartView SmartUpdateStartView.qml - -SmartView 1.0 SmartView.qml -SmartResetView 1.0 SmartResetView.qml -SmartDeleteView 1.0 SmartDeleteView.qml diff --git a/resources/qml/Governikus/Style/+desktop/HighContrastColors.qml b/resources/qml/Governikus/Style/+desktop/HighContrastColors.qml deleted file mode 100644 index f51a7c912..000000000 --- a/resources/qml/Governikus/Style/+desktop/HighContrastColors.qml +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -Colors { - readonly property color background: palette.base - readonly property color border: palette.text - readonly property color control: palette.button - readonly property color control_border: palette.text - readonly property color control_border_disabled: disabledPalette.text - readonly property color control_border_hover: palette.text - readonly property color control_border_pressed: palette.text - readonly property color control_border_unchecked: palette.text - readonly property color control_content: palette.text - readonly property color control_content_disabled: disabledPalette.text - readonly property color control_content_hover: palette.text - readonly property color control_content_pressed: palette.text - readonly property color control_content_unchecked: palette.text - readonly property color control_disabled: disabledPalette.button - readonly property color control_hover: palette.button - readonly property color control_pressed: palette.button - readonly property color control_unchecked: palette.button - readonly property var disabledPalette: SystemPalette { - colorGroup: SystemPalette.Disabled - } - readonly property color fail: "#ff0000" - readonly property color focus_indicator: text - readonly property color mainbutton_content_pressed: palette.text - readonly property var palette: SystemPalette { - colorGroup: SystemPalette.Active - } - readonly property color pane: background - readonly property color pane_active: background - readonly property color pane_border: palette.text - readonly property color pane_sublevel: background - readonly property color success: "#00ff00" - readonly property color text: palette.text - readonly property color text_disabled: disabledPalette.text - readonly property color text_headline: palette.text - readonly property color text_pressed: palette.text - readonly property color text_subline: palette.text - readonly property color text_subline_disabled: disabledPalette.text - readonly property color text_subline_pressed: palette.text - readonly property color text_title: palette.text - readonly property color text_warning: "#ff0000" -} diff --git a/resources/qml/Governikus/Style/+desktop/PlatformDimensions.qml b/resources/qml/Governikus/Style/+desktop/PlatformDimensions.qml deleted file mode 100644 index e3000872c..000000000 --- a/resources/qml/Governikus/Style/+desktop/PlatformDimensions.qml +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQml -import Governikus.Type.SettingsModel - -QtObject { - readonly property real border_width: Math.max(plugin.scaleFactor * 2, 1) - readonly property real control_radius: plugin.scaleFactor * 26 - readonly property real header_icon_size: plugin.scaleFactor * 200 - readonly property real huge_icon_size: plugin.scaleFactor * 125 - readonly property real icon_size: plugin.scaleFactor * 48 - readonly property bool isLongLanguage: SettingsModel.language === "uk" || SettingsModel.language === "ru" - readonly property real large_icon_size: plugin.scaleFactor * 72 - readonly property real lineHeight: plugin.scaleFactor * 40 - readonly property real lineHeight_button: plugin.scaleFactor * 27 - readonly property real lineHeight_headline: plugin.scaleFactor * 47 - readonly property real lineHeight_navigation: plugin.scaleFactor * 63 - readonly property real lineHeight_subline: plugin.scaleFactor * 42 - readonly property real lineHeight_title: plugin.scaleFactor * 70 - readonly property real list_item_height: plugin.scaleFactor * 64 - readonly property real max_text_width: plugin.scaleFactor * (isLongLanguage ? 1250 : 1000) - readonly property real medium_icon_size: plugin.scaleFactor * 64 - readonly property real min_button_width: plugin.scaleFactor * 200 - readonly property real pane_radius: plugin.scaleFactor * 34 - readonly property real popup_border: Math.max(plugin.scaleFactor * 2, 1) - readonly property real progress_bar_border: separator_size_large - readonly property real progress_bar_height: plugin.scaleFactor * 48 - readonly property real scrollbar_padding_horizontal: plugin.scaleFactor * 5 - readonly property real scrollbar_padding_vertical: plugin.scaleFactor * 0 - readonly property real scrollbar_width: plugin.scaleFactor * 10 - readonly property real separator_size: Math.max(plugin.scaleFactor * 2, 1) - readonly property real separator_size_large: Math.max(plugin.scaleFactor * 4, 1) - readonly property real small_icon_size: plugin.scaleFactor * 32 - readonly property real status_icon_medium: plugin.scaleFactor * 200 - readonly property real status_icon_small: plugin.scaleFactor * 100 - readonly property real switch_width: plugin.scaleFactor * 97 - readonly property real text: plugin.scaleFactor * 27 - readonly property real text_headline: plugin.scaleFactor * 40 - readonly property real text_navigation: plugin.scaleFactor * 50 - readonly property real text_subline: plugin.scaleFactor * 30 - readonly property real text_title: plugin.scaleFactor * 60 - readonly property real titlebar_padding: plugin.scaleFactor * 20 - readonly property real titlepane_radius: plugin.scaleFactor * 50 -} diff --git a/resources/qml/Governikus/Style/+mobile/+android/BrandDimensions.qml b/resources/qml/Governikus/Style/+mobile/+android/BrandDimensions.qml deleted file mode 100644 index d0c0d9dab..000000000 --- a/resources/qml/Governikus/Style/+mobile/+android/BrandDimensions.qml +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global - -QtObject { - readonly property real text: 15 * plugin.fontScaleFactor - readonly property real text_headline: 26 * plugin.fontScaleFactor - readonly property real text_navigation: 12 * plugin.fontScaleFactor - readonly property real text_subline: 18 * plugin.fontScaleFactor - readonly property real text_title: 30 * plugin.fontScaleFactor -} diff --git a/resources/qml/Governikus/Style/+mobile/+ios/BrandDimensions.qml b/resources/qml/Governikus/Style/+mobile/+ios/BrandDimensions.qml deleted file mode 100644 index 2735cee61..000000000 --- a/resources/qml/Governikus/Style/+mobile/+ios/BrandDimensions.qml +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Window -import Governikus.Global - -QtObject { - // If this font size changes, it has to be changed in UIPlugInQml, too. - readonly property real text: scaleText(15) * plugin.fontScaleFactor - readonly property real text_headline: scaleText(26) * plugin.fontScaleFactor - readonly property real text_navigation: scaleText(12) * plugin.fontScaleFactor - readonly property real text_subline: scaleText(18) * plugin.fontScaleFactor - readonly property real text_title: scaleText(30) * plugin.fontScaleFactor - - // Scale the text on small devices like the iPhone SE - function scaleText(value) { - let w = Screen.width; - if (w > 415) { - return value; - } - return value * w / 415; - } -} diff --git a/resources/qml/Governikus/Style/+mobile/HighContrastColors.qml b/resources/qml/Governikus/Style/+mobile/HighContrastColors.qml deleted file mode 100644 index b785a2b26..000000000 --- a/resources/qml/Governikus/Style/+mobile/HighContrastColors.qml +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -Colors { -} diff --git a/resources/qml/Governikus/Style/Colors.qml b/resources/qml/Governikus/Style/Colors.qml deleted file mode 100644 index 9231eebc8..000000000 --- a/resources/qml/Governikus/Style/Colors.qml +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -QtObject { - readonly property color background: "#ffffff" - readonly property color border: "#bbbbbb" - readonly property color card_eid: "#0077b6" - readonly property color card_reader: "#444445" - readonly property color card_smart: "#327509" - readonly property color control: "#0077b6" - readonly property color control_border: "#0077b6" - readonly property color control_border_disabled: "#bcc0c1" - readonly property color control_border_hover: "#80cdec" - readonly property color control_border_pressed: "#0077b6" - readonly property color control_border_unchecked: "#576164" - readonly property color control_content: "#ffffff" - readonly property color control_content_disabled: "#ffffff" - readonly property color control_content_hover: "#ffffff" - readonly property color control_content_pressed: "#0077b6" - readonly property color control_content_unchecked: "#576164" - readonly property color control_disabled: "#bcc0c1" - readonly property color control_hover: "#80cdec" - readonly property color control_pressed: "#ffffff" - readonly property color control_unchecked: "#ffffff" - readonly property color fail: "#db6a00" - readonly property color focus_indicator: "#242424" - readonly property color mainbutton_content_pressed: "#ffffff" - readonly property color pane: "#ffffff" - readonly property color pane_active: "#0077b6" - readonly property color pane_border: software_renderer ? border : transparent - readonly property color pane_sublevel: "#f2f3f4" - readonly property color pane_title: "#f2f3f4" - property bool software_renderer: false - readonly property color success: "#3e8401" - readonly property color text: "#576164" - readonly property color text_disabled: "#bcc0c1" - readonly property color text_headline: "#576164" - readonly property color text_navigation: "#ffffff" - readonly property color text_navigation_unchecked: "#576164" - readonly property color text_pressed: "#ffffff" - readonly property color text_subline: "#0077b6" - readonly property color text_subline_disabled: "#80cdec" - readonly property color text_subline_pressed: "#ffffff" - readonly property color text_title: "#004b76" - readonly property color text_warning: "#eb0000" - readonly property color transparent: "transparent" -} diff --git a/resources/qml/Governikus/Style/DarkModeColors.qml b/resources/qml/Governikus/Style/DarkModeColors.qml deleted file mode 100644 index 3827c2269..000000000 --- a/resources/qml/Governikus/Style/DarkModeColors.qml +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -QtObject { - readonly property color background: "#232323" - readonly property color border: "#ffffff" - readonly property color card_eid: "#0077b6" - readonly property color card_reader: "#444445" - readonly property color card_smart: "#327509" - readonly property color control: "#0098eb" - readonly property color control_border: "#0098eb" - readonly property color control_border_disabled: "#798183" - readonly property color control_border_hover: "#80cdec" - readonly property color control_border_pressed: "#0098eb" - readonly property color control_border_unchecked: "#ffffff" - readonly property color control_content: "#ffffff" - readonly property color control_content_disabled: "#798183" - readonly property color control_content_hover: "#ffffff" - readonly property color control_content_pressed: "#0098eb" - readonly property color control_content_unchecked: "#ffffff" - readonly property color control_disabled: "#303030" - readonly property color control_hover: "#80cdec" - readonly property color control_pressed: "#ffffff" - readonly property color control_unchecked: "#232323" - readonly property color fail: "#ff9b29" - readonly property color focus_indicator: "#0098eb" - readonly property color mainbutton_content_pressed: "#ffffff" - readonly property color pane: "#303030" - readonly property color pane_active: "#0098eb" - readonly property color pane_border: software_renderer ? border : transparent - readonly property color pane_sublevel: "#576164" - readonly property color pane_title: "#576164" - property bool software_renderer: false - readonly property color success: "#5fcb01" - readonly property color text: "#ffffff" - readonly property color text_disabled: "#bcc0c1" - readonly property color text_headline: "#ffffff" - readonly property color text_navigation: "#232323" - readonly property color text_navigation_unchecked: "#80cdec" - readonly property color text_pressed: "#000000" - readonly property color text_subline: "#80cdec" - readonly property color text_subline_disabled: "#798183" - readonly property color text_subline_pressed: "#000000" - readonly property color text_title: "#80cdec" - readonly property color text_warning: "#eb0000" - readonly property color transparent: "transparent" -} diff --git a/resources/qml/Governikus/Style/TextStyle.qml b/resources/qml/Governikus/Style/TextStyle.qml deleted file mode 100644 index 48f50d930..000000000 --- a/resources/qml/Governikus/Style/TextStyle.qml +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -QtObject { - property real lineHeight: Style.dimens.lineHeight - property color textColor: Style.color.text - property real textSize: Style.dimens.text -} diff --git a/resources/qml/Governikus/Style/TextStyles.qml b/resources/qml/Governikus/Style/TextStyles.qml deleted file mode 100644 index c226a407f..000000000 --- a/resources/qml/Governikus/Style/TextStyles.qml +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -QtObject { - readonly property var button: TextStyle { - lineHeight: Style.dimens.lineHeight_button - textColor: Style.color.control_content - } - readonly property var headline: TextStyle { - lineHeight: Style.dimens.lineHeight_headline - textColor: Style.color.text_headline - textSize: Style.dimens.text_headline - } - readonly property var link: TextStyle { - textColor: Style.color.text_subline - } - readonly property var navigation: TextStyle { - lineHeight: Style.dimens.lineHeight_navigation - textColor: Style.color.text_title - textSize: Style.dimens.text_navigation - } - readonly property var normal: TextStyle { - } - readonly property var normal_warning: TextStyle { - textColor: Style.color.text_warning - } - readonly property var subline: TextStyle { - lineHeight: Style.dimens.lineHeight_subline - textColor: Style.color.text_subline - textSize: Style.dimens.text_subline - } - readonly property var title: TextStyle { - lineHeight: Style.dimens.lineHeight_title - textColor: Style.color.text_title - textSize: Style.dimens.text_title - } -} diff --git a/resources/qml/Governikus/Style/qmldir b/resources/qml/Governikus/Style/qmldir deleted file mode 100644 index a47404b33..000000000 --- a/resources/qml/Governikus/Style/qmldir +++ /dev/null @@ -1,13 +0,0 @@ -module Style - -internal BrandDimensions BrandDimensions.qml -internal Colors Colors.qml -internal DarkModeColors DarkModeColors.qml -internal Dimensions Dimensions.qml -internal HighContrastColors HighContrastColors.qml -internal PlatformDimensions PlatformDimensions.qml -internal TextStyles TextStyles.qml - -singleton Style 1.0 Style.qml - -TextStyle 1.0 TextStyle.qml diff --git a/resources/qml/Governikus/TechnologyInfo/+mobile/TechnologySwitch.qml b/resources/qml/Governikus/TechnologyInfo/+mobile/TechnologySwitch.qml deleted file mode 100644 index 7c8bccf84..000000000 --- a/resources/qml/Governikus/TechnologyInfo/+mobile/TechnologySwitch.qml +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style -import Governikus.Type.ReaderPlugIn - -GFlickableColumnLayout { - id: baseItem - - property bool flowVertically: false - readonly property int maxItemHeight: Math.max(nfc.implicitHeight, smart.implicitHeight, remote.implicitHeight, sim.implicitHeight) - readonly property int maxItemWidth: Math.max(nfc.implicitWidth, smart.implicitWidth, remote.implicitWidth, sim.implicitWidth) - property int selectedTechnology - property var supportedTechnologies - - signal requestPluginType(int pReaderPlugInType) - - clip: true - implicitHeight: maxItemHeight + 2 * Constants.pane_padding - implicitWidth: maxItemWidth + 2 * Constants.pane_padding - leftMargin: 0 - rightMargin: 0 - - GSpacer { - Layout.fillHeight: true - visible: flowVertically - } - GridLayout { - id: switcher - - readonly property int columnCount: 1 + (baseItem.width - maxItemWidth) / (maxItemWidth + columnSpacing) - - Layout.alignment: Qt.AlignCenter - columnSpacing: Constants.component_spacing * 2 - columns: flowVertically ? 1 : columnCount - rowSpacing: Constants.component_spacing - - GButton { - id: nfc - - checkable: !checked - checked: selectedTechnology === ReaderPlugIn.NFC - icon.source: "qrc:///images/mobile/icon_nfc.svg" - //: LABEL ANDROID IOS - text: qsTr("NFC") - tintIcon: true - visible: supportedTechnologies.includes(ReaderPlugIn.NFC) - - onClicked: baseItem.requestPluginType(ReaderPlugIn.NFC) - } - GButton { - id: smart - - checkable: !checked - checked: selectedTechnology === ReaderPlugIn.SMART - icon.source: "qrc:///images/mobile/icon_smart.svg" - //: LABEL ANDROID IOS - text: qsTr("SMART") - tintIcon: true - visible: supportedTechnologies.includes(ReaderPlugIn.SMART) - - onClicked: baseItem.requestPluginType(ReaderPlugIn.SMART) - } - GButton { - id: remote - - checkable: !checked - checked: selectedTechnology === ReaderPlugIn.REMOTE_IFD - icon.source: "qrc:///images/mobile/icon_remote.svg" - //: LABEL ANDROID IOS - text: qsTr("WiFi") - tintIcon: true - visible: supportedTechnologies.includes(ReaderPlugIn.REMOTE_IFD) - - onClicked: baseItem.requestPluginType(ReaderPlugIn.REMOTE_IFD) - } - GButton { - id: sim - - checkable: !checked - checked: selectedTechnology === ReaderPlugIn.SIMULATOR - icon.source: "qrc:///images/mobile/icon_simulator.svg" - //: LABEL ANDROID IOS - text: qsTr("SIM") - tintIcon: true - visible: supportedTechnologies.includes(ReaderPlugIn.SIMULATOR) - - onClicked: baseItem.requestPluginType(ReaderPlugIn.SIMULATOR) - } - } - GSpacer { - Layout.fillHeight: true - visible: flowVertically - } -} diff --git a/resources/qml/Governikus/TechnologyInfo/qmldir b/resources/qml/Governikus/TechnologyInfo/qmldir deleted file mode 100644 index 87243218e..000000000 --- a/resources/qml/Governikus/TechnologyInfo/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module TechnologyInfo - -TechnologyInfo 1.0 TechnologyInfo.qml -TechnologySwitch 1.0 TechnologySwitch.qml diff --git a/resources/qml/Governikus/TitleBar/+mobile/TitleBarAction.qml b/resources/qml/Governikus/TitleBar/+mobile/TitleBarAction.qml deleted file mode 100644 index fd27ac70f..000000000 --- a/resources/qml/Governikus/TitleBar/+mobile/TitleBarAction.qml +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtQuick.Layouts -import Governikus.Global -import Governikus.Style - -Item { - id: baseItem - - property alias icon: imageItem.source - property alias iconTintColor: imageItem.tintColor - property alias text: textItem.text - - signal clicked - - Accessible.focusable: true - Accessible.ignored: imageItem.source == "" && textItem.text === "" - Accessible.name: text - Accessible.role: Accessible.Button - implicitHeight: contentLayout.implicitHeight - implicitWidth: contentLayout.implicitWidth - - Accessible.onPressAction: clicked() - - RowLayout { - id: contentLayout - - anchors.fill: parent - spacing: 0 - - TintableIcon { - id: imageItem - - Layout.preferredHeight: Layout.preferredWidth - implicitWidth: Style.dimens.small_icon_size - playAnimation: true - sourceSize.width: width - tintColor: textItem.color - visible: imageItem.source != "" - } - GText { - id: textItem - - Accessible.ignored: true - color: Style.color.text - elide: Text.ElideRight - maximumLineCount: 1 - textStyle: Style.text.navigation - visible: textItem.text !== "" - wrapMode: Text.NoWrap - - Behavior on text { - SequentialAnimation { - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.InCubic - property: "opacity" - target: textItem - to: 0 - } - PropertyAction { - property: "text" - target: textItem - } - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.OutCubic - property: "opacity" - target: textItem - to: 1 - } - } - } - - onVisibleChanged: { - if (visible) { - fadeIn.start(); - } else { - fadeOut.start(); - } - } - } - PropertyAnimation { - id: fadeOut - - duration: Constants.animation_duration - easing.type: Easing.InCubic - property: "opacity" - target: textItem - to: 0 - } - PropertyAnimation { - id: fadeIn - - duration: Constants.animation_duration - easing.type: Easing.OutCubic - property: "opacity" - target: textItem - to: 1 - } - } - MouseArea { - id: mouseArea - - anchors.fill: parent - - onClicked: baseItem.clicked() - } -} diff --git a/resources/qml/Governikus/TitleBar/qmldir b/resources/qml/Governikus/TitleBar/qmldir deleted file mode 100644 index 1943f9ae3..000000000 --- a/resources/qml/Governikus/TitleBar/qmldir +++ /dev/null @@ -1,11 +0,0 @@ -module TitleBar - -internal BackCloseAction BackCloseAction.qml -internal TitleBarNavigation TitleBarNavigation.qml -internal TitlePane TitlePane.qml - -NavigationAction 1.0 NavigationAction.qml -Notifications 1.0 Notifications.qml -TitleBar 1.0 TitleBar.qml -TitleBarAction 1.0 TitleBarAction.qml -TitleBarButton 1.0 TitleBarButton.qml diff --git a/resources/qml/Governikus/UpdateView/qmldir b/resources/qml/Governikus/UpdateView/qmldir deleted file mode 100644 index bf29ac45f..000000000 --- a/resources/qml/Governikus/UpdateView/qmldir +++ /dev/null @@ -1,7 +0,0 @@ -module UpdateView - -internal UpdateViewButtonRow UpdateViewButtonRow.qml -internal UpdateViewInformation UpdateViewInformation.qml - -UpdateView 1.0 UpdateView.qml - diff --git a/resources/qml/Governikus/View/+desktop/FramedImage.qml b/resources/qml/Governikus/View/+desktop/FramedImage.qml deleted file mode 100644 index 3e373967c..000000000 --- a/resources/qml/Governikus/View/+desktop/FramedImage.qml +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style - -Item { - id: baseItem - - property bool circularFrame: true - property alias source: image.source - property alias tintColor: image.tintColor - - Rectangle { - id: frame - - anchors.centerIn: parent - anchors.fill: parent - border.color: baseItem.tintColor - border.width: height / 20 - color: Style.color.transparent - radius: circularFrame ? width / 2 : 0 - } - TintableIcon { - id: image - - anchors.fill: frame - anchors.margins: frame.border.width * 2 - sourceSize.height: frame.height - sourceSize.width: frame.width - } -} diff --git a/resources/qml/Governikus/View/+mobile/FocusFrame.qml b/resources/qml/Governikus/View/+mobile/FocusFrame.qml deleted file mode 100644 index 2880ef244..000000000 --- a/resources/qml/Governikus/View/+mobile/FocusFrame.qml +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick - -Item { - property color borderColor - property Item framee - property real marginFactor - property real radius - property Item scope - - anchors.fill: framee -} diff --git a/resources/qml/Governikus/View/qmldir b/resources/qml/Governikus/View/qmldir deleted file mode 100644 index 65a39547b..000000000 --- a/resources/qml/Governikus/View/qmldir +++ /dev/null @@ -1,12 +0,0 @@ -module View - -internal BaseController BaseController.qml - -ContentArea 1.0 ContentArea.qml -Controller 1.0 Controller.qml -FlickableSectionPage 1.0 FlickableSectionPage.qml -SectionPage 1.0 SectionPage.qml -TabBarView 1.0 TabBarView.qml -FocusFrame 1.0 FocusFrame.qml -FocusPoint 1.0 FocusPoint.qml -FramedImage 1.0 FramedImage.qml diff --git a/resources/qml/Governikus/WhiteListClient/qmldir b/resources/qml/Governikus/WhiteListClient/qmldir deleted file mode 100644 index d9bcf4f82..000000000 --- a/resources/qml/Governikus/WhiteListClient/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module WhiteListClient - -WhiteListSurveyView 1.0 WhiteListSurveyView.qml diff --git a/resources/qml/Governikus/Workflow/+mobile/CardReader.qml b/resources/qml/Governikus/Workflow/+mobile/CardReader.qml deleted file mode 100644 index 90fd106a4..000000000 --- a/resources/qml/Governikus/Workflow/+mobile/CardReader.qml +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Style -import Governikus.Type.ApplicationModel - -Item { - id: baseItem - - property bool cardAnimation: true - property bool pinFieldAnimation: true - - width: height * 3 / 7 - - Timer { - id: onTimer - - property int index - - interval: 1500 - running: pinFieldAnimation || cardAnimation - triggeredOnStart: true - - onTriggered: { - onTimer.triggeredOnStart = false; - if (pinFieldAnimation) { - onTimer.index = ApplicationModel.randomInt(0, 8); - repeater.itemAt(onTimer.index).state = "on"; - } - if (cardAnimation) { - card.state = "out"; - } - offTimer.restart(); - } - } - Timer { - id: offTimer - - interval: 500 - - onTriggered: { - if (onTimer.index != undefined) { - repeater.itemAt(onTimer.index).state = "off"; - } - card.state = "in"; - onTimer.restart(); - } - } - Rectangle { - id: reader - - anchors.bottom: parent.bottom - color: Style.color.card_reader - height: parent.height * 5 / 7 - radius: height * 0.05 - width: parent.width - - Rectangle { - id: slot - - anchors.left: parent.left - anchors.leftMargin: parent.width * 0.2 - anchors.right: parent.right - anchors.rightMargin: parent.width * 0.2 - anchors.top: parent.top - anchors.topMargin: parent.height * 0.05 - color: Constants.white - height: reader.height * 0.05 - radius: 10 - } - Rectangle { - id: card - - anchors.horizontalCenter: parent.horizontalCenter - color: Style.color.control - height: baseItem.height * 1.5 / 7 - radius: height * 0.05 - width: baseItem.width * 0.5 - - states: [ - State { - name: "out" - - AnchorChanges { - anchors.bottom: reader.top - target: card - } - }, - State { - name: "in" - - AnchorChanges { - anchors.bottom: slot.verticalCenter - target: card - } - } - ] - transitions: [ - Transition { - AnchorAnimation { - duration: 500 - } - } - ] - - onVisibleChanged: y = reader.mapFromItem(baseItem, baseItem.x, card.y).y - - Rectangle { - id: cardStripe1 - - anchors.left: parent.left - anchors.leftMargin: parent.width * 0.1 - anchors.right: parent.right - anchors.rightMargin: parent.width * 0.1 - anchors.top: parent.top - anchors.topMargin: parent.height * 0.1 - color: Constants.white - height: parent.height * 0.1 - radius: 10 - } - Rectangle { - id: cardStripe2 - - anchors.left: parent.left - anchors.leftMargin: parent.width * 0.1 - anchors.right: parent.right - anchors.rightMargin: parent.width * 0.1 - anchors.top: cardStripe1.top - anchors.topMargin: parent.height * 0.2 - color: Constants.white - height: parent.height * 0.1 - radius: cardStripe1.radius - } - MouseArea { - anchors.fill: parent - - onClicked: card.state = card.state === "out" ? "in" : "out" - } - } - Rectangle { - id: display - - readonly property int margin: parent.width * 0.1 - - anchors.bottom: pinGrid.top - anchors.left: parent.left - anchors.margins: margin - anchors.right: parent.right - color: Constants.white - height: reader.height * 0.2 - radius: height * 0.2 - } - Grid { - id: pinGrid - - anchors.bottom: reader.bottom - anchors.left: parent.left - anchors.margins: display.margin - anchors.right: parent.right - columns: 3 - height: width - spacing: anchors.margins - - Repeater { - id: repeater - - model: 9 - - Item { - id: pinButton - - readonly property int _size: (reader.width - 4 * pinGrid.spacing) / 3 - property alias state: pinButtonCircle.state - - height: width - width: _size - - Rectangle { - id: pinButtonCircle - - anchors.centerIn: parent - height: width - radius: width * 0.5 - state: "off" - width: pinButton._size - - Behavior on color { - ColorAnimation { - duration: 250 - } - } - states: [ - State { - name: "off" - - PropertyChanges { - color: Constants.white - target: pinButtonCircle - } - PropertyChanges { - target: pinButtonCircle - width: pinButton._size - } - }, - State { - name: "on" - - PropertyChanges { - color: Constants.blue - target: pinButtonCircle - } - PropertyChanges { - target: pinButtonCircle - width: pinButton._size + pinButton._size * 0.3 - } - } - ] - Behavior on width { - NumberAnimation { - duration: 1000 - easing.type: Easing.OutElastic - } - } - - MouseArea { - anchors.fill: parent - - onClicked: pinButton.state = pinButton.state === "off" ? "on" : "off" - } - } - } - } - } - } -} diff --git a/resources/qml/Governikus/Workflow/+mobile/WorkflowInfoList.qml b/resources/qml/Governikus/Workflow/+mobile/WorkflowInfoList.qml deleted file mode 100644 index a53f7d773..000000000 --- a/resources/qml/Governikus/Workflow/+mobile/WorkflowInfoList.qml +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import Governikus.Global -import Governikus.Workflow -import Governikus.ResultView -import Governikus.Style -import Governikus.Type.ReaderPlugIn - -Item { - id: baseItem - - property alias autoInsertCard: smartWorkflow.autoInsertCard - readonly property bool contentIsScrolled: nfcWorkflow.visible && !nfcWorkflow.atYBeginning || smartWorkflow.visible && !smartWorkflow.atYBeginning || remoteWorkflow.visible && !remoteWorkflow.atYBeginning || simulatorWorkflow.visible && !simulatorWorkflow.atYBeginning - required property var workflowModel - - NfcWorkflow { - id: nfcWorkflow - - anchors.fill: parent - visible: baseItem.workflowModel.readerPlugInType === ReaderPlugIn.NFC - - onStartScanIfNecessary: baseItem.workflowModel.startScanExplicitly() - } - SmartWorkflow { - id: smartWorkflow - - anchors.fill: parent - visible: baseItem.workflowModel.readerPlugInType === ReaderPlugIn.SMART - workflowModel: baseItem.workflowModel - } - RemoteWorkflow { - id: remoteWorkflow - - anchors.fill: parent - visible: baseItem.workflowModel.readerPlugInType === ReaderPlugIn.REMOTE_IFD || baseItem.workflowModel.readerPlugInType === ReaderPlugIn.PCSC - - onDeviceUnpaired: function (pDeviceName) { - push(deviceUnpairedView, { - "deviceName": pDeviceName - }); - } - - Component { - id: deviceUnpairedView - - ResultView { - property string deviceName - - icon: "qrc:///images/workflow_error_no_sak_%1.svg".arg(Style.currentTheme.name) - //: INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. - text: qsTr("The device \"%1\" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader.").arg(deviceName) - title: workflowTitle - - onCancelClicked: pop() - onContinueClicked: pop() - } - } - } - SimulatorWorkflow { - id: simulatorWorkflow - - anchors.fill: parent - visible: baseItem.workflowModel.readerPlugInType === ReaderPlugIn.SIMULATOR - workflowModel: baseItem.workflowModel - } -} diff --git a/resources/qml/Governikus/Workflow/qmldir b/resources/qml/Governikus/Workflow/qmldir deleted file mode 100644 index 94eb63bac..000000000 --- a/resources/qml/Governikus/Workflow/qmldir +++ /dev/null @@ -1,16 +0,0 @@ -module Workflow - -internal CardReader CardReader.qml -internal NfcProgressIndicator NfcProgressIndicator.qml -internal ProgressCircle ProgressCircle.qml -internal RemoteProgressIndicator RemoteProgressIndicator.qml -internal RemoteWorkflow RemoteWorkflow.qml -internal SmartProgressIndicator SmartProgressIndicator.qml -internal WorkflowInfoList WorkflowInfoList.qml -internal TextCircle TextCircle.qml - -GeneralWorkflow 1.0 GeneralWorkflow.qml -NfcWorkflow 1.0 NfcWorkflow.qml -SimulatorWorkflow 1.0 SimulatorWorkflow.qml -SmartWorkflow 1.0 SmartWorkflow.qml -Workflow 1.0 Workflow.qml diff --git a/resources/shader/ColorOverlayShader.frag b/resources/shader/ColorOverlayShader.frag index 3788d920f..de2203c31 100644 --- a/resources/shader/ColorOverlayShader.frag +++ b/resources/shader/ColorOverlayShader.frag @@ -1,9 +1,14 @@ -varying highp vec2 qt_TexCoord0; -uniform lowp sampler2D source; -uniform highp float qt_Opacity; -uniform highp vec4 color; - -void main() { - highp vec4 pixelColor = texture2D(source, qt_TexCoord0); - gl_FragColor = vec4(mix(pixelColor.rgb/max(pixelColor.a, 0.00390625), color.rgb/max(color.a, 0.00390625), color.a) * pixelColor.a, pixelColor.a) * qt_Opacity; +#version 440 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source; +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + vec4 color; +} ubuf; +void main() +{ + vec4 pixelColor = texture(source, qt_TexCoord0); + fragColor = vec4(mix(pixelColor.rgb/max(pixelColor.a, 0.00390625), ubuf.color.rgb/max(ubuf.color.a, 0.00390625), ubuf.color.a) * pixelColor.a, pixelColor.a) * ubuf.qt_Opacity; } diff --git a/resources/shader/ConicalGradientShader.frag b/resources/shader/ConicalGradientShader.frag index 3d58096bb..df7821c85 100644 --- a/resources/shader/ConicalGradientShader.frag +++ b/resources/shader/ConicalGradientShader.frag @@ -1,14 +1,19 @@ -varying mediump vec2 qt_TexCoord0; -uniform lowp sampler2D source; -uniform lowp sampler2D gradientSource; -uniform highp float qt_Opacity; -uniform highp float startAngle; -uniform highp vec2 center; - -void main() { - lowp float maskAlpha = texture2D(source, qt_TexCoord0).a; - const highp float PI = 3.14159265; - const highp float PIx2inv = 0.1591549; - highp float a = (atan((center.y - qt_TexCoord0.t), (center.x - qt_TexCoord0.s)) + PI - startAngle) * PIx2inv; - gl_FragColor = texture2D(gradientSource, vec2(0.0, fract(a))) * maskAlpha * qt_Opacity; -} \ No newline at end of file +#version 440 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source; +layout(binding = 2) uniform sampler2D gradientSource; +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + float startAngle; + vec2 center; +} ubuf; +void main() +{ + float maskAlpha = texture(source, qt_TexCoord0).a; + const float PI = 3.14159265; + const float PIx2inv = 0.1591549; + float a = (atan((ubuf.center.y - qt_TexCoord0.t), (ubuf.center.x - qt_TexCoord0.s)) + PI - ubuf.startAngle) * PIx2inv; + fragColor = texture(gradientSource, vec2(0.0, fract(a))) * maskAlpha * ubuf.qt_Opacity; +} diff --git a/resources/shader/DesaturateShader.frag b/resources/shader/DesaturateShader.frag index 1dc3495a1..dd7d49d70 100644 --- a/resources/shader/DesaturateShader.frag +++ b/resources/shader/DesaturateShader.frag @@ -1,9 +1,14 @@ -varying highp vec2 qt_TexCoord0; -uniform lowp sampler2D source; -uniform highp float qt_Opacity; - -void main() { - highp vec4 pixelColor = texture2D(source, qt_TexCoord0); - highp float bw = dot(pixelColor.xyz, vec3(0.344, 0.5, 0.156)); - gl_FragColor = vec4(bw, bw, bw, pixelColor.a) * qt_Opacity; +#version 440 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source; +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; +} ubuf; +void main() +{ + vec4 pixelColor = texture(source, qt_TexCoord0); + float bw = dot(pixelColor.xyz, vec3(0.344, 0.5, 0.156)); + fragColor = vec4(bw, bw, bw, pixelColor.a) * ubuf.qt_Opacity; } diff --git a/resources/shader/qt6/ColorOverlayShader.frag b/resources/shader/qt6/ColorOverlayShader.frag deleted file mode 100644 index de2203c31..000000000 --- a/resources/shader/qt6/ColorOverlayShader.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 440 -layout(location = 0) in vec2 qt_TexCoord0; -layout(location = 0) out vec4 fragColor; -layout(binding = 1) uniform sampler2D source; -layout(std140, binding = 0) uniform buf { - mat4 qt_Matrix; - float qt_Opacity; - vec4 color; -} ubuf; -void main() -{ - vec4 pixelColor = texture(source, qt_TexCoord0); - fragColor = vec4(mix(pixelColor.rgb/max(pixelColor.a, 0.00390625), ubuf.color.rgb/max(ubuf.color.a, 0.00390625), ubuf.color.a) * pixelColor.a, pixelColor.a) * ubuf.qt_Opacity; -} diff --git a/resources/shader/qt6/ConicalGradientShader.frag b/resources/shader/qt6/ConicalGradientShader.frag deleted file mode 100644 index df7821c85..000000000 --- a/resources/shader/qt6/ConicalGradientShader.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 440 -layout(location = 0) in vec2 qt_TexCoord0; -layout(location = 0) out vec4 fragColor; -layout(binding = 1) uniform sampler2D source; -layout(binding = 2) uniform sampler2D gradientSource; -layout(std140, binding = 0) uniform buf { - mat4 qt_Matrix; - float qt_Opacity; - float startAngle; - vec2 center; -} ubuf; -void main() -{ - float maskAlpha = texture(source, qt_TexCoord0).a; - const float PI = 3.14159265; - const float PIx2inv = 0.1591549; - float a = (atan((ubuf.center.y - qt_TexCoord0.t), (ubuf.center.x - qt_TexCoord0.s)) + PI - ubuf.startAngle) * PIx2inv; - fragColor = texture(gradientSource, vec2(0.0, fract(a))) * maskAlpha * ubuf.qt_Opacity; -} diff --git a/resources/shader/qt6/DesaturateShader.frag b/resources/shader/qt6/DesaturateShader.frag deleted file mode 100644 index dd7d49d70..000000000 --- a/resources/shader/qt6/DesaturateShader.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 440 -layout(location = 0) in vec2 qt_TexCoord0; -layout(location = 0) out vec4 fragColor; -layout(binding = 1) uniform sampler2D source; -layout(std140, binding = 0) uniform buf { - mat4 qt_Matrix; - float qt_Opacity; -} ubuf; -void main() -{ - vec4 pixelColor = texture(source, qt_TexCoord0); - float bw = dot(pixelColor.xyz, vec3(0.344, 0.5, 0.156)); - fragColor = vec4(bw, bw, bw, pixelColor.a) * ubuf.qt_Opacity; -} diff --git a/resources/translations/ausweisapp2_de.ts b/resources/translations/ausweisapp_de.ts similarity index 80% rename from resources/translations/ausweisapp2_de.ts rename to resources/translations/ausweisapp_de.ts index 275298374..da7a33d66 100644 --- a/resources/translations/ausweisapp2_de.ts +++ b/resources/translations/ausweisapp_de.ts @@ -4,8 +4,14 @@ DvcsAttributes - revision - 56dc58807a8c + 828ae9a4549a + revision + 828ae9a4549a + + + 2.2.0 + version + 2.2.0 @@ -26,6 +32,88 @@ Es wurden Netzwerkprobleme erkannt. Die Verbindung wird weiterhin für 30 Sekunden versucht. + + App + + The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. + Das Programm steht weiterhin in der Menüleiste zur Verfügung. Klicken Sie auf das Symbol der %1, um die Anwendung wieder zu öffnen. + + + The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. + Das Programm steht weiterhin im Infobereich zur Verfügung. Klicken Sie auf das Symbol der %1, um die Anwendung wieder zu öffnen. + + + Another application uses %1 + INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. + Eine andere Anwendung verwendet %1 + + + The user interface of the %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. + Die Benutzeroberfläche der %1 wird geschlossen. + + + Do not show this dialog again. + LABEL DESKTOP + Diesen Hinweis nicht mehr anzeigen. + + + The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. + INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. + Die %1 wird beendet und steht nicht länger für eine Authentisierung zur Verfügung. Sie müssen die %1 erneut starten, um sich gegenüber Dienstanbietern auszuweisen. + + + The %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. + Die %1 wird beendet. + + + This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. + Hiermit wird der aktuelle Vorgang abgebrochen und die Benutzeroberfläche der %1 geschlossen. Sie können den Vorgang jederzeit erneut starten. + + + This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. + INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. + Hierdurch wird der aktuelle Vorgang abgebrochen und die %1 beendet. Sie müssen die %1 erneut starten, um den Vorgang neuzustarten. + + + Abort operation + INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active + Vorgang abbrechen + + + Failed to retrieve update information. + INFO DESKTOP Message that the update data is invalid and can't be used. + Das Herunterladen der Aktualisierungsinformationen ist fehlgeschlagen. + + + An update is available (version %1). + INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. + Eine Aktualisierung ist verfügbar (Version %1). + + + Developer Mode: Enabled! + LABEL DESKTOP + Entwicklermodus: Aktiviert! + + + Disable + LABEL DESKTOP Global button to disable developer mode. + Deaktivieren + + + Detached log viewer + Protokollbetrachter + + + To close the app, press the back button 2 times. + INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). + Zum Schließen erneut "Zurück" drücken. + + AuthController @@ -64,9 +152,9 @@ Bitte beachten Sie die Anzeige Ihres Kartenlesers. - A wrong PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO ANDROID IOS The PIN was entered wrongfully two times, the third attempts requires additional CAN verification, hint where the CAN is found. - Die PIN Ihres Ausweises wurde zweimal falsch eingegeben. Für einen dritten Versuch geben Sie bitte zunächst die sechsstellige Zugangsnummer (CAN) ein. Diese finden Sie rechts unten auf der Vorderseite Ihres Ausweises. + A wrong PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + INFO ANDROID IOS The PIN was entered wrongfully two times, the 3rd attempts requires additional CAN verification, hint where the CAN is found. + Die PIN Ihres Ausweises wurde 2 Mal falsch eingegeben. Für einen 3. Versuch geben Sie bitte zunächst die 6-stellige Zugangsnummer (CAN) ein. Diese finden Sie rechts unten auf der Vorderseite Ihres Ausweises. Send log @@ -78,6 +166,16 @@ LABEL ANDROID IOS A11y button to confirm the PIN and start the provider authentication Bei Anbieter ausweisen + + Authentication failed + LABEL ANDROID IOS + Authentisierung fehlgeschlagen + + + Return to provider + LABEL ANDROID IOS + Zurück zum Anbieter + AuthView @@ -163,12 +261,12 @@ INFO DESKTOP Generic progress status message during authentication.Bei Anbieter ausweisen - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. - Die Benutzung der Online-Ausweisfunktion mit der Transport-PIN ist nicht möglich. Die selbstgewählte, sechsstellige Karten-PIN wird zur Nutzung der Online-Ausweisfunktion zwingend benötigt. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. + Die Benutzung der Online-Ausweisfunktion mit der Transport-PIN ist nicht möglich. Die selbstgewählte, 6-stellige Karten-PIN wird zur Nutzung der Online-Ausweisfunktion zwingend benötigt. - Do you know your six-digit ID card PIN? - Kennen Sie Ihre sechsstellige Karten-PIN? + Do you know your 6-digit ID card PIN? + Kennen Sie Ihre 6-stellige Karten-PIN? The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. @@ -275,8 +373,9 @@ INFO DESKTOP Generic progress status message during authentication. CardReaderDelegate - Press space to open the link in your browser - Drücken Sie die Leertaste um den Link im Browser zu öffnen + Press space to open link. + INFO DESKTOP Text read by screen reader if the text contains a web link to a card reader driver which may be opened. + Drücken Sie die Leertaste um den Link zu öffnen. @@ -302,6 +401,10 @@ INFO DESKTOP Generic progress status message during authentication.No connected card reader found. Keine angeschlossenen Kartenleser gefunden. + + List of connected card readers. + Liste der verbundenen Kartenleser. + CertificateDescriptionPage @@ -315,11 +418,6 @@ LABEL ANDROID IOS ChangePinController - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO ANDROID IOS The ID card has just been unblocked and the user can now continue with their PIN change. - Ihre Karten-PIN wurde entsperrt. Sie haben nun drei weitere Versuche, um Ihre PIN zu ändern. - Setting new Smart-eID PIN LABEL ANDROID IOS Processing screen label while the card communication is running after the new Smart-eID PIN has been entered during PIN change process. @@ -356,19 +454,19 @@ LABEL ANDROID IOS Bitte beachten Sie die Anzeige Ihres Kartenlesers. - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + A wrong ID card PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. INFO ANDROID IOS The wrong ID card PIN was entered twice, the next attempt requires additional verifcation via CAN. - Die Karten-PIN Ihres Ausweises wurde zweimal falsch eingegeben. Für einen dritten Versuch geben Sie bitte zunächst die sechsstellige Zugangsnummer (CAN) ein. Diese finden Sie rechts unten auf der Vorderseite Ihres Ausweises. + Die Karten-PIN Ihres Ausweises wurde 2 Mal falsch eingegeben. Für einen 3. Versuch geben Sie bitte zunächst die 6-stellige Zugangsnummer (CAN) ein. Diese finden Sie rechts unten auf der Vorderseite Ihres Ausweises. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. + You have entered an incorrect, 6-digit ID card PIN 3 times, your ID card PIN is now blocked. To remove the block, the 10-digit PUK must be entered first. INFO ANDROID IOS The ID card PIN (including the CAN) was entered wrongfully three times, the PUK is required to unlock the ID card. - Sie haben dreimal eine falsche, sechsstellige Karten-PIN eingegeben, Ihre Karten-PIN ist nun gesperrt. Um die Sperre aufzuheben, muss zunächst die zehnstellige PUK eingegeben werden. + Sie haben 3 Mal eine falsche, 6-stellige Karten-PIN eingegeben, Ihre Karten-PIN ist nun gesperrt. Um die Sperre aufzuheben, muss zunächst die 10-stellige PUK eingegeben werden. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO ANDROID IOS - Bitte beachten Sie, dass Sie die fünfstellige Transport-PIN nur einmalig zum Ändern in eine sechsstellige Karten-PIN verwenden können. Wenn Sie bereits eine sechsstellige Karten-PIN festgelegt haben, ist die fünfstellige Transport-PIN nicht mehr gültig. + Back to start page + LABEL ANDROID IOS + Zur Startseite @@ -392,11 +490,6 @@ LABEL ANDROID IOS INFO DESKTOP Processing screen text while the card communication is running after the PIN has been entered during PIN change process. Bitte den Ausweis nicht bewegen. - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO DESKTOP The ID card has just been unblocked and the user can now continue with their ID card PIN change. - Ihre Karten-PIN wurde entsperrt. Sie haben nun drei weitere Versuche, um Ihre PIN zu ändern. - Weak NFC signal. Please - change the card position @@ -417,20 +510,15 @@ LABEL ANDROID IOS - stellen Sie sicher, dass der Ausweis korrekt auf dem Kartenleser positioniert ist - bewegen Sie den Ausweis nicht, während auf diesen zugegriffen wird - - Change Transport PIN - LABEL ANDROID IOS - Transport-PIN ändern - The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. INFO DESKTOP The paired devices was removed since it did not respond to connection attempts. It needs to be paired again if it should be used as card reader. Das Gerät "%1" wurde entkoppelt, da es nicht auf Verbindungsversuche reagiert hat. Koppeln Sie das Gerät erneut, um es wieder als Kartenleser zu verwenden. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO DESKTOP - Bitte beachten Sie, dass Sie die fünfstellige Transport-PIN nur einmalig zum Ändern in eine sechsstellige Karten-PIN verwenden können. Wenn Sie bereits eine sechsstellige Karten-PIN festgelegt haben, ist die fünfstellige Transport-PIN nicht mehr gültig. + Back to start page + LABEL DESKTOP + Zur Startseite @@ -441,24 +529,24 @@ LABEL ANDROID IOS Was für eine PIN haben Sie? - Six-digit PIN + 6-digit PIN LABEL ALL_PLATFORMS - Sechsstellige PIN + 6-stellige PIN - Set by yourself + Set by yourself or received by the PIN Reset Service LABEL ALL_PLATFORMS - Von Ihnen selbst gesetzt + Selbst gewählt oder per PIN-Rücksetzdienst erhalten - Five-digit Transport PIN + 5-digit Transport PIN LABEL ALL_PLATFORMS - Fünfstellige Transport-PIN + 5-stellige Transport-PIN - Received by mail in PIN letter + Received by letter while ordering your ID card LABEL ALL_PLATFORMS - Per Post im PIN-Brief erhalten + Bei Beantragung des Ausweises als Brief erhalten No PIN @@ -560,16 +648,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Ausweiszugriff erfolgreich - - Online identification feature disabled - LABEL ANDROID IOS - Online-Ausweisfunktion deaktiviert - - - Online identification feature enabled - LABEL ANDROID IOS - Online-Ausweisfunktion aktiviert - ID card PIN suspended LABEL ANDROID IOS @@ -585,6 +663,16 @@ LABEL ANDROID IOS LABEL ANDROID IOS Ausweis einsatzbereit + + eID function disabled + LABEL ANDROID IOS + Online-Ausweis deaktiviert + + + eID function enabled + LABEL ANDROID IOS + Online-Ausweisfunktion aktiviert + CheckIDCardSuggestionView @@ -599,9 +687,9 @@ LABEL ANDROID IOS Kein NFC - Your mobile device has no NFC interface. This is required to read the ID card. However, you can use a separate smartphone as card reader to utilize the eID function.<br><br>You can find smartphones compatible with the %1 on our website. + Your mobile device has no NFC interface. This is required to read the ID card. To use the eID function on this device you may pair a NFC capable smartphone as a card reader.<br><br>To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>.<br><br>You can find smartphones compatible with the %1 on our website. LABEL ANDROID IOS - Ihr Mobilgerät besitzt keine NFC-Schnittstelle. Diese wird zum Auslesen des Ausweises benötigt. Sie können die Online-Ausweisfunktion aber mit einem anderen Smartphone als Kartenleser nutzen.<br><br>Mit der %1 kompatible Smartphones finden Sie auf unserer Website. + Ihr Mobilgerät besitzt keine NFC-Schnittstelle. Diese wird zum Auslesen des Ausweises benötigt. Möchten Sie die Online-Ausweisfunktion auf diesem Gerät nutzen, können Sie ein NFC-Fähiges Smartphone als Kartenleser koppeln.<br><br>Öffnen Sie dafür das Menü <b>Einstellungen</b> und wählen <b>Kopplungen verwalten</b>.<br><br>Mit der %1 kompatible Smartphones finden Sie auf unserer Website. Open website @@ -613,11 +701,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Keine unterstützte Karte erkannt - - No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check.<br><br>Tip: Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. - LABEL ANDROID IOS - Es wurde kein unterstützter Ausweis erkannt. Die %1 unterstützt:<p><ul><li>deutsche Personalausweise</li><li>elektronische Aufenthaltstitel (eAT)</li><li>eID-Karten</li></ul></p>Haben Sie eines der genannten Dokumente verwendet und diese Fehlermeldung erscheint dennoch, starten Sie bitte die Prüfung erneut.<br><br>Tipp: Versuchen Sie eine andere Kartenposition, stellen Sie sicher, dass Sie den Ausweis während der Prüfung nicht bewegen und dass sich keine anderen NFC-Karten (bspw. Kreditkarten) in der Nähe des Geräts befinden. - Retry LABEL ANDROID IOS @@ -643,11 +726,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Es war nicht möglich, eine stabile Verbindung mit Ihrem Ausweis herzustellen.<br><br>Bitte starten Sie die Prüfung erneut. Versuchen Sie eine andere Kartenposition und achten Sie darauf, die Karte während der Prüfung nicht zu bewegen.<br><br>Wenn auch bei unterschiedlichen Kartenpositionen keine Verbindung zur Ausweiskarte hergestellt werden kann, deutet dies darauf hin, dass die NFC-Schnittstelle Ihres mobilen Geräts die Ausweiskarte nicht ausreichend mit Strom versorgen kann.<br><br>Mit der %1 kompatible Smartphones finden Sie auf unserer <a href="%2">Website</a>. - - Online identification feature disabled - LABEL ANDROID IOS - Online-Ausweisfunktion deaktiviert - OK LABEL ANDROID IOS @@ -659,9 +737,9 @@ LABEL ANDROID IOS Karten-PIN pausiert - The ID card PIN has been entered incorrectly twice in a row. This is why you must first enter the six-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. + The ID card PIN has been entered incorrectly 2 times in a row. This is why you must first enter the 6-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. LABEL ANDROID IOS - Die Karten-PIN wurde zweimal hintereinander falsch eingegeben. Deshalb müssen Sie beim nächsten Ausweisvorgang zunächst die sechstellige Zugangsnummer (CAN) eingeben. Sie finden diese auf der Vorderseite Ihres Ausweises unten rechts.<br><br>Probieren Sie zum Abschluss der Prüfung die Funktion "Meine Daten einsehen". Dort können Sie auch die CAN verwenden, um die PIN-Eingabe fortzusetzen. + Die Karten-PIN wurde 2 Mal hintereinander falsch eingegeben. Deshalb müssen Sie beim nächsten Ausweisvorgang zunächst die 6-stellig Zugangsnummer (CAN) eingeben. Sie finden diese auf der Vorderseite Ihres Ausweises unten rechts.<br><br>Probieren Sie zum Abschluss der Prüfung die Funktion "Meine Daten einsehen". Dort können Sie auch die CAN verwenden, um die PIN-Eingabe fortzusetzen. Continue @@ -674,9 +752,34 @@ LABEL ANDROID IOS Karten-PIN gesperrt - The ID card PIN has been entered incorrectly thrice. Therefore, you must first enter the ten-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + The ID card PIN has been entered incorrectly 3 times. Therefore, you must first enter the 10-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + LABEL ANDROID IOS + Die Karten-PIN wurde 3 Mal hintereinander falsch eingegeben. Deshalb müssen Sie beim nächsten Ausweisvorgang zunächst die 10-stellige PUK eingeben. Sie finden diese im PIN-Brief, den Sie nach Beantragung Ihres Ausweises erhalten haben.<br><br>Probieren Sie zum Abschluss der Prüfung die Funktion "Meine Daten einsehen". Halten Sie zum Entsperren der Karten-PIN Ihre PUK bereit. + + + Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. + LABEL ANDROID IOS + Versuchen Sie eine andere Kartenposition, stellen Sie sicher, dass Sie den Ausweis während der Prüfung nicht bewegen und dass sich keine anderen NFC-Karten (bspw. Kreditkarten) in der Nähe des Geräts befinden. + + + No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards for citizen of the EU/EEA/</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check. + LABEL ANDROID IOS + Es wurde kein unterstützter Ausweis erkannt. Die %1 unterstützt:<p><ul><li>deutsche Personalausweise</li><li>elektronische Aufenthaltstitel (eAT)</li><li>eID-Karten für EU-/EWR-Bürger</li></ul></p>Haben Sie eines der genannten Dokumente verwendet und diese Fehlermeldung erscheint dennoch, starten Sie bitte die Prüfung erneut. + + + eID function disabled + LABEL ANDROID IOS + Online-Ausweis deaktiviert + + + Activate the eID function. + LABEL ANDROID IOS Hint when a workflow failed because the eID function was not activated + Online-Ausweisfunktion aktivieren + + + List of compatible devices LABEL ANDROID IOS - Die Karten-PIN wurde dreimal hintereinander falsch eingegeben. Deshalb müssen Sie beim nächsten Ausweisvorgang zunächst die zehnstellige PUK eingeben. Sie finden diese im PIN-Brief, den Sie nach Beantragung Ihres Ausweises erhalten haben.<br><br>Probieren Sie zum Abschluss der Prüfung die Funktion "Meine Daten einsehen". Halten Sie zum Entsperren der Karten-PIN Ihre PUK bereit. + Liste kompatibler Geräte @@ -692,9 +795,9 @@ LABEL ANDROID IOS Um die Online-Ausweisfunktion nutzen zu können, muss Ihr Gerät gewisse technische Anforderungen erfüllen. Zudem muss die Online-Ausweisfunktion Ihres Ausweises aktiviert sein. - Check if your smartphone and ID card are ready for use. + Check if your device & ID card are ready for use LABEL ANDROID IOS - Prüfen Sie hier, ob Ihr Smartphone und Ihr Ausweis einsatzbereit sind. + Prüfen Sie, ob Ihr Gerät & Ausweis einsatzbereit sind Start check @@ -763,9 +866,9 @@ LABEL ANDROID IOS Die Einrichtung wurde nicht vollständig abgeschlossen. - The Smart-eID PIN has been entered incorrectly three times. + The Smart-eID PIN has been entered incorrectly 3 times. LABEL ANDROID IOS - Die Smart-eID-PIN wurde drei mal falsch eingegeben. + Die Smart-eID-PIN wurde 3 Mal falsch eingegeben. The %1 has been uninstalled temporarily. @@ -825,11 +928,6 @@ LABEL ANDROID IOS LABEL DESKTOP Das Gerät wird gekoppelt ... - - Pairing to "%1" failed: - ERROR DESKTOP An error occurred while pairing the device. - Die Kopplung mit "%1" ist fehlgeschlagen: - DarkModeButtons @@ -867,12 +965,18 @@ LABEL ANDROID IOS DataGroup - selected - ausgewählt + %1, optional right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + %1, optionales Recht, Element %2 von %3 - not selected - nicht ausgewählt + %1, required right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + %1, erforderliches Recht, Element %2 von %3 @@ -930,11 +1034,13 @@ LABEL ANDROID IOS DetachedLogView Select log: + LABEL DESKTOP Protokoll auswählen: - Font size: - Schriftgröße: + Zoom: + LABEL DESKTOP + Zoom: Save log @@ -1167,283 +1273,191 @@ LABEL IOS_PHONE ANDROID_PHONE You are about to identify yourself towards the following provider: - LABEL DESKTOP ----------- -LABEL IOS_PHONE ANDROID_PHONE + LABEL IOS ANDROID Sie möchten sich bei folgendem Anbieter ausweisen: - - Provider - LABEL IOS_PHONE ANDROID_PHONE - Anbieter - - - Touch for more details - LABEL IOS_PHONE ANDROID_PHONE - Tippen Sie hier für mehr Details - EnterPasswordView - - Attempts - LABEL DESKTOP - Versuche - Enter CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. CAN eingeben Enter PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. PUK eingeben Enter pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Kopplungscode eingeben - Enter new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Neue Karten-PIN eingeben + Choose new ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Neue Karten-PIN wählen Confirm new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Neue Karten-PIN bestätigen Enter Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Transport-PIN eingeben Enter ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Karten-PIN eingeben - Please enter the five-digit Transport PIN. - INFO DESKTOP The AA2 expects the Transport PIN with five digits. ----------- -INFO ANDROID IOS The Transport PIN is required by AA2, it needs to be change to an actual PIN. - Bitte geben Sie die fünfstellige Transport-PIN ein. - - - Please enter your current six-digit ID card PIN. - INFO DESKTOP The AA2 expects the current ID card PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current ID card PIN with six digits in a PIN change. - Bitte geben Sie Ihre aktuelle sechsstellige Karten-PIN ein. - - - Please enter your six-digit ID card PIN. - INFO DESKTOP The AA2 expects a ID card PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a ID card PIN with six digits in an authentication. - Bitte geben Sie Ihre sechsstellige Karten-PIN ein. - - - Please enter the six-digit Card Access Number (CAN). You can find it in the bottom right on the front of the ID card. - INFO DESKTOP The user is required to enter the six-digit CAN in CAN-allowed authentication. ----------- -INFO ANDROID IOS The user is required to enter the six-digit CAN in CAN-allowed authentication. - Bitte geben Sie die sechsstellige Zugangsnummer (CAN) ein. Diese finden Sie unten rechts auf der Vorderseite des Ausweises. - - - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO DESKTOP The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. ----------- -INFO ANDROID IOS The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. - Die Karten-PIN Ihres Ausweises wurde zweimal falsch eingegeben. Für einen dritten Versuch geben Sie bitte zunächst die sechsstellige Zugangsnummer (CAN) ein. Diese finden Sie rechts unten auf der Vorderseite Ihres Ausweises. + Please enter the 5-digit Transport PIN. + INFO ALL_PLATFORMS The Transport PIN is required by AA, it needs to be change to an actual PIN. This is the description for the main text. + Bitte geben Sie die 5-stellige Transport-PIN ein. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO DESKTOP The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. ----------- -INFO ANDROID IOS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. - Sie haben dreimal eine falsche, sechsstellige Karten-PIN eingegeben, Ihre Karten-PIN ist nun gesperrt. Um die Sperre aufzuheben, muss zunächst die zehnstellige PUK eingegeben werden. + Please enter your current 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects the current ID card PIN with six digits in a PIN change. This is the description for the main text. + Bitte geben Sie Ihre aktuelle 6-stellige Karten-PIN ein. - Please enter a new six-digit ID card PIN now. - INFO DESKTOP A new six-digit ID card PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit ID card PIN needs to be supplied. - Bitte geben Sie nun eine neue sechsstellige Karten-PIN ein. + Please enter your 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects a ID card PIN with six digits in an authentication. This is the description for the main text. + Bitte geben Sie Ihre 6-stellige Karten-PIN ein. - Please confirm your new six-digit ID card PIN. - INFO DESKTOP The new ID card PIN needs to be entered again for verification. ----------- -INFO ANDROID IOS The new ID card PIN needs to be confirmed. - Bitte wiederholen Sie die Eingabe Ihrer neuen sechsstelligen Karten-PIN. + You will enter this 6-digit PIN every time you want to use your ID card online. + INFO ALL_PLATFORMS A new 6-digit ID card PIN needs to be supplied. This is the description for the main text. + Diese 6-stellige PIN geben Sie jedes Mal ein, wenn Sie Ihren Ausweis online benutzen. - Unknown password type: - INFO DESKTOP Error message during PIN/CAN/PUK input procedure, the requested password type is unknown; internal error. - Unbekannter Passwort-Typ: + The PIN is going to be tied to your ID card. It always stays the same regardless of the device you want to use your ID card with. + INFO ALL_PLATFORMS The new ID card PIN needs to be confirmed. This is the description for the main text. + Die Karten-PIN wird mit Ihrem Ausweis verknüpft. Sie bleibt gleich, egal auf welchem Gerät Sie Ihren Online-Ausweis nutzen. - Do you have a five-digit Transport PIN? - LABEL ANDROID IOS Button to start a change of the Transport PIN. - Haben Sie eine fünfstellige Transport-PIN? + Do you have a 5-digit Transport PIN? + LABEL ALL_PLATFORMS Button to start a change of the Transport PIN. + Haben Sie eine 5-stellige Transport-PIN? Enter Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Smart-eID-PIN eingeben - Enter new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Neue Smart-eID-PIN eingeben + Choose new Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Neue Smart-eID-PIN wählen Confirm new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Neue Smart-eID-PIN bestätigen - You have entered an incorrect, six-digit Smart-eID PIN twice. An incorrect third attempt will invalidate your Smart-eID and you will have to set it up again. - INFO DESKTOP The wrong Smart-eID PIN was entered twice on the Smart-eID - Sie haben zweimal eine falsche, sechsstellige Smart-eID-PIN eingegeben. Ein dritter Fehlversuch wird Ihre Smart-eID ungültig machen und Sie müssen sie neu einrichten. + The PIN is going to be tied to your Smart-eID. It always stays the same regardless of the service you want to use your Smart-eID with. + INFO ALL_PLATFORMS The new Smart-eID PIN needs to be confirmed. This is the description for the main text. + Die Smart-eID-PIN wird mit Ihrer Smart-eID verknüpft. Sie bleibt gleich, egal für welchen Dienst Sie Ihre Smart-eID nutzen. - Please confirm your new six-digit Smart-eID PIN. - INFO DESKTOP The new Smart-eID PIN needs to be confirmed. ----------- -INFO ANDROID IOS The new Smart-eID PIN needs to be confirmed. - Bitte bestätigen Sie Ihre neue sechsstellige Smart-eID-PIN. - - - Please enter a new six-digit Smart-eID PIN now. - INFO DESKTOP A new six-digit Smart-eID PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit Smart-eID PIN needs to be supplied. - Bitte vergeben Sie eine neue sechsstellige Smart-eID-PIN. + You will enter this 6-digit PIN every time you want to use your Smart-eID. + INFO ALL_PLATFORMS A new 6-digit Smart-eID PIN needs to be supplied. This is the description for the main text. + Diese 6-stellige PIN geben Sie jedes Mal ein, wenn Sie Ihre Smart-eID benutzen. Enter the pairing code shown on the device you want to pair. - INFO ANDROID IOS The pairing code for the smartphone is required. + INFO MOBILE The pairing code for the smartphone is required. This is the description for the main text. Geben Sie den Kopplungscode ein, der auf dem zu koppelnden Smartphone angezeigt wird. - Please enter your current six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects the current Smart-eID PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current Smart-eID PIN with six digits in a PIN change. - Bitte geben Sie Ihre aktuelle sechsstellige Smart-eID-PIN ein. + Please enter your current 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects the current Smart-eID PIN with six digits in a PIN change. This is the description for the main text. + Bitte geben Sie Ihre aktuelle 6-stellige Smart-eID-PIN ein. - Please enter your six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects a Smart-eID PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a Smart-eID PIN with six digits in an authentication. - Bitte geben Sie Ihre sechsstellige Smart-eID-PIN ein. + Please enter your 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects a Smart-eID PIN with six digits in an authentication. This is the description for the main text. + Bitte geben Sie Ihre 6-stellige Smart-eID-PIN ein. - Do you have a six-digit ID card PIN? - LABEL ANDROID IOS Button to switch to a six-digit ID card PIN. - Haben Sie eine sechsstellige Karten-PIN? + Do you have a 6-digit ID card PIN? + LABEL ALL_PLATFORMS Button to switch to a 6-digit ID card PIN. + Haben Sie eine 6-stellige Karten-PIN? - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice on the Smart-eID - Sie haben zweimal eine falsche, sechsstellige Smart-eID-PIN eingegeben. Nach dem nächsten Fehlversuch können Sie Ihre Smart-eID nicht mehr einsetzen und müssen diese neu einrichten. + You have entered an incorrect, 6-digit Smart-eID PIN 2 times. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered twice on the Smart-eID + Sie haben 2 Mal eine falsche, 6-stellige Smart-eID-PIN eingegeben. Nach dem nächsten Fehlversuch können Sie Ihre Smart-eID nicht mehr einsetzen und müssen diese neu einrichten. Send CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. CAN senden Send PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. PUK senden Send pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Kopplungscode senden Send new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Neue Karten-PIN senden Send Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Transport-PIN senden Send Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Smart-eID-PIN senden Send new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Neue Smart-eID-PIN senden Send ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Karten-PIN senden - Send confirmation of new ID card PIN - LABEL ANDROID IOS - Bestätigung der neuen Karten-PIN senden + Enter the pairing code shown on your smartphone. + INFO DESKTOP The pairing code needs to be supplied. This is the description for the main text. + Geben Sie den Kopplungscode ein, der auf Ihrem Smartphone angezeigt wird. - Send confirmation of new Smart-eID PIN - LABEL ANDROID IOS - Bestätigung der neuen Smart-eID-PIN senden + Please enter the CAN. You can find the CAN in the bottom right on the front of the ID card. + INFO ALL_PLATFORMS The user is required to enter the 6-digit CAN. This is the description for the main text. + Bitte geben Sie Ihre CAN ein. Sie finden die CAN unten rechts auf der Vorderseite Ihres Ausweises. - Enter the pairing code shown on your smartphone. - INFO DESKTOP The pairing code needs to be supplied. - Geben Sie den Kopplungscode ein, der auf Ihrem Smartphone angezeigt wird. + Please enter your 10-digit PUK. + INFO ALL_PLATFORMS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. This is the description for the main text. + Bitte geben Sie Ihre 10-stellige PUK ein. + + + Confirm ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Karten-PIN bestätigen + + + Confirm Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Smart-eID-PIN bestätigen @@ -1474,9 +1488,9 @@ LABEL ANDROID IOS GText - Press space to open link: %1 - INFO ALL_PLATFORMS Text read by screen reader if the text contains a weblink which may be opened. - Drücken Sie die Leertaste, um diesen Link zu öffnen: %1 + Press space to open link + INFO DESKTOP Text read by screen reader if the text contains a weblink which may be opened. + Drücken Sie die Leertaste, um diesen Link zu öffnen @@ -1488,11 +1502,6 @@ LABEL ANDROID IOS GeneralSettings - - Language selection - LABEL DESKTOP - Sprachauswahl - Behavior LABEL DESKTOP @@ -1548,14 +1557,39 @@ LABEL ANDROID IOS LABEL WINDOWS Text for auto-start option %1 automatisch beim Hochfahren starten und im Benachrichtigungsfeld hinzufügen - - - GeneralWorkflow - Attempts + Change language + LABEL DESKTOP + Sprache wechseln + + + Use images instead of animations + LABEL DESKTOP + Bilder statt Animationen verwenden + + + Accessibility + LABEL DESKTOP + Barrierefreiheit + + + Hide key animations when entering PIN LABEL DESKTOP - Versuche + Tastenanimationen bei PIN-Eingabe ausblenden + + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. + LABEL DESKTOP + Nach dem Ausweisen erfolgt die Weiterleitung zurück zum Anbieter erst nach Bestätigung. Ansonsten erfolgt die Weiterleitung automatisch nach wenigen Sekunden. + + + Manual redirection back to the provider + LABEL DESKTOP + Manuelle Weiterleitung zurück zum Anbieter + + + + GeneralWorkflow Step %1 of 3 Schritt %1 von 3 @@ -1586,9 +1620,9 @@ LABEL ANDROID IOS Es wurde kein Ausweis erkannt. Bitte stellen Sie sicher, dass Ihr Ausweis auf dem Kartenleser aufliegt. - No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and available. Open the reader settings to configure readers and get more information about supported readers. + No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and ready. Open the reader settings to configure readers and get more information about supported readers. INFO DESKTOP AA2 is waiting for the card reader or the ID card. - Es wurde kein Kartenleser gefunden. Bitte überprüfen Sie, ob ein USB-Kartenleser angeschlossen bzw. ein Smartphone als Kartenleser gekoppelt und verfügbar ist. Öffnen Sie die Einstellungen, um Kartenleser zu konfigurieren und weitere Hinweise zu erhalten. + Es wurde kein Kartenleser gefunden. Bitte überprüfen Sie, ob ein USB-Kartenleser angeschlossen bzw. ein Smartphone als Kartenleser gekoppelt und bereit ist. Öffnen Sie die Einstellungen, um Kartenleser zu konfigurieren und weitere Hinweise zu erhalten. Please observe the display of your card reader. @@ -1610,15 +1644,99 @@ LABEL ANDROID IOS INFO DESKTOP The AA2 is waiting for an ID card to be inserted into the card reader (or smartphone for that matter). Bitte folgen Sie den Anweisungen auf Ihrem Smartphone (verbunden mit %1) oder legen Sie den Ausweis auf den Kartenleser. + + The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. + INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. + Das Gerät "%1" wurde entkoppelt, da es nicht auf Verbindungsversuche reagiert hat. Koppeln Sie das Gerät erneut, um es wieder als Kartenleser zu verwenden. + - Hint + InputErrorView - Hint - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Tipp + Wrong CAN + LABEL ALL_PLATFORMS + Falsche CAN + + + Wrong PUK + LABEL ALL_PLATFORMS + Falsche PUK + + + Wrong Transport PIN + LABEL ALL_PLATFORMS + Falsche Transport-PIN + + + Wrong Smart-eID PIN + LABEL ALL_PLATFORMS + Falsche Smart-eID-PIN + + + Wrong ID card PIN + LABEL ALL_PLATFORMS + Falsche Karten-PIN + + + Wrong new ID card PIN confirmation + LABEL ALL_PLATFORMS + Falsche Bestätigung der neuen Karten-PIN + + + Wrong new Smart-eID PIN confirmation + LABEL ALL_PLATFORMS + Falsche Bestätigung der neuen Smart-eID-PIN + + + Continue + LABEL ALL_PLATFORMS + Weiter + + + + InputSuccessView + + PUK is correct + INFO ALL_PLATFORMS + PUK ist korrekt + + + You now have <b>3 more attempts</b> to enter your correct <b>ID card PIN</b>. + INFO ALL_PLATFORMS + Sie haben nun <b>3 weitere Versuche</b>, um Ihre <b>Karten-PIN</b> korrekt einzugeben. + + + Continue + LABEL ALL_PLATFORMS + Weiter + + + CAN is correct + INFO ALL_PLATFORMS + CAN ist korrekt + + + Please enter your <b>6-digit ID card PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Bitte geben Sie nun Ihre <b>6-stellige Karten-PIN</b> ein. <b>Das ist Ihr letzter Versuch</b>. + + + If you enter a wrong ID Card PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Falls Sie erneut eine falsche Karten-PIN eingeben, wird die PIN gesperrt. Diese Sperre können Sie nur mit der PUK aufheben. + + + Please enter your <b>5-digit Transport PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Bitte geben Sie nun Ihre <b>5-stellige Transport-PIN</b> ein. <b>Das ist Ihr letzter Versuch</b>. + + + If you enter a wrong Transport PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Falls Sie erneut eine falsche Transport-PIN eingeben, wird die PIN gesperrt. Diese Sperre können Sie nur mit der PUK aufheben. + + + You now have <b>3 more attempts</b> to enter your correct <b>Transport PIN</b>. + INFO ALL_PLATFORMS + Sie haben nun <b>3 weitere Versuche</b>, um Ihre <b>Transport-PIN</b> korrekt einzugeben. @@ -1691,10 +1809,6 @@ LABEL ANDROID IOS Share log Protokoll teilen - - Delete log - Protokoll löschen - Delete all logs Alle Protokolle löschen @@ -1717,31 +1831,14 @@ LABEL ANDROID IOS LABEL DESKTOP Protokolldateien (*.log) - - Delete log - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Protokoll löschen - The current log will be automatically deleted at exit. Das aktuelle Protokoll wird beim Beenden automatisch gelöscht. - - Delete old logs - LABEL DESKTOP - Lösche alte Protokolle - Detach log viewer Protokoll separat anzeigen - - Delete selected log - LABEL DESKTOP - Ausgewähltes Protokoll löschen - All old logs will be deleted. INFO DESKTOP All logfiles are about to be removed, user confirmation required. @@ -1749,13 +1846,6 @@ LABEL ANDROID IOS INFO ANDROID IOS All logfiles are about to be removed, user confirmation required. Alle Protokolle werden gelöscht. - - The log will be deleted. - INFO DESKTOP The current logfile is about to be removed, user confirmation required. ----------- -INFO ANDROID IOS The current logfile is about to be removed, user confirmation required. - Das Protokoll wird gelöscht. - Log LABEL ANDROID IOS @@ -1767,12 +1857,16 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Delete all logs - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Alle Protokolle löschen Delete - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Löschen @@ -1826,11 +1920,6 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r LABEL DESKTOP Hilfe - - Start page - LABEL ANDROID IOS - Startseite - Check device and ID card LABEL ANDROID IOS @@ -1850,10 +1939,6 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Two finger swipe to scroll. Mit zwei Fingern wischem zum Scrollen. - - List of workflows with %1 items. - Liste mit %1 Vorgängen. - Item %1 of %2 Element %1 von %2 @@ -1865,6 +1950,10 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r LABEL ANDROID IOS PIN ändern + + Three finger swipe to scroll. + Mit drei Fingern wischem zum Scrollen. + MoreInformationLink @@ -1885,14 +1974,14 @@ LABEL ANDROID IOS General - LABEL DESKTOP + LABEL DESKTOP +---------- +LABEL ANDROID IOS Allgemein Version information - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ANDROID IOS Versionsinformationen @@ -1907,11 +1996,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Release Notes - - Help & Feedback - LABEL ANDROID IOS - Hilfe & Feedback - Privacy statement LABEL ANDROID IOS @@ -1934,7 +2018,9 @@ LABEL ANDROID IOS Information - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Information @@ -2003,21 +2089,6 @@ LABEL ANDROID IOS LABEL DESKTOP Öffne Webseite - - Privacy statement - LABEL DESKTOP - Datenschutzerklärung - - - Accessibility statement - LABEL DESKTOP - Barrierefreiheitserklärung - - - Do you want to see a list of service providers? - LABEL DESKTOP - Möchten Sie eine Liste mit Diensteanbietern sehen? - List of Providers LABEL DESKTOP @@ -2045,25 +2116,6 @@ LABEL ANDROID IOS Zurück - - NavigationButton - - Yes - Ja - - - No - Nein - - - Continue - Fortsetzen - - - Back - Zurück - - NavigationView @@ -2082,6 +2134,31 @@ LABEL ANDROID IOS Card reader Kartenleser + + %1 of %2 + ANDROID IOS LABEL Relative position of current navigation tab in navigation view. %1 is replaced with the current tab's index, %2 with the total count of tabs + %1 von %2 + + + Tab + ANDROID IOS LABEL + Tab + + + Selection + IOS Selected navigation tab. + Auswahl + + + Tab bar + IOS Name of a11y element of selected navigation tab. + Tab-Leiste + + + Selected + ANDROID Currently selected navigation tab of navigation view. + Ausgewählt + NfcWorkflow @@ -2095,16 +2172,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS NFC-Scan starten - - Unfortunately, this functionality is not available on your device. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - Diese Funktion steht auf Ihrem Gerät leider nicht zur Verfügung. - - - However, you can use a separate smartphone as card reader to utilize the eID function. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - Sie können die Online-Ausweisfunktion aber mit einem anderen Smartphone als Kartenleser nutzen. - NFC is switched off. INFO ANDROID IOS NFC is available but needs to be activated in the settings of the smartphone. @@ -2155,23 +2222,53 @@ LABEL ANDROID IOS INFO IOS The ID card may be inserted, the authentication process may be started. Bitte platzieren Sie Ihren Ausweis oben an der Geräterückseite. - - Please place your ID card directly on the device's back side.<br/><br/>The exact position of the ID card is device dependent. The animations depict possible positions. Keep one position for several seconds before trying another one and do not move the ID card after contact was established. - INFO ANDROID The ID card may be inserted, the authentication process may be started. - Bitte platzieren Sie Ihren Ausweis direkt an der Geräterückseite.<br/><br/>Die genaue Position des Ausweises ist modellabhängig. Die Animationen zeigen Ihnen mögliche Positionen. Halten Sie jede Position einige Sekunden, bevor Sie eine andere ausprobieren und bewegen Sie den Ausweis nicht mehr, sobald der Kontakt hergestellt wurde. - The device "%1" wants to use this smartphone as card reader and connect to your id card. INFO ANDROID IOS %1 will be replaced with the name of the device. Das Gerät "%1" möchte dieses Smartphone als Kartenleser nutzen und sich mit Ihrem Ausweis verbinden. + + The animations depict possible positions. + INFO ANDROID Text regarding ID card position animations + Die Animationen zeigen Ihnen mögliche Positionen. + + + The exact position of the ID card is device dependent. + INFO ANDROID Text regarding different NFC chip positions on different smartphones + Die genaue Position des Ausweises ist modellabhängig. + + + Keep one position for several seconds before trying another one and do not move the ID card after contact was established. + INFO ANDROID Text that one ID card position should be kept for several seconds + Halten Sie jede Position einige Sekunden, bevor Sie eine andere ausprobieren und bewegen Sie den Ausweis nicht mehr, sobald der Kontakt hergestellt wurde. + + + Please place your ID card directly on the device's back side. + INFO ANDROID Text regarding the ID card position on the device + Bitte platzieren Sie Ihren Ausweis direkt an der Geräterückseite. + + + This device cannot be used to read your ID card. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + Dieses Gerät kann nicht zum Auslesen des Ausweises verwendet werden. + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + Möchten Sie die Online-Ausweisfunktion auf diesem Gerät nutzen, können Sie ein NFC-fähiges Smartphone als Kartenleser koppeln. + + + To pair a smartphone select the <b>WiFi</b> option and click <b>Manage Pairings</b>. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + Wählen Sie dafür die Option <b>WLAN</b> und klicken <b>Kopplungen verwalten</b>. + NumberField - The password is hidden. + The number is hidden. LABEL DESKTOP Screenreader text for the password field - Das Passwort ist ausgeblendet. + Die Geheimzahl ist ausgeblendet. You entered %1 of %2 digits. @@ -2179,19 +2276,19 @@ LABEL ANDROID IOS Sie haben %1 von %2 Ziffern eingegeben. - Press to hide the password + Press to hide the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Drücken Sie die Taste um das Passwort auszublenden + Drücken Sie die Taste um die Geheimnummer einzublenden - Press to show the password + Press to show the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Drücken Sie die Taste um das Passwort einzublenden + Drücken Sie die Taste um die Geheimnummer auszublenden - The password is visible. Digits entered so far: %1 + The number is visible. Digits entered so far: %1 LABEL DESKTOP Screenreader text for the password field - Das Passwort ist sichtbar. Bisher eingegebene Ziffern: %1 + Die Geheimnummer ist sichtbar. Bisher eingegebene Ziffern: %1 @@ -2203,10 +2300,12 @@ LABEL ANDROID IOS Delete last digit + LABEL ANDROID IOS A11y text for the "delete" button image. Lösche letzte Ziffer Submit + LABEL ANDROID IOS A11y text for the "submit" button image. Absenden @@ -2236,19 +2335,32 @@ LABEL ANDROID IOS Open %1 on your %2other device%3. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4 Öffnen Sie auf Ihrem %2anderen Gerät%3 die %1. On that device go to %1Settings%2 and then %1Smartphone as card reader%2 resp. %1Manage pairings%2. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 3. %1 and %2 are surrounding tags for bold font. + LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 and %2 are surrounding tags for bold font. Gehen Sie dort in die %1Einstellungen%2 und dann zu %1Smartphone als Kartenleser%2 bzw. %1Kopplungen verwalten%2. Choose this smartphone in the list to pair it. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4 Wählen Sie in der angezeigten Liste dieses Smartphone aus, um es zu koppeln. + + Enter the pairing code "%1". + LABEL ANDROID IOS Provide pairing code. Step 4 of 4 + Geben Sie den Kopplungscode "%1" ein. + + + + PairingFailedView + + Pairing to "%1" failed: + ERROR ALL_PLATFORMS An error occurred while pairing the device. + Die Kopplung mit "%1" ist fehlgeschlagen: + PairingProcessInfo @@ -2273,6 +2385,18 @@ LABEL ANDROID IOS Stellen Sie sicher, dass die %1 auf Ihrem Smartphone als Kartenleser mindestens die Version %2 hat. + + PairingSuccessView + + Pairing with "%1" successful, it will be listed under "Paired devices". + INFO ALL_PLATFORMS The pairing with the SaC server was successful. + Die Kopplung mit "%1" war erfolgreich, es wird bei den "Gekoppelten Geräten" gelistet. + + + The device may now be used as a card reader. + Das Gerät kann nun als Kartenleser verwendet werden. + + PasswordInfoContent @@ -2304,14 +2428,14 @@ LABEL ANDROID IOS Wie wähle ich eine sichere PIN? - For your six-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + For your 6-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 1/3 - Wählen Sie für Ihre sechsstellige PIN eine Zahlenkombination, die nicht zu erraten ist - also weder „123456“, noch Ihr Geburtsdatum oder andere Zahlen, die auf dem Ausweis aufgedruckt sind. + Wählen Sie für Ihre 6-stellige PIN eine Zahlenkombination, die nicht zu erraten ist - also weder „123456“, noch Ihr Geburtsdatum oder andere Zahlen, die auf dem Ausweis aufgedruckt sind. - You can change your six-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. + You can change your 6-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 2/3 - Sie können Ihre sechsstellige PIN jederzeit und unbegrenzt oft ändern, solange Ihnen Ihre gültige PIN bekannt ist. + Sie können Ihre 6-stellige PIN jederzeit und unbegrenzt oft ändern, solange Ihnen Ihre gültige PIN bekannt ist. Keep your PIN secret and change it if another person becomes aware of it. @@ -2326,24 +2450,24 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Was ist die Transport-PIN? - Transport PIN information - LABEL ALL_PLATFORMS - Transport-PIN-Information + The Transport PIN is a %1one-time PIN%2 which is required for the initial %1setup of your ID card%2. Once you replace the %1Transport PIN with a card PIN%2, it is tied to your ID card and valid for all devices. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' + Die Transport-PIN ist eine %1Einmal-PIN%2, die zur erstmaligen %1Einrichtung Ihres Online-Ausweises%2 benötigt wird. Sobald Sie die %1Transport-PIN mit einer Karten-PIN ersetzen%2, ist diese mit Ihrem Ausweis verknüpft und gilt auf allen Geräten. - The five-digit Transport PIN was sent to you in the PIN letter by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 1/3 - Die fünfstellige Transport-PIN wurde Ihnen im PIN-Brief per Post zugesandt, nachdem Sie Ihren Ausweis beantragt haben. + Where do I find the Transport PIN? + LABEL ALL_PLATFORMS + Wo finde ich die Transport-PIN? - If you did not set a self-selected six-digit card PIN when you picked up your ID card, you can do so using the Transport PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 2/3 - Falls Sie nicht direkt bei der Abholung Ihres Ausweises eine selbstgewählte, sechsstellige Karten-PIN gesetzt haben, können Sie dies mithilfe der Transport-PIN tun. + The 5-digit Transport PIN is a %1one-time PIN%2, that you reveived per %1letter%2 when applying for the ID card. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 1/2 + Die 5-stellige Transport-PIN ist eine %1Einmal-PIN%2, die Sie bei Beantragung des Online-Ausweises per %1Brief%2 erhalten. - Once you have set a card PIN, the Transport PIN loses its validity. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 3/3 - Sobald Sie eine Karten-PIN gesetzt haben, verliert die Transport-PIN Ihre Gültigkeit. + When setting up your ID card, you will %1replace%2 this 5-digit %1Transport PIN with%2 a 6-digit, %1self chosen card PIN%2. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 2/2 + Wenn Sie Ihren Online-Ausweis einrichten, %1ersetzen Sie%2 diese 5-stellige %1Transport-PIN durch%2 eine 6-stellige, %1selbstgewählte Karten-PIN%2. Where do I find the PUK? @@ -2351,14 +2475,9 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Wo finde ich die PUK? - PUK information - LABEL ALL_PLATFORMS - PUK-Information - - - The PUK is a ten-digit number that you can find in the PIN letter that was sent to you by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' - Die PUK ist eine zehnstellige Zahl, die Sie in dem PIN-Brief finden, der Ihnen nach Beantragung Ihres Ausweises per Post zugeschickt wurde. + The PUK is a %1 10-digit number%2 that you can find in the %1PIN letter%2 that was sent to you by mail after you %1applied for your ID card%2. You may find it to the %1right%2 of the 5-digit %1Transport PIN%2. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' + Die PUK ist eine %1 10-stellige Zahl%2, die Sie in dem %1PIN-Brief%2 finden, den Sie %1nach Beantragung Ihres Ausweises%2 erhalten. Sie befindet sich %1rechts neben%2 der 5-stelligen %1Transport-PIN%2. Why is the PUK required? @@ -2366,49 +2485,44 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Warum wird die PUK verlangt? - The PUK is required if the card PIN has been entered incorrectly three times in a row. As a result, the card PIN is blocked. + The PUK is required if the %1card PIN has been entered incorrectly 3 times%2 in a row. As a result, the card PIN is blocked. By entering the PUK you will %1unblock the card PIN%2 and have %1 3 more attempts%2 to enter the correct PIN. INFO ALL_PLATFORMS Answer to the question 'Why is the PUK required?' - Die PUK wird verlangt, wenn die Karten-PIN dreimal hintereinander falsch eingegeben wurde. Die Karten-PIN ist dadurch gesperrt. + Die PUK wird verlangt, wenn die %1Karten-PIN 3-mal falsch eingegeben%2 wurde. Die Karten-PIN ist dadurch gesperrt. Durch die Eingabe der PUK %1entsperren Sie die Karten-PIN%2 und haben %1 3 weitere Versuche%2, die richtige PIN einzugeben. - What is the PUK's purpose? + My PUK does not work LABEL ALL_PLATFORMS - Was ist die Funktion der PUK? + Meine PUK funktioniert nicht - By entering the PUK, you unblock the card PIN and have another three chances to enter the correct PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the PUK's purpose?' - Durch die Eingabe der PUK entsperren Sie die Karten-PIN wieder und haben weitere drei Möglichkeiten, die richtige PIN einzugeben. + Make sure, that the letter at hand is the %1letter for your current ID card%2. The PIN letter is valid only for your current ID card. With a new ID card, you receive a new PIN letter with a new PUK. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + Stellen Sie sicher, dass es sich bei dem vorliegenden Brief um den %1Brief zu Ihrem aktuellen Ausweis%2 handelt. Der PIN-Brief ist nur an den jeweiligen Ausweis geknüpft. Bei Wechsel des Ausweises bekommen Sie daher einen neuen PIN-Brief mit neuer PUK. - Why is the CAN required? - LABEL ALL_PLATFORMS - Warum wird die CAN verlangt? + If you applied for a PIN Reset letter, make sure that you don't mix up the letters. The %1PIN letter you need contains the 5-digit Transport PIN and the PUK%2. The PIN Reset letter contains the 6-digit card PIN and the activation code. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + Falls Sie einen PIN-Rücksetzbrief bestellt haben, stellen Sie sicher, dass Sie die Briefe nicht verwechseln. Der %1PIN-Brief, den Sie benötigen, enthält die 5-stellige Transport-PIN und die PUK%2. Der PIN-Rücksetzbrief enthält jedoch die 6-stellige Karten-PIN und den Aktivierungscode. - CAN information - LABEL ALL_PLATFORMS - CAN-Information - - - When is the card access number (CAN) required? + Why is the CAN required? LABEL ALL_PLATFORMS - Wann wird die Zugangsnummer (CAN) verlangt? + Warum wird die CAN verlangt? - The card access number (CAN) is required when the card PIN has been entered incorrectly twice. + The card access number (CAN) is required when the %1card PIN has been entered incorrectly 2 times%2. INFO ALL_PLATFORMS Answer to the question 'When is the card access number (CAN) required?' - Die Zugangsnummer (CAN) wird verlangt, wenn die Karten-PIN zweimal falsch eingegeben wurde. + Die Zugangsnummer (CAN) wird verlangt, wenn die %1Karten-PIN 2 Mal falsch eingegeben wurde%2. - Why do I have to enter the CAN before a third attempt? + Why do I have to enter the CAN before a 3rd attempt? LABEL ALL_PLATFORMS - Warum muss ich vor einem dritten Versuch die CAN eingeben? + Warum muss ich vor einem 3. Versuch die CAN eingeben? - A third incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that a third incorrect entry can only be made with direct access to your ID card. - INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a third attempt?' - Eine dritte Fehleingabe sperrt Ihre PIN und Sie können die Online-Ausweisfunktion bis zur Entsperrung nicht mehr nutzen. Durch die Abfrage der CAN wird sichergestellt, dass nur mit direktem Zugriff auf Ihren Ausweis eine dritte Fehleingabe erfolgen kann. + A 3rd incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that %1direct access to your ID card%2 is given. + INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a 3rd attempt?' + Eine 3. Fehleingabe sperrt Ihre PIN und Sie können die Online-Ausweisfunktion bis zur Entsperrung nicht mehr nutzen. Durch die Abfrage der CAN wird sichergestellt, dass ein %1direkter Zugriff zum Ausweis vorliegt%2. Where can I find the CAN? @@ -2416,14 +2530,14 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Wo finde ich die CAN? - The CAN is a six-digit number that can be found on the bottom right of the front of the ID card. + The CAN is a 6-digit number that can be found on the %1bottom right%2 of the %1front of the ID card%2. INFO ALL_PLATFORMS Answer to the question 'Where can I find the CAN?' - Die CAN ist eine sechsstellige Zahl, die unten rechts auf der Vorderseite des Ausweises zu finden ist. + Die CAN ist eine 6-stellige Zahl, die %1unten rechts%2 auf der %1Vorderseite des Ausweisdokuments%2 zu finden ist. - The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a six-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in red). + The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a 6-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in picture). INFO ALL_PLATFORMS Description text of CAN-allowed authentication - Die Zugangsnummer (CAN) ermöglicht den Zugriff auf die auf dem Ausweis gespeicherten Daten. Die CAN ist eine sechsstellige Zahl, die auf der Vorderseite des Ausweises unten rechts zu finden ist (rot markiert). + Die Zugangsnummer (CAN) ermöglicht den Zugriff auf die auf dem Ausweis gespeicherten Daten. Die CAN ist eine 6-stellige Zahl, die auf der Vorderseite des Ausweises unten rechts zu finden ist (auf Abbildung markiert). Smart-eID blocking code @@ -2453,9 +2567,9 @@ LABEL ALL_PLATFORMS Sie kennen Ihre PIN nicht? - You have not yet set a six-digit card PIN and cannot find the PIN letter with the Transport PIN? + You have not yet set a 6-digit card PIN and cannot find the PIN letter with the Transport PIN? INFO ALL_PLATFORMS - Sie haben noch keine sechsstellige PIN gesetzt und können den Brief mit der Transport-PIN nicht finden? + Sie haben noch keine 6-stellige PIN gesetzt und können den Brief mit der Transport-PIN nicht finden? You set a card PIN when picking up your ID card or later by yourself, but you can no longer remember it? @@ -2463,49 +2577,29 @@ LABEL ALL_PLATFORMS Sie haben bei der Abholung des Ausweises oder später selbst eine Karten-PIN gesetzt, können sich aber nicht mehr an diese erinnern? - Learn more about the two types of PIN - LABEL ALL_PLATFORMS - Erfahren Sie mehr über die zwei PIN-Arten - - - Types of PIN + How do the PIN types differ? LABEL ALL_PLATFORMS - PIN-Arten + Wie unterscheiden sich die PIN-Arten? - Your ID card comes with a five-digit 'Transport PIN' which you need to replace with a six-digit PIN that you choose yourself. + Your ID card comes with a 5-digit %1Transport PIN%2 which you need to %1replace with%2 a 6-digit %1card PIN%2 that you choose yourself. INFO ALL_PLATFORMS Description text explaining the PINs 1/7 - Ihr Ausweis wurde bei Erstellung mit einer fünfstelligen „Transport-PIN“ versehen, die Sie durch eine sechsstellige, selbstgewählte PIN ersetzen müssen. - - - Five-digit Transport PIN - LABEL ALL_PLATFORMS - Fünfstellige Transport-PIN + Ihr Ausweis wurde bei Erstellung mit einer 5-stelligen %1Transport-PIN%2 versehen, die Sie %1durch eine%2 6-stellige, selbstgewählte %1Karten-PIN ersetzen%2 müssen. - Six-digit PIN + 5-digit Transport PIN LABEL ALL_PLATFORMS - Sechsstellige PIN + 5-stellige Transport-PIN - You can use the PIN Reset Service to request a new card PIN free of charge. + 6-digit PIN LABEL ALL_PLATFORMS - Dann fordern Sie jetzt mithilfe des PIN-Rücksetzdienstes kostenlos eine neue Karten-PIN an. - - - If you do not know either your Transport PIN or your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. - Wenn Ihnen weder Ihre Transport-PIN noch Ihre Karten-PIN bekannt ist, können Sie mit dem PIN-Rücksetzdienst kostenlos eine neue PIN anfordern. - - - If you have forgotten your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - Wenn Sie Ihre Karten-PIN vergessen haben, können Sie mit dem PIN-Rücksetzdienst kostenlos eine neue PIN anfordern. + 6-stellige PIN - The five-digit Transport PIN was sent to you by mail after you applied for your ID card. + The 5-digit Transport PIN is a %1one-time PIN%2 that was sent to you by %1mail%2 after you applied for your ID card. INFO ALL_PLATFORMS Description text explaining the PINs 2/7 - Die fünfstellige Transport-PIN wurde Ihnen per Post zugesandt, nachdem Sie Ihren Ausweis beantragt haben. + Die 5-stellige Transport-PIN ist eine %1Einmal-PIN%2, die Sie bei Beantragung des Online-Ausweises per %1Brief%2 erhalten haben. What is the Smart-eID PIN? @@ -2518,34 +2612,34 @@ LABEL ALL_PLATFORMS Smart-eID einrichten - The Smart-eID PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. + The Smart-eID PIN is a 6-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' - Die Smart-eID-PIN ist eine sechsstellige PIN, die Sie selbst setzen. Diese PIN brauchen Sie immer, wenn Sie die Smart-eID nutzen möchten. + Die Smart-eID-PIN ist eine 6-stellige PIN, die Sie selbst setzen. Diese PIN brauchen Sie immer, wenn Sie die Smart-eID nutzen möchten. - For your six-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + For your 6-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 - Wählen Sie für Ihre sechsstellige Smart-eID-Pin eine Zahlenkombination, die nicht leicht zu erraten ist - also weder „123456“, noch Ihr Geburtsdatum oder andere Zahlen, die auf dem Ausweis aufgedruckt sind. + Wählen Sie für Ihre 6-stellige Smart-eID-Pin eine Zahlenkombination, die nicht leicht zu erraten ist - also weder „123456“, noch Ihr Geburtsdatum oder andere Zahlen, die auf dem Ausweis aufgedruckt sind. - You can change your six-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. + You can change your 6-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 - Sie können Ihre sechsstellige Smart-eID-PIN jederzeit und unbegrenzt oft ändern, solange Ihnen Ihre gültige Smart-eID-PIN bekannt ist. + Sie können Ihre 6-stellige Smart-eID-PIN jederzeit und unbegrenzt oft ändern, solange Ihnen Ihre gültige Smart-eID-PIN bekannt ist. - The PIN can only be used once. When you set up the eID function, you will replace this five-digit Transport PIN with a six-digit card PIN that you choose yourself. + When you set up the eID function, you will %1replace%2 this 5-digit %1Transport PIN%2 with a 6-digit %1card PIN that you choose yourself%2. INFO ALL_PLATFORMS Description text explaining the PINs 3/7 - Diese PIN kann nur einmal verwendet werden. Wenn Sie Ihren Online-Ausweis einrichten, ersetzen Sie diese fünfstellige Transport-PIN durch eine sechsstellige, selbstgewählte Karten-PIN. + Wenn Sie Ihren Online-Ausweis einrichten, %1ersetzen Sie%2 diese 5-stellige %1Transport-PIN durch%2 eine 6-stellige, %1selbstgewählte Karten-PIN%2. - The six-digit card PIN is a number that you choose yourself when you set up the eID function for the first time. It replaces your five-digit Transport PIN. + The 6-digit card PIN is a %1number that you choose yourself%2 when you set up the eID function for the first time. It %1replaces%2 your %1 5-digit Transport PIN%2. INFO ALL_PLATFORMS Description text explaining the PINs 4/7 - Die sechsstellige Karten-PIN ist eine Zahlenkombination, die Sie selbst vergeben, wenn Sie Ihren Online-Ausweis zum ersten Mal einrichten. Sie ersetzt Ihre fünfstellige Transport-PIN. + Die 6-stellige Karten-PIN ist %1eine Geheimnummer, die Sie selbst wählen%2, wenn Sie Ihren Online-Ausweis zum ersten Mal einrichten. Sie %1ersetzt%2 Ihre %1 5-stellige Transport-PIN%2. The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time. INFO ALL_PLATFORMS Description text explaining the PINs 5/7 - Auch die Smart-eID-PIN ist sechsstellig. Sie vergeben auch diese PIN selbst, wenn Sie die Smart-eID zum ersten Mal einrichten. + Auch die Smart-eID-PIN ist 6-stellig. Sie vergeben auch diese PIN selbst, wenn Sie die Smart-eID zum 1. Mal einrichten. You can change your card PIN and your Smart-eID PIN at any time in %1. @@ -2553,19 +2647,49 @@ LABEL ALL_PLATFORMS Sie können die Karten-PIN und die Smart-eID-PIN jederzeit in der %1 ändern. - With this six-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. + With this 6-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - Mit der sechsstelligen PIN weisen Sie online nach, dass der Ausweis bzw. die Smart-eID Ihnen gehören. Keiner kann die Online-Ausweisfunktion benutzen ohne diese PIN. + Mit der 6-stelligen PIN weisen Sie online nach, dass der Ausweis bzw. die Smart-eID Ihnen gehören. Keiner kann die Online-Ausweisfunktion benutzen ohne diese PIN. - The card PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use the eID function with your ID card. + The card PIN is a 6-digit PIN that you set yourself. You always need this %1PIN%2 if you want to use the %1eID function%2. INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' - Die Karten-PIN ist eine sechsstellige PIN, die Sie selbst gesetzt haben. Diese PIN brauchen Sie immer, wenn Sie die Online-Ausweisfunktion mit Ihrer Ausweiskarte nutzen möchten. + Die Karten-PIN ist eine 6-stellige PIN, die Sie selbst gewählt haben. Diese %1PIN%2 brauchen Sie immer, wenn Sie die %1Online-Ausweisfunktion%2 nutzen möchten. - You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the five-digit Transport PIN. Only when you have set a six-digit PIN of your own choice can you use the eID function and set up a Smart-eID. + You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the 5-digit Transport PIN. Only when you have set a 6-digit PIN of your own choice can you use the eID function and set up a Smart-eID. INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) - Sie haben die Karten-PIN entweder direkt bei der Abholung des Ausweises im Bürgeramt oder später in der %1 mithilfe der fünfstelligen Transport-PIN gesetzt. Erst wenn Sie eine selbstgewählte, sechsstellige PIN gesetzt haben, können Sie die Online-Ausweisfunktion nutzen und eine Smart-eID einrichten. + Sie haben die Karten-PIN entweder direkt bei der Abholung des Ausweises im Bürgeramt oder später in der %1 mithilfe der 5-stelligen Transport-PIN gesetzt. Erst wenn Sie eine selbstgewählte, 6-stellige PIN gesetzt haben, können Sie die Online-Ausweisfunktion nutzen und eine Smart-eID einrichten. + + + The card PIN was %1either%2... + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Intro + Die Karten-PIN wurde %1entweder%2... + + + set by you when picking up the ID card %1at the citiziens' office%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 1/3 + von Ihnen direkt bei der Abholung des Ausweises %1in der Ausweisbehörde%2 gesetzt + + + set %1in the %3 using%2 the 5-digit %1Transport PIN%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 2/3 + %1in der %3 mithilfe%2 der 5-stelligen %1Transport-PIN%2 gesetzt + + + requested using the %1PIN Reset Service%2 - you may continue using the 6-digit card PIN from the letter or change it via "Change PIN" to a self chosen card PIN + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 3/3 + per %1PIN-Rücksetzdienst%2 beantragt - die 6-stellige Karten-PIN aus dem Brief können Sie weiterverwenden oder per "PIN ändern" durch eine selbstgewählte Karten-PIN ersetzen + + + I just have a 5-digit Transport PIN + LABEL ALL_PLATFORMS + Ich habe nur eine 5-stellige Transport-PIN + + + You need to change the %1 5-digit Transport PIN%2 to your personal card PIN. Use %1Change PIN > Transport PIN%2 from the startpage to do so. + INFO ALL_PLATFORMS Explanation if only the Transport PIN is at hand + Die %1 5-stellige Transport-PIN%2 müssen Sie durch Ihre persönliche Karten-PIN ersetzen. Wählen Sie hierfür auf der Startseite %1PIN ändern > Transport-PIN%2. If you have forgotten your Smart-eID PIN, you can renew your Smart-eID and thereby set a new PIN. @@ -2583,14 +2707,62 @@ LABEL ALL_PLATFORMS Sie haben die Smart-eID-PIN bei der Einrichtung der Smart-eID gesetzt. - With this six-digit PIN you prove online that the ID card belongs to you. No one can use the eID function without this PIN. + With this 6-digit PIN you prove online that the ID card belongs to you. %1No one can use the eID function without this PIN%2. INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - Mit der sechsstelligen PIN weisen Sie online nach, dass der Ausweis Ihnen gehört. Keiner kann die Online-Ausweisfunktion benutzen ohne diese PIN. + Mit der 6-stelligen, selbstgewählten PIN weisen Sie online nach, dass der Ausweis Ihnen gehört. %1Ohne diese PIN kann keiner Ihren Ausweis online nutzen%2. - You can change your card PIN at any time in %1. + If you applied for a %1PIN Reset letter%2, a new card PIN was already set for you. You can change your card PIN at %1any time in %3%2. INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 - Sie können die Karten-PIN jederzeit in der %1 ändern. + Falls Sie einen %1PIN-Rücksetzbrief%2 bestellt haben, wurde Ihnen bereits eine Karten-PIN gesetzt. Sie können Ihre Karten-PIN jedoch %1jederzeit in der %3 ändern%2. + + + I can't recall my PIN + LABEL ALL_PLATFORMS + Ich kenne meine PIN nicht + + + I can't recall my PUK + Ich kenne meine PUK nicht + + + Set a new PIN + Neue PIN setzen + + + My Transport PIN does not work + LABEL ALL_PLATFORMS + Meine Transport-PIN funktioniert nicht + + + If your Transport PIN from the PIN letter does work, this might be caused by the following reasons: + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Introduction why the Transport PIN might not work. + Wenn Ihre Transport-PIN aus dem PIN-Brief nicht funktioniert, kann das folgende Gründe haben: + + + You already set a 6-digit PIN either at the competent authority or using the %1. + INFO ALL_PLATFORMS Information why the Transport PIN is void: a 6-digit PIN was already set + Sie haben bereits eine 6-stellige PIN gewählt, in der Behörde oder per %1. + + + You applied for PIN Reset Letter (letter containing a 6-digit PIN and corresponding Activation Code). + INFO ALL_PLATFORMS Information why the Transport PIN is void: the PIN Reset Service was used + Sie haben einen PIN-Rücksetzbrief bestellt (Brief mit 6-stelliger PIN & Aktivierungscode). + + + Once you set a 6-digit PIN, the Transport PIN is no longer valid. You may then only use the 6-digit PIN to authenticate yourself. + INFO ALL_PLATFORMS Information that the Transport PIN is void once a 6-digit PIN was set. + Sobald Sie eine 6-stellige PIN gesetzt haben, ist die Transport-PIN hinfällig. Sie können dann ausschließlich die 6-stellige PIN zum Ausweisen verwenden. + + + + PasswordInfoView + + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Tipp @@ -2629,7 +2801,7 @@ LABEL ALL_PLATFORMS Wichtige Informationen - Do not give your smartphone to third parties unattended, especially if it is already unlocked. + Do not give your smartphone to 3rd parties unattended, especially if it is already unlocked. LABEL ANDROID IOS Geben Sie Ihr Smartphone nicht unbeaufsichtigt an Dritte weiter, insbesondere wenn es bereits entsperrt ist. @@ -2639,7 +2811,7 @@ LABEL ALL_PLATFORMS Notieren Sie die Smart-eID-PIN nicht in bzw. auf Ihrem Smartphone. - Do not give your Smart-eID PIN to third parties. + Do not give your Smart-eID PIN to 3rd parties. LABEL ANDROID IOS Geben Sie Ihre Smart-eID-PIN nicht an Dritte weiter. @@ -2739,11 +2911,6 @@ LABEL ALL_PLATFORMS INFO ANDROID IOS Success message that the Smart-eID was created. Sie haben Ihre Smart-eID erfolgreich eingerichtet. - - OK - LABEL ANDROID IOS - OK - Continue LABEL ANDROID IOS @@ -2769,6 +2936,16 @@ LABEL ALL_PLATFORMS LABEL ANDROID IOS Achtung: Sie können mit Ihrem Ausweis noch <b><u>eine</u></b> Smart-eID einrichten. Weitere Einrichtungen können Sie ab dem %1 vornehmen. + + Personalization failed + LABEL ANDROID IOS + Personalisierung fehlgeschlagen + + + Back to start page + LABEL ANDROID IOS + Zur Startseite + PkiSwitch @@ -2812,10 +2989,10 @@ LABEL ALL_PLATFORMS - ProviderInfoSection + ProviderInfo See details under "more..." - LABEL DESKTOP + LABEL ALL_PLATFORMS Weitere Details unter "mehr..." @@ -2823,6 +3000,21 @@ LABEL ALL_PLATFORMS LABEL DESKTOP Zeige mehr Informationen über den Anbieter + + You are about to identify yourself towards the following provider: + LABEL DESKTOP + Sie möchten sich bei folgendem Anbieter ausweisen: + + + Provider + LABEL ANDROID IOS + Anbieter + + + Touch for more details + LABEL ANDROID IOS + Tippen Sie hier für mehr Details + Details about the provider LABEL DESKTOP @@ -2872,8 +3064,8 @@ LABEL DESKTOP Title of the proxy credentials popup. Es ist ein Fehler bei der Protokollverwaltung aufgetreten: %1 - Please describe the error that occurred. - Bitte beschreiben Sie den aufgetretenen Fehler. + Please describe the error that occurs. Our support is available to you in German and English. + Bitte beschreiben Sie den auftretenden Fehler. Unser Support steht Ihnen in deutscher und englischer Sprache zur Verfügung. You may want to attach the logfile which can be saved from the error dialog. @@ -2904,6 +3096,44 @@ LABEL DESKTOP Title of the proxy credentials popup. Unbekannter Kartenleser + + RedirectView + + Remove the ID card from the card reader + INFO DESKTOP Hint to user that the ID card should be removed + Entfernen Sie nun den Ausweis vom Kartenleser + + + Remove the ID card from the NFC interface + INFO ANDROID IOS Hint to user that the ID card should be removed + Entfernen Sie jetzt Ihren Ausweis von der NFC-Schnittstelle + + + If you have any questions or encounter any errors during the process, please contact the corresponding provider. + LABEL ALL_PLATFORMS + Bei Rückfragen oder auftretenden Fehlern zum Vorgang wenden Sie sich bitte an den jeweiligen Anbieter. + + + You will be automatically redirected to the provider in a few seconds. If you are not automatically redirected, click on the "%1" button. + INFO ALL_PLATFORMS Redirect information when automatic redirect is enabled + Die automatische Weiterleitung zum Anbieter erfolgt in wenigen Sekunden. Falls Sie nicht automatisch weitergeleitet werden, drücken Sie auf den Button "%1". + + + Press the button to complete the authentication and return to the provider. + INFO ALL_PLATFORMS Redirect information when automatic redirect is disabled + Drücken Sie auf den Button, um die Authentisierung abzuschließen und zum Anbieter zurückzukehren. + + + Return to provider + LABEL ALL_PLATFORMS + Zurück zum Anbieter + + + Authentication successful + LABEL ALL_PLATFORMS + Authentisierung erfolgreich + + ReleaseNotes @@ -2922,15 +3152,18 @@ LABEL ANDROID IOS RemoteReaderDelegate - Smartphone named "%1" - Smartphone namens "%1" + Smartphone named "%1". %2. + INFO DESKTOP Name and status of remote device. %1 is replaced with the name, %2 with the status + Smartphone namens "%1". %2. Press space to unpair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is paired. Drücken Sie die Leertaste um das Smartphone "%1" zu entkoppeln. Press space to pair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is unpaired. Drücken Sie die Leertaste um das Smartphone "%1" zu koppeln. @@ -2955,10 +3188,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 is a placeholder-tag for the app name. Öffnen Sie die %1 auf Ihrem Smartphone als Kartenleser. - - Both devices have to be connected to the same WiFi. - Beide Geräte müssen mit demselben WLAN verbunden sein. - On that device go to %1Card reader%2 and then %1Pair device%2 rsp. %1Pair new device%2. LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4. %1 and %2 are surrounding tags for bold font @@ -2979,6 +3208,10 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4. %1 is a placeholder-tag for the app name. Stellen Sie sicher, dass die %1 auf Ihrem Smartphone als Kartenleser mindestens die Version %2 hat. + + Both devices have to be on the same network (e.g. WiFi). + Beide Geräte müssen hierfür im selben Netzwerk (z.B. WLAN) sein. + RemoteServiceController @@ -3008,11 +3241,6 @@ LABEL ANDROID IOS RemoteServiceView - - Pairing failed. Please start a new pairing process on your other device and enter the shown pairing code. - ERROR ANDROID IOS An error occurred while pairing the device. - Die Kopplung ist fehlgeschlagen. Bitte starten Sie eine neue Kopplung an Ihrem anderen Gerät und geben den angezeigten Kopplungscode ein. - WiFi not active LABEL ANDROID IOS @@ -3023,25 +3251,20 @@ LABEL ANDROID IOS LABEL ANDROID IOS NFC nicht aktiv - - Remote service not available - LABEL ANDROID IOS - Fernzugriff nicht verfügbar - Card access in progress LABEL ANDROID IOS Kartenzugriff - Waiting for connection + Card reader ready LABEL ANDROID IOS - Warte auf Verbindung + Kartenleser bereit - Waiting for connection from a paired device... + To do this, start a process on a paired device. INFO ANDROID IOS - Warte auf eine Verbindung eines gekoppelten Gerätes... + Starten Sie hierzu auf einem gekoppelten Gerät einen Vorgang. Pairing code: <b>%1</b> @@ -3064,9 +3287,9 @@ LABEL ANDROID IOS Gerät koppeln - Allow connection + Activate card reader LABEL ANDROID IOS - Verbindung erlauben + Kartenleser aktivieren You can use this Smartphone as a card reader for the %1 on other devices e.g. a laptop. @@ -3108,9 +3331,9 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel Wo gebe ich den Kopplungscode ein? - Enter the pairing code %1 in the %2 on your other device. + Enter the pairing code "%1" in the %2 on your other device. INFO ANDROID IOS - Geben Sie den Kopplungscode %1 in der %2 auf Ihrem anderen Gerät ein. + Geben Sie den Kopplungscode "%1" in der %2 auf Ihrem anderen Gerät ein. Cancel pairing @@ -3127,6 +3350,16 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel INFO ANDROID IOS Gekoppelte Geräte können dieses Smartphone jetzt als Kartenleser nutzen. + + NFC is not available + LABEL ANDROID IOS + Kein NFC verfügbar + + + Stop card reader + LABEL ANDROID IOS + Kartenleser beenden + RemoteServiceViewRemote @@ -3190,13 +3423,18 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel LABEL ANDROID IOS Klicken zum Koppeln + + Pairing the device ... + LABEL ANDROID IOS + Das Gerät wird gekoppelt ... + RemoteServiceWifiInfo - Both devices have to be connected to the same WiFi. + Both devices have to be on the same network (e.g. WiFi). INFO ANDROID IOS The remote service is active. Hint that both devices need to be connected to the same network. - Beide Geräte müssen mit demselben WLAN verbunden sein. + Beide Geräte müssen hierfür im selben Netzwerk (z.B. WLAN) sein. @@ -3249,15 +3487,16 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel ResultErrorView - - Details - Details - Error code: LABEL ANDROID IOS Fehlercode: + + Show Details + LABEL ANDROID IOS + Details anzeigen + ResultView @@ -3286,26 +3525,20 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel LABEL ANDROID IOS OK - - - RetryCounter - Remaining ID card PIN attempts: %1 - LABEL DESKTOP - Verbleibende Karten-PIN Versuche: %1 + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Tipp SecurityAndPrivacySettings - Onscreen keypad - LABEL DESKTOP - Bildschirmtastatur - - - Use on screen keypad for PIN entry + Numeric keypad LABEL DESKTOP - Bildschirmtastatur für die PIN-Eingabe verwenden + Ziffernblock Software updates @@ -3313,9 +3546,9 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel Software-Aktualisierungen - Check at program start + Check for updates at program start LABEL DESKTOP - Automatisch bei Programmstart prüfen + Automatisch bei Programmstart nach Updates suchen Show update @@ -3348,19 +3581,19 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel Keine Aktualisierungsinformationen vorhanden, bitte prüfen Sie manuell auf verfügbare Aktualisierungen. - Shuffle digits of on screen keypad + Shuffle keys LABEL DESKTOP - Ziffern der Bildschirmtastatur zufällig anordnen + Tasten zufällig anordnen - Button animation + Hide key animations LABEL DESKTOP - Tasten-Animationen + Tasten Animationen ausblenden - Visually highlight key presses on screen keypad + Makes it difficult for outsiders to detect PIN entry LABEL DESKTOP - Eingaben auf der Bildschirmtastatur optisch hervorheben + Erschwert eine Erkennung der PIN-Eingabe durch Außenstehende @@ -3380,18 +3613,18 @@ Hierfür müssen Sie zuvor das entsprechende Gerät mit diesem Smartphone koppel LABEL DESKTOP Title of the self authentication result data view Ausgelesene Daten - - OK - LABEL DESKTOP ----------- -LABEL ANDROID IOS - OK - Identify LABEL ANDROID IOS Ausweisen + + Back to start page + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Zur Startseite + SelfAuthenticationView @@ -3418,9 +3651,7 @@ LABEL ANDROID IOS Use the button "See my personal data" to start the self-authentication service of the manufacturer of the %1 to display the data stored in the chip of your ID card. - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Über die Schaltfläche "Meine Daten einsehen" können Sie den Selbstauskunftsdienst des Herstellers der %1 aufrufen, um sich die im Chip Ihres Ausweises gespeicherten Daten anzeigen zu lassen. @@ -3440,6 +3671,11 @@ LABEL ANDROID IOS LABEL ANDROID IOS Tipp + + View the data stored on your ID card + LABEL ANDROID IOS + Sehen Sie sich die Daten an, die auf Ihrem Ausweis gespeichert sind + SettingsView @@ -3471,11 +3707,14 @@ LABEL ANDROID IOS Security and privacy - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Sicherheit und Datenschutz + + Numeric keypad + LABEL ANDROID IOS + Ziffernblock + Debug options LABEL DESKTOP @@ -3506,14 +3745,14 @@ LABEL ANDROID IOS PIN-Eingabe auf diesem Gerät - Randomize the order of the on screen keypad buttons + Shuffle keys LABEL ANDROID IOS - Ziffern der Bildschirmtastatur zufällig anordnen + Tasten zufällig anordnen - Keypad animations + Hide key animations LABEL ANDROID IOS - Tasten-Animationen + Tasten Animationen ausblenden Skip rights page @@ -3540,11 +3779,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Benutze einen toleranten Modus - - Layout style - LABEL ANDROID IOS - Layout-Stil - Create dummy entries LABEL ANDROID IOS @@ -3636,9 +3870,34 @@ LABEL ANDROID IOS Bei der Authentisierung eine Testmusterkarte simulieren - Visually highlight key presses on screen keypad + Makes it difficult for outsiders to detect PIN entry + LABEL ANDROID IOS + Erschwert eine Erkennung der PIN-Eingabe durch Außenstehende + + + Use images instead of animations + LABEL ANDROID IOS + Bilder statt Animationen verwenden + + + Accessibility + LABEL ANDROID IOS + Barrierefreiheit + + + Hide key animations when entering PIN LABEL ANDROID IOS - Eingaben auf der Bildschirmtastatur optisch hervorheben + Tastenanimationen bei PIN-Eingabe ausblenden + + + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. + LABEL ANDROID IOS + Nach dem Ausweisen erfolgt die Weiterleitung zurück zum Anbieter erst nach Bestätigung. Ansonsten erfolgt die Weiterleitung automatisch nach wenigen Sekunden. + + + Manual redirection back to the provider + LABEL ANDROID IOS + Manuelle Weiterleitung zurück zum Anbieter @@ -3890,9 +4149,9 @@ LABEL ANDROID IOS Smart-eID - You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your six-digit ID card PIN and an internet connection. + You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Sie sind dabei, eine Smart-eID auf Ihrem Gerät einzurichten. Um fortzufahren, benötigen Sie Ihren Ausweis, Ihre sechsstellige Karten-PIN sowie eine Internetverbindung. + Sie sind dabei, eine Smart-eID auf Ihrem Gerät einzurichten. Um fortzufahren, benötigen Sie Ihren Ausweis, Ihre 6-stellige Karten-PIN sowie eine Internetverbindung. Set up Smart-eID @@ -3908,9 +4167,9 @@ LABEL ANDROID IOS SmartUpdateStartView - You are about to renew your Smart-eID. In order to proceed, you need your ID card, your six-digit ID card PIN and an internet connection. + You are about to renew your Smart-eID. In order to proceed, you need your ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Sie sind dabei, Ihre Smart-eID zu erneuern. Um fortzufahren, benötigen Sie Ihren Ausweis, Ihre sechsstellige Karten-PIN sowie eine Internetverbindung. + Sie sind dabei, Ihre Smart-eID zu erneuern. Um fortzufahren, benötigen Sie Ihren Ausweis, Ihre 6-stellige Karten-PIN sowie eine Internetverbindung. Please note that your current Smart-eID is invalidated during the process and will not be usable until the update process is completed. @@ -4052,6 +4311,26 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au App bewerten + + SuggestionData + + Hint + Tipp + + + + TabbedPane + + Tab selected + LABEL DESKTOP + Registerkarte ausgewählt + + + %1 of %2 + LABEL DESKTOP %1 is the current selected Page of %2 Pages + %1 von %2 + + TabbedReaderView @@ -4067,6 +4346,10 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au USB card reader USB Kartenleser + + Found new USB card reader that is suitable for the ID card. The workflow may now be continued. + Es wurde ein neuer USB-Kartenleser gefunden, der für den Ausweis geeignet ist. Der Vorgang kann nun fortgesetzt werden. + TechnologySwitch @@ -4090,6 +4373,16 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au LABEL ANDROID IOS SIM + + %1 mode is active. + INFO ANDROID IOS A11y text on button indicating the currently active technology. %1 will be replaced with the name of the technology (e.g. NFC). + %1 Modus ist aktiv. + + + Click here to change the mode to %1. + INFO ANDROID IOS A11y text on button to switch to another technology. %1 will be replaced with the name of the technology (e.g. NFC). + Klicken Sie hier um auf den %1 Modus zu wechseln. + TitleBar @@ -4112,13 +4405,19 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Show in-app notifications of %1 - Zeige den interne Benachrichtigungsdialog der %1 + LABEL DESKTOP + Internen Benachrichtigungsdialog der %1 einblenden Title bar LABEL DESKTOP Titelleiste + + Hide in-app notifications of %1 + LABEL DESKTOP + Internen Benachrichtigungsdialog der %1 ausblenden + TitleBarNavigation @@ -4136,9 +4435,9 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au TransportPinReminderView - Do you know your six-digit ID card PIN? + Do you know your 6-digit ID card PIN? LABEL ANDROID IOS - Kennen Sie Ihre sechsstellige Karten-PIN? + Kennen Sie Ihre 6-stellige Karten-PIN? No @@ -4151,14 +4450,14 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Ja - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. LABEL ANDROID IOS - Die Benutzung der Online-Ausweisfunktion mit der Transport-PIN ist nicht möglich. Die selbstgewählte, sechsstellige Karten-PIN wird zur Nutzung der Online-Ausweisfunktion zwingend benötigt. + Die Benutzung der Online-Ausweisfunktion mit der Transport-PIN ist nicht möglich. Die selbstgewählte, 6-stellige Karten-PIN wird zur Nutzung der Online-Ausweisfunktion zwingend benötigt. - To set up a Smart-eID you also need to have assigned a six-digit PIN beforehand. + To set up a Smart-eID you also need to have assigned a 6-digit PIN beforehand. LABEL ANDROID IOS - Auch für die Einrichtung der Smart-eID müssen Sie zuvor die sechsstellige Karten-PIN gesetzt haben. + Auch für die Einrichtung der Smart-eID müssen Sie zuvor die 6-stellige Karten-PIN gesetzt haben. @@ -4230,16 +4529,6 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au UpdateViewButtonRow - - Skip update - LABEL DESKTOP User choice to skip this update, the automatic update check will *not* inform about this update again. - Aktualisierung überspringen - - - Remind me later - LABEL DESKTOP The available update is shown again after next automatic update check. - Später erinnern - Open App Store LABEL DESKTOP Open the Mac App Store on macOS @@ -4316,6 +4605,21 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au LABEL ANDROID IOS Erweiterte Einstellungen deaktiviert. + + Open website + LABEL DESKTOP + Öffne Webseite + + + Privacy statement + LABEL DESKTOP + Datenschutzerklärung + + + Accessibility statement + LABEL DESKTOP + Barrierefreiheitserklärung + WhiteListSurveyView @@ -4364,14 +4668,6 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Senden - - WorkflowInfoList - - The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. - INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. - Das Gerät "%1" wurde entkoppelt, da es nicht auf Verbindungsversuche reagiert hat. Koppeln Sie das Gerät erneut, um es wieder als Kartenleser zu verwenden. - - governikus::AccessRoleAndRightsUtil @@ -4537,6 +4833,31 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au INFO ALL_PLATFORMS Failure code (string) of current workflow error. Grund: + + Redirect failed + LABEL ALL_PLATFORMS + Weiterleitung fehlgeschlagen + + + Authentication failed + LABEL ALL_PLATFORMS + Authentisierung fehlgeschlagen + + + Authentication successful + LABEL ALL_PLATFORMS + Authentisierung erfolgreich + + + Return to provider + LABEL ALL_PLATFORMS + Zurück zum Anbieter + + + Back to start page + LABEL ALL_PLATFORMS + Zur Startseite + governikus::CardInfo @@ -4799,12 +5120,12 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Antivirus-Erkennung fehlgeschlagen. - Third party firewalls cannot be detected on Windows 7. + 3rd party firewalls cannot be detected on Windows 7. LABEL DESKTOP Firewalls von Drittherstellern können auf Windows 7 nicht erkannt werden. - No third party firewalls detected + No 3rd party firewalls detected LABEL DESKTOP Keine Drittanbieter-Firewall erkannt @@ -4819,7 +5140,7 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Auf dem aktuellen Stand: %1 - Firewalls from third party vendors + Firewalls from 3rd party vendors LABEL DESKTOP Firewalls von Drittanbietern @@ -4963,6 +5284,11 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au LABEL DESKTOP Nicht gebunden + + Encountered error: %1 + LABEL DESKTOP + Aufgetretener Fehler: %1 + governikus::ECardApiResult @@ -5355,9 +5681,9 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Die PIN ist nicht gesperrt. - The entered PUK has already been used ten times and can no longer be used to unblock the PIN. + The entered PUK has already been used 10 times and can no longer be used to unblock the PIN. ERROR ALL_PLATFORMS The card declined the PUK since it was entered wrongfully 10 times. - Die eingegebene PUK wurde bereits zehn Mal verwendet und kann nicht mehr zur Entsperrung der PIN genutzt werden. + Die eingegebene PUK wurde bereits 10 Mal verwendet und kann nicht mehr zur Entsperrung der PIN genutzt werden. The new PIN and the confirmation do not match. @@ -5400,9 +5726,9 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Bei der Verbindung zum Smartphone als Kartenleser (SaK) ist ein Fehler aufgetreten. - The smartphone to be paired has rejected the connection. Please check the pairing code. If no pairing code is shown activate the pairing mode. + The smartphone to be paired has rejected the connection. Please check the pairing code. ERROR ALL_PLATFORMS The requested connection to the smartphone card reader (SaK) was rejected by the device. - Das zu koppelnde Smartphone hat die Verbindung verweigert. Überprüfen Sie bitte den Kopplungscode. Sollte kein Kopplungscode angezeigt werden aktivierten Sie bitte den Kopplungsmodus. + Das zu koppelnde Smartphone hat die Verbindung verweigert. Überprüfen Sie bitte den Kopplungscode. File not found. @@ -5450,7 +5776,7 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Die Authentisierung gegenüber dem Personalisierungsservice ist fehlgeschlagen. - The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN three times. You may personalize a new Smart-eID to resolve the issue. + The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN 3 times. You may personalize a new Smart-eID to resolve the issue. ERROR ALL_PLATFORMS The existing Smart-eID was invalidated. Die Smart-eID ist nicht mehr einsatzbereit. Dies kann an einer dreifachen, fehlerhaften Eingabe der Smart-eID-PIN liegen. Um dieses Problem zu beheben, können Sie eine neue Smart-eID personalisieren. @@ -5519,7 +5845,7 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au - governikus::LocalIfdReaderManagerPlugIn + governikus::LocalIfdReaderManagerPlugin Connection closed by remote with status: %1. Die Verbindung wurde von der Gegenstelle mit dem Status %1 geschlossen. @@ -5601,76 +5927,114 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au governikus::NumberModel - You have entered an incorrect, five-digit Transport PIN. You have two further attempts to enter the correct Transport PIN. - INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. - Sie haben eine falsche, fünfstellige Transport-PIN eingegeben. Sie haben zwei weitere Versuche, die korrekte Transport-PIN einzugeben. + You have entered an incorrect, 6-digit Smart-eID PIN. You have <b>2 further attempts</b> to enter the correct Smart-eID PIN. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. + Sie haben eine falsche, 6-stellige Smart-eID-PIN eingegeben. Sie haben <b>2 weitere Versuche</b>, die richtige Smart-eID-PIN einzugeben. + + + You have entered an incorrect, 5-digit Transport PIN 3 times, your <b>Transport PIN is now blocked</b>. To remove the block, the <b>10-digit PUK</b> must be entered first. + INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. + Sie haben 3 Mal eine falsche, 5-stellige Transport-PIN eingegeben, Ihre <b>Transport-PIN ist nun gesperrt</b>. Um die Sperre aufzuheben, muss zunächst die <b>10-stellige PUK</b> eingegeben werden. - You have entered an incorrect, six-digit Smart-eID PIN. You have two further attempts to enter the correct Smart-eID PIN. - INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. - Sie haben eine falsche, sechsstellige Smart-eID-PIN eingegeben. Sie haben zwei weitere Versuche, die richtige Smart-eID-PIN einzugeben. + You have entered an incorrect, 6-digit Smart-eID PIN 3 times. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. + INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. + Sie haben 3 Mal eine falsche, 6-stellige Smart-eID-PIN eingegeben. Ihre Smart-eID ist nun ungültig. Um die Smart-eID erneut nutzen zu können, müssen Sie erneut die Einrichtung auf der Startseite durchführen. - You have entered an incorrect, six-digit ID card PIN. You have two further attempts to enter the correct ID card PIN. - INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. - Sie haben eine falsche, sechsstellige Karten-PIN eingegeben. Sie haben zwei weitere Versuche, die richtige Karten-PIN einzugeben. + You have entered an incorrect, 10-digit PUK. Please try again. + INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. + Sie haben eine falsche, 10-stellige PUK eingegeben. Bitte versuchen Sie es erneut. - You have entered an incorrect, five-digit Transport PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. - Sie haben zweimal eine falsche, fünfstellige Transport-PIN eingegeben. Für den dritten Versuch muss zunächst die sechsstellige Zugangsnummer (CAN) eingegeben werden. Sie finden Ihre CAN unten rechts auf der Vorderseite Ihres Ausweises. + You have entered an <b>incorrect, 6-digit Smart-eID PIN 2 times</b>. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a 3rd wrong attempt could invalidate the Smart-eID. + Sie haben <b>2 Mal eine falsche, 6-stellige Smart-eID-PIN</b> eingegeben. Nach dem nächsten Fehlversuch können Sie Ihre Smart-eID nicht mehr einsetzen und müssen diese neu einrichten. - You have entered an incorrect, six-digit ID card PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. - Sie haben zweimal eine falsche, sechsstellige Karten-PIN eingegeben. Für den dritten Versuch muss zunächst die sechsstellige Zugangsnummer (CAN) eingegeben werden. Sie finden Ihre CAN unten rechts auf der Vorderseite Ihres Ausweises. + The input does not match. Please choose a new Smart-eID PIN. + ALL_PLATFORMS Error message if the new pin confirmation mismatches. + Die Eingaben stimmen nicht überein. Bitte wählen Sie eine neue Smart-eID-PIN. - You have entered an incorrect, five-digit Transport PIN thrice, your Transport PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Sie haben dreimal eine falsche, fünfstellige Transport-PIN eingegeben, Ihre Transport-PIN ist nun gesperrt. Um die Sperre aufzuheben, muss zunächst die zehnstellige PUK eingegeben werden. + The input does not match. Please choose a new ID card PIN. + Die Eingaben stimmen nicht überein. Bitte wählen Sie eine neue Karten-PIN. - You have entered an incorrect, six-digit Smart-eID PIN thrice. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. - INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. - Sie haben dreimal eine falsche, sechsstellige Smart-eID-PIN eingegeben. Ihre Smart-eID ist nun ungültig. Um die Smart-eID erneut nutzen zu können, müssen Sie erneut die Einrichtung auf der Startseite durchführen. + You have entered an incorrect, 6-digit ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 1/2 + Sie haben eine falsche 6-stellige Karten-PIN eingegeben. + + + You have <b>2 further attempts</b> to enter the correct ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 2/2 + Sie haben <b>2 weitere Versuche</b>, die richtige Karten-PIN einzugegeben. + + + You have entered an <b>incorrect, 6-digit ID card PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Sie haben zum <b>2. Mal eine falsche 6-stellige Karten-PIN</b> eingegeben. + + + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN in the <b>bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 +---------- +INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 + Für den 3. Versuch muss zunächst die <b>6-stellige Zugangsnummer (CAN)</b> eingegeben werden. Sie finden Ihre CAN <b>unten rechts auf der Vorderseite Ihres Ausweises</b>. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Sie haben dreimal eine falsche, sechsstellige Karten-PIN eingegeben, Ihre Karten-PIN ist nun gesperrt. Um die Sperre aufzuheben, muss zunächst die zehnstellige PUK eingegeben werden. + You have entered an incorrect, 6-digit ID card PIN 3 times. Your <b>ID card PIN is now blocked</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 1/2 + Sie haben 3-mal eine falsche, 6-stellige Karten-PIN eingegeben. Ihre <b>Karten-PIN ist nun gesperrt</b>. - You have entered an incorrect, six-digit Card Access Number (CAN). Please try again. + To remove the block, the <b>10-digit PUK</b> must be entered first. You can find the PUK in the bottom <b>right next</b> to the Transport PIN in the <b>authority's letter</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 2/2 + Um die Sperre aufzuheben, muss zunächst die <b>10-stellige PUK</b> eingegeben werden. Sie finden die PUK <b>im Brief der Ausweisbehörde unten rechts</b> neben der Transport-PIN. + + + You have entered an <b>incorrect Card Access Number (CAN)</b>. Please try again. You can find your CAN in the <b>bottom right on the front of your ID card</b>. INFO ALL_PLATFORMS The CAN was entered wrongfully and needs to be supplied again. - Sie haben eine falsche, sechsstellige Zugangsnummer (CAN) eingegeben. Bitte versuchen Sie es erneut. + Sie haben eine <b>falsche Zugangsnummer (CAN)</b> eingegeben. Bitte versuchen Sie es erneut. Sie finden Ihre CAN <b>unten rechts auf der Vorderseite Ihres Ausweises</b>. - You have entered an incorrect, ten-digit PUK. Please try again. - INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. - Sie haben einen falschen, zehnstelligen PUK eingegeben. Bitte versuchen Sie es erneut. + You have entered an incorrect, 5-digit Transport PIN. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. Part 1/2 + Sie haben eine falsche, 5-stellige Transport-PIN eingegeben. - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a third wrong attempt could invalidate the Smart-eID. - Sie haben zweimal eine falsche, sechsstellige Smart-eID-PIN eingegeben. Nach dem nächsten Fehlversuch können Sie Ihre Smart-eID nicht mehr einsetzen und müssen diese neu einrichten. + You have <b>2 further attempts</b> to enter the correct Transport PIN. The 5-digit Transport PIN may be found on the <b>bottom left of your PIN letter</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt.Part 2/2 + Sie haben <b>2 weitere Versuche</b>, die korrekte Transport-PIN einzugeben. Die 5-stellige Transport-PIN befindet sich <b>unten links in Ihrem PIN-Brief</b>. - The input does not match. Please choose a new Smart-eID PIN. - ALL_PLATFORMS Error message if the new pin confirmation mismatches. - Die Eingaben stimmen nicht überein. Bitte wählen Sie eine neue Smart-eID-PIN. + You have entered an <b>incorrect, 5-digit Transport PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Sie haben <b>2-mal eine falsche, 5-stellige Transport-PIN</b> eingegeben. - The input does not match. Please choose a new ID card PIN. - Die Eingaben stimmen nicht überein. Bitte wählen Sie eine neue Karten-PIN. + <b>An incorrect PIN has been entered 2 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 1/2 + Bei der letzten Nutzung ihres Online-Ausweises wurde <b>2-mal eine falsche Karten-PIN</b> eingegeben. + + + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN <b>in the bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 2/2 + Für einen 3. Versuch muss die <b>6-stellige Zugangsnummer (CAN)</b> eingeben werden. Sie finden die CAN <b>unten rechts auf der Vorderseite Ihres Ausweises</b>. + + + <b>An incorrect PIN has been entered 3 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 1/2 + Bei der letzten Nutzung ihres Online-Ausweises wurde <b>3-mal eine falsche Karten-PIN</b> eingegeben. + + + Therefor you have to enter the <b>PUK</b> first to <b>unlock the ID card PIN</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 2/2 + Deshalb müssen Sie zunächst die <b>PUK</b> eingeben um die <b>Karten-PIN zu entsperren</b>. governikus::PinResetInformationModel - - https://www.personalausweisportal.de/EN - https://www.personalausweisportal.de/DE - You cannot use the PUK to reset your previously set card PIN. If you forgot your card PIN, you can use the PIN Reset Service to request a new PIN. LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. @@ -5682,19 +6046,70 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au Zum PIN-Rücksetzdienst - You can request activation of the eID function without charge. + Go to Activation Service + LABEL ALL_PLATFORMS + Zum Aktivierungsdienst + + + You may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK +---------- +LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Bei Ihrer zuständigen Ausweisbehörde können Sie eine neue PIN setzen. + + + Please contact the competent authority to activate the eID function. LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated - Sie können die Aktivierung der Online-Ausweisfunktion kostenlos anfordern. + Bei Ihrer zuständigen Ausweisbehörde können Sie die Online-Ausweisfunktion aktivieren. - Go to Activation Service + Find competent authority LABEL ALL_PLATFORMS - Zum Aktivierungsdienst + Ausweisbehörde finden + + + If you don't have your Transport PIN letter and no access to the PUK, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. + Wenn Ihnen der Brief mit Transport-PIN und PUK nicht vorliegt, können Sie bei Ihrer zuständigen Ausweisbehörde eine neue Karten-PIN setzen. + + + If you know neither your Transport PIN nor your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Wenn Sie weder Ihre Transport-PIN, noch Ihre Karten-PIN kennen, können Sie bei Ihrer zuständigen Ausweisbehörde eine neue Karten-PIN setzen. + + + If you cannot recall your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Wenn Sie Ihre Karten-PIN nicht kennen, können Sie bei Ihrer zuständigen Ausweisbehörde eine neue Karten-PIN setzen. + + + To find your competent authority you may visit servicesuche.bund.de. + Ihre zuständige Behörde finden Sie beispielsweise unter servicesuche.bund.de. - Request a new card PIN free of charge to be able to use the eID function again. + Request a new card PIN to be able to use the eID function again. LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK - Fordern Sie kostenlos eine neue Karten-PIN an, um die Online-Ausweisfunktion wieder nutzen zu können. + Fordern Sie eine neue Karten-PIN an, um die Online-Ausweisfunktion wieder nutzen zu können. + + + You can request activation of the eID function. + LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + Sie können die Aktivierung der Online-Ausweisfunktion anfordern. + + + You can use the PIN Reset Service to request a new card PIN. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Dann fordern Sie jetzt mithilfe des PIN-Rücksetzdienstes eine neue Karten-PIN an. + + + If you do not know either your Transport PIN or your card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Wenn Ihnen weder Ihre Transport-PIN noch Ihre Karten-PIN bekannt ist, können Sie mit dem PIN-Rücksetzdienst eine neue PIN anfordern. + + + If you have forgotten your ID card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Wenn Sie Ihre Karten-PIN vergessen haben, können Sie mit dem PIN-Rücksetzdienst eine neue PIN anfordern. @@ -5807,6 +6222,11 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au LABEL ALL_PLATFORMS Klicken zum Koppeln + + was + LABEL ALL_PLATFORMS Describes the former name of the device and is shown as: "New_Name (was Old_Name)" + ehem. + governikus::RemoteServiceModel @@ -5823,15 +6243,6 @@ Um fortzufahren, verwenden Sie Ihren Ausweis, indem Sie die NFC-Schnittstelle au The NFC radio standard is required for communication with the ID card. -Unfortunately NFC is not available on your device. - INFO ALL_PLATFORMS The device does not offer NFC. - Für die Kommunikation mit dem Ausweis wird der Funkstandard NFC benötigt. - -Dieser ist auf Ihrem Gerät leider nicht verfügbar. - - - The NFC radio standard is required for communication with the ID card. - Please enable NFC to use your smartphone as a card reader (SaC). INFO ALL_PLATFORMS NFC is available but not active. Für die Kommunikation mit dem Ausweis wird der Funkstandard NFC benötigt. @@ -5839,9 +6250,19 @@ Please enable NFC to use your smartphone as a card reader (SaC). Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu können. - Pairing with %1 successful. - LABEL ALL_PLATFORMS - Die Kopplung mit %1 war erfolgreich. + This device cannot be used to read your ID card. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + Dieses Gerät kann nicht zum Auslesen des Ausweises verwendet werden. + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + Möchten Sie die Online-Ausweisfunktion auf diesem Gerät nutzen, können Sie ein NFC-fähiges Smartphone als Kartenleser koppeln. + + + To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + Öffnen Sie dafür das Menü <b>Einstellungen</b> und wählen <b>Kopplungen verwalten</b>. @@ -5871,7 +6292,9 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k xx.MM.yyyy - LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day + LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day +---------- +LABEL ALL_PLATFORMS Additional date format with unknown day xx.MM.yyyy @@ -6036,11 +6459,6 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k governikus::StateConnectCard - - The used card reader does not meet the technical requirements (Extended Length not supported). - INFO IOS - Der verwendete Kartenleser erfüllt leider nicht die technischen Voraussetzungen (Extended Length wird nicht unterstützt). - The used ID card type is not accepted by the server. INFO IOS @@ -6173,7 +6591,7 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k - governikus::SurveyModel + governikus::Survey Vendor Hersteller @@ -6230,21 +6648,21 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k - governikus::UIPlugInProxy + governikus::UiPluginProxy Reverse proxy plugin is enabled Reverse-Proxy-Plugin ist aktiviert - governikus::UIPlugInQml + governikus::UiPluginQml Information Information - governikus::UIPlugInWebService + governikus::UiPluginWebService An unknown program uses the required port (%1). Please exit the other program and try again! ERROR ALL_PLATFORMS An unknown programme is using the local port on which the AA2 listens. @@ -6320,9 +6738,9 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k Jetzt melden - The connection to the browser was lost. No forwarding was executed. Please try to call the URL again manually: %1 + The connection to the browser was lost while redirecting to the provider (%1). No automatic redirection could be performed. ERROR ALL_PLATFORMS The connection to the browser was lost/timed out.. - Die Verbindung zum Browser ging verloren. Es konnte keine Weiterleitung durchgeführt werden. Bitte versuchen Sie, die URL manuell aufzurufen: %1 + Bei der Weiterleitung zum Anbieter (%1) ging die Verbindung zum Browser verloren. Es konnte keine automatische Weiterleitung erfolgen. @@ -6360,87 +6778,10 @@ Bitte aktivieren Sie NFC, um Ihr Smartphone als Kartenleser (SaK) benutzen zu k LABEL ANDROID IOS The text on the redirect button that appears when the user tried to use an unusable Smart-eID Zum Smart-eID Menü - - - main - - Another application uses %1 - INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. - Eine andere Anwendung verwendet %1 - - - The user interface of the %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. - Die Benutzeroberfläche der %1 wird geschlossen. - - - The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. - Das Programm steht weiterhin im Infobereich zur Verfügung. Klicken Sie auf das Symbol der %1, um die Anwendung wieder zu öffnen. - - - Do not show this dialog again. - LABEL DESKTOP - Diesen Hinweis nicht mehr anzeigen. - - - This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. - Hiermit wird der aktuelle Vorgang abgebrochen und die Benutzeroberfläche der %1 geschlossen. Sie können den Vorgang jederzeit erneut starten. - - - Abort operation - INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active - Vorgang abbrechen - - - Failed to retrieve update information. - INFO DESKTOP Message that the update data is invalid and can't be used. - Das Herunterladen der Aktualisierungsinformationen ist fehlgeschlagen. - - - An update is available (version %1). - INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. - Eine Aktualisierung ist verfügbar (Version %1). - - - Developer Mode: Enabled! - LABEL DESKTOP - Entwicklermodus: Aktiviert! - - - Disable - LABEL DESKTOP Global button to disable developer mode. - Deaktivieren - - - Detached log viewer - Protokollbetrachter - - - To close the app, quickly press the back button twice. - INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). - Um die Anwendung zu schließen, drücken Sie zweimal schnell die Zurück-Taste. - - - The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. - Das Programm steht weiterhin in der Menüleiste zur Verfügung. Klicken Sie auf das Symbol der %1, um die Anwendung wieder zu öffnen. - - - The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. - INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. - Die %1 wird beendet und steht nicht länger für eine Authentisierung zur Verfügung. Sie müssen die %1 erneut starten, um sich gegenüber Dienstanbietern auszuweisen. - - The %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. - Die %1 wird beendet. - - - This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. - INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. - Hierdurch wird der aktuelle Vorgang abgebrochen und die %1 beendet. Sie müssen die %1 erneut starten, um den Vorgang neuzustarten. + Set a new PIN + LABEL ALL_PLATFORMS Hint title to assist the user on how to set a new PIN + Neue PIN setzen diff --git a/resources/translations/ausweisapp2_ru.ts b/resources/translations/ausweisapp_ru.ts similarity index 76% rename from resources/translations/ausweisapp2_ru.ts rename to resources/translations/ausweisapp_ru.ts index c57b7de54..924b826c1 100644 --- a/resources/translations/ausweisapp2_ru.ts +++ b/resources/translations/ausweisapp_ru.ts @@ -4,8 +4,14 @@ DvcsAttributes - revision - 56dc58807a8c + 828ae9a4549a + revision + 828ae9a4549a + + + 2.2.0 + version + 2.2.0 @@ -26,6 +32,88 @@ Обнаружены проблемы в сети, в течение 30 секунд выполняется подключение к серверу. + + App + + The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. + Программа по-прежнему доступна через значок в строке меню. Нажмите на символ %1, чтобы снова открыть пользовательский интерфейс. + + + The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. + Программа по-прежнему доступна через значок на панели задач. Нажмите на символ %1, чтобы снова открыть пользовательский интерфейс. + + + Another application uses %1 + INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. + Другое приложение использует %1 + + + The user interface of the %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. + Пользовательский интерфейс %1 закрыт. + + + Do not show this dialog again. + LABEL DESKTOP + Не показывать этот диалог снова. + + + The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. + INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. + %1 будет закрыто, и аутентификация больше не будет возможна. Вам нужно будет перезапустить %1, чтобы идентифицировать себя у провайдеров. + + + The %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. + %1 закрыто. + + + This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. + Текущий процесс будет прерван, а пользовательский интерфейс %1 скрыт. Вы можете перезапустить процесс в любое время. + + + This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. + INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. + Текущая операция будет отменена, и %1 будет остановлено. Чтобы снова начать операцию, вам нужно будет перезапустить %1. + + + Abort operation + INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active + Отмена операции + + + Failed to retrieve update information. + INFO DESKTOP Message that the update data is invalid and can't be used. + Сбой загрузки информации об обновлении. + + + An update is available (version %1). + INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. + Доступно обновление (версия %1). + + + Developer Mode: Enabled! + LABEL DESKTOP + Режим разработчика: активирован! + + + Disable + LABEL DESKTOP Global button to disable developer mode. + Деактивировать + + + Detached log viewer + Средство просмотра файлов журнала + + + To close the app, press the back button 2 times. + INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). + Чтобы закрыть приложение, два раза нажмите кнопку «Назад». + + AuthController @@ -64,8 +152,8 @@ Учитывайте указания на дисплее устройства чтения карт. - A wrong PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO ANDROID IOS The PIN was entered wrongfully two times, the third attempts requires additional CAN verification, hint where the CAN is found. + A wrong PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + INFO ANDROID IOS The PIN was entered wrongfully two times, the 3rd attempts requires additional CAN verification, hint where the CAN is found. Дважды введен неправильный PIN-код идентификационной карты. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. @@ -78,6 +166,16 @@ LABEL ANDROID IOS A11y button to confirm the PIN and start the provider authentication Аутентификация с помощью провайдера + + Authentication failed + LABEL ANDROID IOS + Сбой аутентификации + + + Return to provider + LABEL ANDROID IOS + Вернуться к провайдеру + AuthView @@ -104,19 +202,19 @@ LABEL ANDROID IOS - remove the mobile phone case (if present) - connect the smartphone with a charging cable INFO DESKTOP A weak NFC signal was detected since the card communication was aborted. The card's position needs to be adjusted to hopefully achieve better signal strength. - Слабый сигнал NFC. Выполните следующее. -— Измените положение карты. -— Снимите чехол с мобильного телефона (при наличии). -— Подключите смартфон к зарядному кабелю. + Слабый сигнал NFC. Выполните следующее: +- Измените положение карты +- Снимите чехол с мобильного телефона (при наличии) +- Подключите смартфон к зарядному кабелю Weak NFC signal. Please - make sure the card is positioned correctly on the reader - do note move the card while it is being accessed INFO DESKTOP The NFC signal is weak or unstable, while using a stationary card reader. - Слабый сигнал NFC. Выполните следующее. -— Убедитесь в том, что карта правильно вставлена в устройство чтения карт. -— Не перемещайте карту, пока система получает к ней доступ. + Слабый сигнал NFC. Выполните следующее: +- Убедитесь в том, что карта правильно вставлена в устройство чтения карт +- Не перемещайте карту, пока система получает к ней доступ Aborting process and informing the service provider @@ -163,12 +261,12 @@ INFO DESKTOP Generic progress status message during authentication.Аутентификация с помощью провайдера - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. Онлайн-идентификация с помощью временного PIN-кода невозможна. Для использования функции eID необходим 6-значный PIN-код идентификационной карты, который пользователь создает самостоятельно. - Do you know your six-digit ID card PIN? - Вы знаете 6-значный PIN-код идентификационной карты? + Do you know your 6-digit ID card PIN? + Вы знаете 6-значный PIN-код своей идентификационной карты? The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. @@ -266,17 +364,18 @@ INFO DESKTOP Generic progress status message during authentication. INFO ANDROID IOS The NFC signal is weak, by repositioning the card the signal might improve. - Слабый сигнал NFC. Выполните следующее. -— Измените положение карты. -— Снимите чехол с мобильного телефона (при наличии). -— Подключите смартфон к зарядному кабелю. + Слабый сигнал NFC. Выполните следующее: +— Измените положение карты +— Снимите чехол с мобильного телефона (при наличии) +— Подключите смартфон к зарядному кабелю CardReaderDelegate - Press space to open the link in your browser - Нажмите на пробел, чтобы открыть ссылку в браузере + Press space to open link. + INFO DESKTOP Text read by screen reader if the text contains a web link to a card reader driver which may be opened. + Нажмите на пробел, чтобы открыть ссылку в браузере. @@ -300,7 +399,11 @@ INFO DESKTOP Generic progress status message during authentication. No connected card reader found. - + Подключенные устройства чтения карт не найдены. + + + List of connected card readers. + Перечень подключенных устройств чтения карт. @@ -315,11 +418,6 @@ LABEL ANDROID IOS ChangePinController - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO ANDROID IOS The ID card has just been unblocked and the user can now continue with their PIN change. - PIN-код вашей карты разблокирован. У вас есть три попытки изменить PIN-код. - Setting new Smart-eID PIN LABEL ANDROID IOS Processing screen label while the card communication is running after the new Smart-eID PIN has been entered during PIN change process. @@ -356,19 +454,19 @@ LABEL ANDROID IOS Учитывайте указания на дисплее устройства чтения карт. - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + A wrong ID card PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. INFO ANDROID IOS The wrong ID card PIN was entered twice, the next attempt requires additional verifcation via CAN. - Дважды введен неправильный PIN-код вашей идентификационной карты. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. + Дважды введен неправильный PIN-код идентификационной карты. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. + You have entered an incorrect, 6-digit ID card PIN 3 times, your ID card PIN is now blocked. To remove the block, the 10-digit PUK must be entered first. INFO ANDROID IOS The ID card PIN (including the CAN) was entered wrongfully three times, the PUK is required to unlock the ID card. - Вы трижды ввели неправильный 6-значный PIN-код идентификационной карты, PIN-код идентификационной карты заблокирован. Для разблокировки введите 10-значный PUK-код. + Вы трижды ввели неправильный 6-значный PIN-код идентификационной карты; PIN-код идентификационной карты заблокирован. Для разблокирования сначала введите 10-значный PUK-код. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO ANDROID IOS - Внимание: вы можете использовать 5-значный временный PIN-код только один раз — для смены 6-значного PIN-кода. Если вы уже установили 6-значный PIN-код, 5-значный временный PIN-код больше не действует. + Back to start page + LABEL ANDROID IOS + Назад к начальной странице @@ -392,35 +490,25 @@ LABEL ANDROID IOS INFO DESKTOP Processing screen text while the card communication is running after the PIN has been entered during PIN change process. Не перемещайте идентификационную карту. - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO DESKTOP The ID card has just been unblocked and the user can now continue with their ID card PIN change. - PIN-код вашей карты разблокирован. У вас есть три попытки изменить PIN-код. - Weak NFC signal. Please - change the card position - remove the mobile phone case (if present) - connect the smartphone with a charging cable INFO DESKTOP The NFC signal is weak or unstable, the user is asked to change the card's position to (hopefully) reduce the distance to the NFC chip. - Слабый сигнал NFC. Выполните следующее. + Слабый сигнал NFC. Выполните следующее: — Измените положение карты. -— Снимите чехол с мобильного телефона (при наличии). -— Подключите смартфон к зарядному кабелю. +— Снимите чехол с мобильного телефона (при наличии) +— Подключите смартфон к зарядному кабелю Weak NFC signal. Please - make sure the card is positioned correctly on the reader - do note move the card while it is being accessed INFO DESKTOP The NFC signal is weak or unstable, while using a stationary card reader. - Слабый сигнал NFC. Выполните следующее. -— Убедитесь в том, что карта правильно вставлена в устройство чтения карт. -— Не перемещайте карту, пока система получает к ней доступ. - - - Change Transport PIN - LABEL ANDROID IOS - Изменить временный PIN-код + Слабый сигнал NFC. Выполните следующее: +— Убедитесь в том, что карта правильно вставлена в устройство чтения карт +— Не перемещайте карту, пока система получает к ней доступ The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. @@ -428,9 +516,9 @@ LABEL ANDROID IOS Сопряжение устройства «%1» не было выполнено, поскольку оно не отвечало на попытки соединения. Снова выполните сопряжение устройства для его использования в качестве устройства чтения карт. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO DESKTOP - Внимание: вы можете использовать 5-значный временный PIN-код только один раз — для смены 6-значного PIN-кода. Если вы уже установили 6-значный PIN-код, 5-значный временный PIN-код больше не действует. + Back to start page + LABEL DESKTOP + Назад к начальной странице @@ -441,24 +529,24 @@ LABEL ANDROID IOS Какой у вас PIN-код? - Six-digit PIN + 6-digit PIN LABEL ALL_PLATFORMS 6-значный PIN-код - Set by yourself + Set by yourself or received by the PIN Reset Service LABEL ALL_PLATFORMS - Создается пользователем самостоятельно + Создается пользователем самостоятельно - Five-digit Transport PIN + 5-digit Transport PIN LABEL ALL_PLATFORMS 5-значный временный PIN-код - Received by mail in PIN letter + Received by letter while ordering your ID card LABEL ALL_PLATFORMS - Получен по почте в письме с PIN-кодом + Получен по почте в письме с PIN-кодом No PIN @@ -560,16 +648,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Успешный доступ к идентификационной карте - - Online identification feature disabled - LABEL ANDROID IOS - Функция онлайн-идентификации деактивирована - - - Online identification feature enabled - LABEL ANDROID IOS - Функция онлайн-идентификации активирована - ID card PIN suspended LABEL ANDROID IOS @@ -585,6 +663,16 @@ LABEL ANDROID IOS LABEL ANDROID IOS Идентификационная карта готова к использованию + + eID function disabled + LABEL ANDROID IOS + Функция онлайн-идентификации деактивирована + + + eID function enabled + LABEL ANDROID IOS + Функция онлайн-идентификации активирована + CheckIDCardSuggestionView @@ -599,9 +687,9 @@ LABEL ANDROID IOS NFC отсутствует - Your mobile device has no NFC interface. This is required to read the ID card. However, you can use a separate smartphone as card reader to utilize the eID function.<br><br>You can find smartphones compatible with the %1 on our website. + Your mobile device has no NFC interface. This is required to read the ID card. To use the eID function on this device you may pair a NFC capable smartphone as a card reader.<br><br>To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>.<br><br>You can find smartphones compatible with the %1 on our website. LABEL ANDROID IOS - В вашем мобильном устройстве нет интерфейса NFC. Он требуется для считывания идентификационной карты. Вы можете воспользоваться функцией eID на другом смартфоне, используемом в качестве устройства чтения карт.<br><br>Список совместимых с %1 смартфонов см. на нашем сайте. + В вашем мобильном устройстве нет интерфейса NFC. Он требуется для считывания идентификационной карты. Вы можете воспользоваться функцией eID на другом смартфоне, используемом в качестве устройства чтения карт.<br><br>Список совместимых с %1 смартфонов см. на нашем сайте. Open website @@ -613,11 +701,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Поддерживаемые карты не обнаружены - - No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check.<br><br>Tip: Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. - LABEL ANDROID IOS - Поддерживаемые идентификационные карты не обнаружены. %1 поддерживает:<p><ul><li>идентификационные карты Германии;</li><li>электронные разрешения на временное пребывание (РВП);</li><li>карты eID.</li></ul></p>Если вы используете один из перечисленных документов, но данное сообщение об ошибке все равно появляется, перезапустите проверку.<br><br>Совет: попробуйте изменить положение карты; убедитесь в том, что идентификационная карта не смещается во время проверки и рядом с устройством нет других карт с NFC (например, банковских карт). - Retry LABEL ANDROID IOS @@ -643,11 +726,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Не удалось установить стабильное соединение с вашей идентификационной картой.<br><br>Перезапустите проверку. Попробуйте изменить положение карты и убедитесь в том, что карта не смещается во время проверки.<br><br>Если невозможно установить соединение с идентификационной картой в разных положениях, то это значит, что интерфейс NFC вашего мобильного устройства не подает достаточно тока на идентификационную карту.<br><br>Список совместимых с %1 смартфонов см. на нашем <a href="%2">сайте</a>. - - Online identification feature disabled - LABEL ANDROID IOS - Функция онлайн-идентификации деактивирована - OK LABEL ANDROID IOS @@ -659,9 +737,9 @@ LABEL ANDROID IOS Действие PIN-кода идентификационной карты приостановлено - The ID card PIN has been entered incorrectly twice in a row. This is why you must first enter the six-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. + The ID card PIN has been entered incorrectly 2 times in a row. This is why you must first enter the 6-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. LABEL ANDROID IOS - PIN-код идентификационной карты введен неправильно два раза подряд. Поэтому перед следующей попыткой идентификации необходимо ввести 6-значный код доступа (CAN). Он указан внизу справа на передней стороне вашей идентификационной карты.<br><br>Проверьте функцию: «Просмотреть персональные данные». Вы также можете использовать код CAN для разблокировки PIN-кода идентификационной карты. + PIN-код идентификационной карты введен неправильно два раза подряд. Поэтому перед следующей попыткой идентификации сначала необходимо ввести 6-значный код доступа (CAN). Он расположен внизу справа на передней стороне идентификационной карты.<br><br>Теперь проверьте работу функции. «Просмотреть персональные данные». Вы также можете использовать код CAN для разблокировки PIN-кода идентификационной карты. Continue @@ -674,9 +752,34 @@ LABEL ANDROID IOS PIN-код идентификационной карты заблокирован - The ID card PIN has been entered incorrectly thrice. Therefore, you must first enter the ten-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + The ID card PIN has been entered incorrectly 3 times. Therefore, you must first enter the 10-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + LABEL ANDROID IOS + PIN-код идентификационной карты введен неправильно трижды. Поэтому в следующем процессе аутентификации сначала необходимо ввести 10-значный PUK-код. Он указан в письме с PIN-кодом, которое вы получили после заказа идентификационной карты.<br><br>Теперь проверьте работу функции. «Просмотреть персональные данные». Подготовьте PUK-код для разблокировки PIN-кода идентификационной карты. + + + Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. + LABEL ANDROID IOS + попробуйте изменить положение карты; убедитесь в том, что идентификационная карта не смещается во время проверки и рядом с устройством нет других карт с NFC (например, банковских карт). + + + No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards for citizen of the EU/EEA/</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check. + LABEL ANDROID IOS + Поддерживаемые идентификационные карты не обнаружены. %1 поддерживает:<p><ul><li>идентификационные карты Германии;</li><li>электронные разрешения на временное пребывание (eAT);</li><li>карты eID для граждан ЕС/ЕЭП.</li></ul></p>Если вы используете один из перечисленных документов, но данное сообщение об ошибке все равно появляется, перезапустите проверку. + + + eID function disabled + LABEL ANDROID IOS + Функция онлайн-идентификации деактивирована + + + Activate the eID function. + LABEL ANDROID IOS Hint when a workflow failed because the eID function was not activated + Активируйте функцию онлайн-идентификации. + + + List of compatible devices LABEL ANDROID IOS - PIN-код идентификационной карты введен неправильно трижды. Поэтому при следующем процессе аутентификации сначала необходимо ввести 10-значный PUK-код. Он указан в письме с PIN-кодом, которое вы получили после заказа идентификационной карты.<br><br>Проверьте функцию: «Просмотреть персональные данные». Подготовьте PUK-код для разблокировки PIN-кода идентификационной карты. + @@ -692,9 +795,9 @@ LABEL ANDROID IOS Для использования функции онлайн-идентификации ваше устройство должно соответствовать определенным техническим требованиям. Также необходимо активировать функцию онлайн-идентификации. - Check if your smartphone and ID card are ready for use. + Check if your device & ID card are ready for use LABEL ANDROID IOS - Убедитесь в том, что смартфон и идентификационная карта готовы к использованию. + Убедитесь в том, что устройство и идентификационная карта готовы к использованию Start check @@ -725,92 +828,92 @@ LABEL ANDROID IOS Unknown result code: %1 LABEL ANDROID IOS - Неизвестный код результата: %1 + Неизвестный код результата: %1 Please wait a moment. LABEL ANDROID IOS - Подождите. + Подождите. Updating Smart-eID status... LABEL ANDROID IOS - Обновление статуса Smart-eID… + Обновление статуса Smart-eID… Check device and ID card LABEL ANDROID IOS - Проверить устройство и идентификационную карту + Проверить устройство и идентификационную карту Your mobile device does not meet the technical requirements for Smart-eID.<br><br>You may check if your device and ID card are suitable to use the eID function. LABEL ANDROID IOS - Ваше мобильное устройство не соответствует техническим требованиям для Smart-eID.<br><br>Вы можете проверить пригодность вашего устройства и идентификационной карты для использования функции eID. + Ваше мобильное устройство не соответствует техническим требованиям для Smart-eID.<br><br>Вы можете проверить пригодность своего устройства и идентификационной карты для использования функции eID. Smart-eID not supported LABEL ANDROID IOS - Smart-eID не поддерживается + Smart-eID не поддерживается Possible causes are: LABEL ANDROID IOS - Возможные причины + Возможные причины: The setup has not been completed. LABEL ANDROID IOS - Создание не завершено. + Создание не завершено. - The Smart-eID PIN has been entered incorrectly three times. + The Smart-eID PIN has been entered incorrectly 3 times. LABEL ANDROID IOS - PIN-код для Smart-eID трижды введен неправильно. + PIN-код для Smart-eID введен неправильно трижды. The %1 has been uninstalled temporarily. LABEL ANDROID IOS - Приложение %1 удалено. + %1 временно удалено. You may continue with the setup of the Smart-eID. LABEL ANDROID IOS - + Вы можете продолжить настройку Smart-eID. Continue LABEL ANDROID IOS - Продолжить + Продолжить Your device meets the technical requirements for Smart-eID. You may now continue the setup process. LABEL ANDROID IOS - + Ваше устройство соответствует техническим требованиям для Smart-eID. Теперь можно продолжить процесс настройки. Smart-eID supported LABEL ANDROID IOS - + Электронная идентификационная карта Smart-eID не поддерживается Your device meets the technical requirements for Smart-eID, however, the Smart-eID that was set up is invalid. LABEL ANDROID IOS LABEL ANDROID IOS - + Ваше устройство соответствует техническим требованиям для Smart-eID, однако созданная электронная идентификационная карта Smart-eID недействительна. Smart-eID invalid LABEL ANDROID IOS - + Электронная идентификационная карта Smart-eID недействительна Smart-eID check failed LABEL ANDROID IOS - + Сбой проверки Smart-eID Back LABEL ANDROID IOS - Назад + Назад @@ -825,54 +928,55 @@ LABEL ANDROID IOS LABEL DESKTOP Сопряжение устройства… - - Pairing to "%1" failed: - ERROR DESKTOP An error occurred while pairing the device. - Сбой сопряжения «%1»: - DarkModeButtons System LABEL ALL_PLATFORMS - Система + Система Dark LABEL ALL_PLATFORMS - + Темная тема Light LABEL ALL_PLATFORMS - + Светлая тема Set the app appearance to system mode LABEL ALL_PLATFORMS - + Установить для приложения тему в зависимости от режима системы Set the app appearance to dark mode LABEL ALL_PLATFORMS - + Установить для приложения темную тему Set the app appearance to light mode LABEL ALL_PLATFORMS - + Установить для приложения светлую тему DataGroup - selected - выбрано + %1, optional right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + - not selected - не выбрано + %1, required right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + @@ -905,12 +1009,12 @@ LABEL ANDROID IOS Reset hideable dialogs LABEL DESKTOP - + Сбросить скрываемые диалоговые окна Show Transport PIN reminder, store feedback and close reminder dialogs. LABEL DESKTOP - + Показывать напоминание временного PIN-кода, сохранять обратную связь и закрывать диалоговые окна с напоминаниями. @@ -930,11 +1034,13 @@ LABEL ANDROID IOS DetachedLogView Select log: + LABEL DESKTOP Выбрать файл журнала: - Font size: - Размер шрифта: + Zoom: + LABEL DESKTOP + Изменение масштаба изображения: Save log @@ -1027,17 +1133,17 @@ LABEL ANDROID IOS Allow test sample card usage LABEL DESKTOP - + Разрешить использование тестовой карты Internal card simulator LABEL DESKTOP - Внутренний симулятор карт + Внутренний симулятор карт The developer mode deactivates some security checks and the authentication process will continue even if some errors occur. Skipped errors will be shown as notifications. The developer mode is only usable with the test PKI. LABEL DESKTOP - Режим разработчика предназначен для интеграторов/разработчиков новых сервисных приложений. Поэтому режим разработчика функционирует только в тестовой ИОК. При активации режима разработчика некоторые проверки безопасности деактивируются. При этом процесс аутентификации продолжается, хотя при использовании в стандартном режиме %1 обычно прерывает процесс с сообщением об ошибке. Проигнорированная ошибка в режиме разработчика отображается на дисплее в дополнительном окне под окном приложения %1. + Режим разработчика деактивирует некоторые проверки безопасности, и процесс аутентификации продолжается даже при возникновении ошибок. Пропущенные ошибки будут отображены как уведомления. Режим разработчика можно использовать только с тестовой ИОК. @@ -1072,20 +1178,20 @@ LABEL ANDROID IOS System data LABEL DESKTOP - Диагностика + Системные данные Save system data to textfile - Сохранить данные диагностики в текстовый файл + Сохранить системные данные в текстовый файл SystemData - Диагностика + Системные данные Save system data LABEL DESKTOP - Сохранить диагностику + Сохранить системные данные @@ -1116,14 +1222,14 @@ LABEL IOS_PHONE Inserted into "Proceed to %1 entry" LABEL DESKTOP ---------- LABEL IOS_PHONE ANDROID_PHONE - При вводе CAN вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты. + При вводе CAN вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты: By entering your PIN, access to the following data of your ID card will be allowed to the mentioned provider: LABEL DESKTOP ---------- LABEL IOS_PHONE ANDROID_PHONE - При вводе PIN-кода вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты. + При вводе PIN-кода вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты: Transactional information @@ -1167,283 +1273,191 @@ LABEL IOS_PHONE ANDROID_PHONE You are about to identify yourself towards the following provider: - LABEL DESKTOP ----------- -LABEL IOS_PHONE ANDROID_PHONE + LABEL IOS ANDROID Вы собираетесь пройти самоидентификацию для следующего провайдера: - - Provider - LABEL IOS_PHONE ANDROID_PHONE - Провайдер - - - Touch for more details - LABEL IOS_PHONE ANDROID_PHONE - Нажмите для получения подробной информации - EnterPasswordView - - Attempts - LABEL DESKTOP - Попытки - Enter CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести CAN Enter PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести PUK-код Enter pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести код сопряжения - Enter new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Ввести новый PIN-код идентификационной карты + Choose new ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Ввести новый PIN-код идентификационной карты Confirm new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Подтвердить новый PIN-код идентификационной карты Enter Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести временный PIN-код Enter ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести PIN-код идентификационной карты - Please enter the five-digit Transport PIN. - INFO DESKTOP The AA2 expects the Transport PIN with five digits. ----------- -INFO ANDROID IOS The Transport PIN is required by AA2, it needs to be change to an actual PIN. + Please enter the 5-digit Transport PIN. + INFO ALL_PLATFORMS The Transport PIN is required by AA, it needs to be change to an actual PIN. This is the description for the main text. Введите 5-значный временный PIN-код. - Please enter your current six-digit ID card PIN. - INFO DESKTOP The AA2 expects the current ID card PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current ID card PIN with six digits in a PIN change. + Please enter your current 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects the current ID card PIN with six digits in a PIN change. This is the description for the main text. Введите текущий 6-значный PIN-код идентификационной карты. - Please enter your six-digit ID card PIN. - INFO DESKTOP The AA2 expects a ID card PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a ID card PIN with six digits in an authentication. + Please enter your 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects a ID card PIN with six digits in an authentication. This is the description for the main text. Введите 6-значный PIN-код идентификационной карты. - Please enter the six-digit Card Access Number (CAN). You can find it in the bottom right on the front of the ID card. - INFO DESKTOP The user is required to enter the six-digit CAN in CAN-allowed authentication. ----------- -INFO ANDROID IOS The user is required to enter the six-digit CAN in CAN-allowed authentication. - Введите 6-значный код доступа (CAN). Он указан внизу справа на передней стороне идентификационной карты. - - - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO DESKTOP The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. ----------- -INFO ANDROID IOS The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. - Дважды введен неправильный PIN-код вашей идентификационной карты. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. - - - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO DESKTOP The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. ----------- -INFO ANDROID IOS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. - Вы трижды ввели неправильный 6-значный PIN-код идентификационной карты, PIN-код идентификационной карты заблокирован. Для разблокировки введите 10-значный PUK-код. - - - Please enter a new six-digit ID card PIN now. - INFO DESKTOP A new six-digit ID card PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit ID card PIN needs to be supplied. - Теперь введите новый 6-значный PIN-код идентификационной карты. - - - Please confirm your new six-digit ID card PIN. - INFO DESKTOP The new ID card PIN needs to be entered again for verification. ----------- -INFO ANDROID IOS The new ID card PIN needs to be confirmed. - Подтвердите новый 6-значный PIN-код идентификационной карты. + You will enter this 6-digit PIN every time you want to use your ID card online. + INFO ALL_PLATFORMS A new 6-digit ID card PIN needs to be supplied. This is the description for the main text. + Теперь введите новый 6-значный PIN-код идентификационной карты. - Unknown password type: - INFO DESKTOP Error message during PIN/CAN/PUK input procedure, the requested password type is unknown; internal error. - Неизвестный тип пароля: + The PIN is going to be tied to your ID card. It always stays the same regardless of the device you want to use your ID card with. + INFO ALL_PLATFORMS The new ID card PIN needs to be confirmed. This is the description for the main text. + Подтвердите новый 6-значный PIN-код идентификационной карты. - Do you have a five-digit Transport PIN? - LABEL ANDROID IOS Button to start a change of the Transport PIN. + Do you have a 5-digit Transport PIN? + LABEL ALL_PLATFORMS Button to start a change of the Transport PIN. У вас есть 5-значный временный PIN-код? Enter Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Ввести PIN-код для Smart-eID - Enter new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Ввести новый PIN-код для Smart-eID + Choose new Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Ввести новый PIN-код для Smart-eID Confirm new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Подтвердить новый PIN-код для Smart-eID - You have entered an incorrect, six-digit Smart-eID PIN twice. An incorrect third attempt will invalidate your Smart-eID and you will have to set it up again. - INFO DESKTOP The wrong Smart-eID PIN was entered twice on the Smart-eID - Вы дважды ввели неправильный 6-значный PIN-код для Smart-eID. При третьем неправильном вводе электронная идентификационная карта Smart-eID становится недействительной, ее необходимо создать повторно. - - - Please confirm your new six-digit Smart-eID PIN. - INFO DESKTOP The new Smart-eID PIN needs to be confirmed. ----------- -INFO ANDROID IOS The new Smart-eID PIN needs to be confirmed. - Подтвердите новый 6-значный PIN-код для Smart-eID. + You will enter this 6-digit PIN every time you want to use your Smart-eID. + INFO ALL_PLATFORMS A new 6-digit Smart-eID PIN needs to be supplied. This is the description for the main text. + Теперь введите новый 6-значный PIN-код для Smart-eID. - Please enter a new six-digit Smart-eID PIN now. - INFO DESKTOP A new six-digit Smart-eID PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit Smart-eID PIN needs to be supplied. - Теперь введите новый 6-значный PIN-код для Smart-eID. + The PIN is going to be tied to your Smart-eID. It always stays the same regardless of the service you want to use your Smart-eID with. + INFO ALL_PLATFORMS The new Smart-eID PIN needs to be confirmed. This is the description for the main text. + Подтвердите новый 6-значный PIN-код для Smart-eID. Enter the pairing code shown on the device you want to pair. - INFO ANDROID IOS The pairing code for the smartphone is required. + INFO MOBILE The pairing code for the smartphone is required. This is the description for the main text. Введите код сопряжения с устройства, которое вы хотите подключить. - Please enter your current six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects the current Smart-eID PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current Smart-eID PIN with six digits in a PIN change. + Please enter your current 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects the current Smart-eID PIN with six digits in a PIN change. This is the description for the main text. Введите текущий 6-значный PIN-код для Smart-eID. - Please enter your six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects a Smart-eID PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a Smart-eID PIN with six digits in an authentication. + Please enter your 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects a Smart-eID PIN with six digits in an authentication. This is the description for the main text. Введите 6-значный PIN-код для Smart-eID. - Do you have a six-digit ID card PIN? - LABEL ANDROID IOS Button to switch to a six-digit ID card PIN. + Do you have a 6-digit ID card PIN? + LABEL ALL_PLATFORMS Button to switch to a 6-digit ID card PIN. У вас есть 6-значный PIN-код идентификационной карты? - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice on the Smart-eID - + You have entered an incorrect, 6-digit Smart-eID PIN 2 times. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered twice on the Smart-eID + Вы дважды ввели неправильный 6-значный PIN-код для Smart-eID. После третьей попытки неправильного ввода вы больше не сможете использовать Smart-eID, и ее придется настроить еще раз. Send CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить CAN-код Send PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить PUK-код Send pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить код сопряжения Send new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить новый PIN-код идентификационной карты Send Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить временный PIN-код Send Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить PIN-код для Smart-eID Send new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить новый PIN-код для Smart-eID Send ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Отправить PIN-код идентификационной карты - Send confirmation of new ID card PIN - LABEL ANDROID IOS - + Enter the pairing code shown on your smartphone. + INFO DESKTOP The pairing code needs to be supplied. This is the description for the main text. + Введите указанный в смартфоне код сопряжения. - Send confirmation of new Smart-eID PIN - LABEL ANDROID IOS - + Please enter the CAN. You can find the CAN in the bottom right on the front of the ID card. + INFO ALL_PLATFORMS The user is required to enter the 6-digit CAN. This is the description for the main text. + Введите CAN. Вы найдете CAN в нижнем правом углу лицевой стороны идентификационной карты. - Enter the pairing code shown on your smartphone. - INFO DESKTOP The pairing code needs to be supplied. - Введите указанный в смартфоне код сопряжения. + Please enter your 10-digit PUK. + INFO ALL_PLATFORMS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. This is the description for the main text. + Введите 10-значный PUK-код. + + + Confirm ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Подтвердить новый PIN-код идентификационной карты + + + Confirm Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Подтвердить новый PIN-код для Smart-eID @@ -1451,17 +1465,17 @@ LABEL ANDROID IOS collapse LABEL ANDROID IOS - + Свернуть expand LABEL ANDROID IOS - + Развернуть Currently selected is %1 LABEL ANDROID IOS - + В настоящее время выбрано %1 @@ -1474,9 +1488,9 @@ LABEL ANDROID IOS GText - Press space to open link: %1 - INFO ALL_PLATFORMS Text read by screen reader if the text contains a weblink which may be opened. - Нажмите пробел, чтобы открыть ссылку: %1 + Press space to open link + INFO DESKTOP Text read by screen reader if the text contains a weblink which may be opened. + Нажмите пробел, чтобы открыть ссылку @@ -1488,11 +1502,6 @@ LABEL ANDROID IOS GeneralSettings - - Language selection - LABEL DESKTOP - Выбор языка - Behavior LABEL DESKTOP @@ -1521,41 +1530,66 @@ LABEL ANDROID IOS Appearance LABEL DESKTOP - + Внешний вид Use the system font LABEL DESKTOP - + Использовать системный шрифт Toggling will restart the %1 LABEL DESKTOP - + Переключение приведет к перезапуску %1 Close %1 after authentication LABEL DESKTOP - Закрытие после аутентификации + Закрыть %1 после аутентификации Show notifications inside of %1 LABEL DESKTOP - Включение внутренних оповещений + Показывать уведомления внутри %1 Auto-start %1 after boot and add a tray icon LABEL WINDOWS Text for auto-start option - Автозапуск %1 после загрузки + Автозапуск %1 после загрузки и добавление значка на панель задач + + + Change language + LABEL DESKTOP + Изменить язык + + + Use images instead of animations + LABEL DESKTOP + + + + Accessibility + LABEL DESKTOP + + + + Hide key animations when entering PIN + LABEL DESKTOP + - - - GeneralWorkflow - Attempts + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. LABEL DESKTOP - Попытки + + + Manual redirection back to the provider + LABEL DESKTOP + + + + + GeneralWorkflow Step %1 of 3 Шаг %1 из 3 @@ -1586,9 +1620,9 @@ LABEL ANDROID IOS Идентификационная карта не обнаружена. Убедитесь в том, что идентификационная карта размещена на устройстве чтения карт. - No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and available. Open the reader settings to configure readers and get more information about supported readers. + No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and ready. Open the reader settings to configure readers and get more information about supported readers. INFO DESKTOP AA2 is waiting for the card reader or the ID card. - Устройство чтения карт не обнаружено. Убедитесь в том, что USB-устройство чтения карт подключено или используемый в качестве устройства чтения карт смартфон сопряжен и доступен. Откройте настройки устройства чтения карт для конфигурирования устройств чтения карт и получения подробной информации о поддерживаемых устройствах чтения карт. + Устройство чтения карт не обнаружено. Убедитесь в том, что USB-устройство чтения карт подключено или используемый в качестве устройства чтения карт смартфон сопряжен и доступен. Откройте настройки устройства чтения карт для конфигурирования устройств чтения карт и получения подробной информации о поддерживаемых устройствах чтения карт. Please observe the display of your card reader. @@ -1603,22 +1637,106 @@ LABEL ANDROID IOS No ID card detected. Please follow the instructions on your smartphone (connected to %1) to use it as card reader. INFO DESKTOP The AA2 is waiting for the smartphone to be placed on the id. - + Идентификационная карта не обнаружена. Следуйте инструкциям в смартфоне (подключен к %1), чтобы использовать его в качестве устройства чтения карт. Please follow the instructions on your smartphone (connected to %1) or put the ID card on the card reader. INFO DESKTOP The AA2 is waiting for an ID card to be inserted into the card reader (or smartphone for that matter). - + Следуйте инструкциям в смартфоне (подключен к %1) или вставьте идентификационную карту в устройство чтения карт. + + + The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. + INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. + Сопряжение устройства "%1" не было выполнено, поскольку оно не отвечало на попытки соединения. Снова выполните сопряжение устройства для его использования в качестве устройства чтения карт. - Hint + InputErrorView - Hint - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Совет + Wrong CAN + LABEL ALL_PLATFORMS + Неправильный CAN-код + + + Wrong PUK + LABEL ALL_PLATFORMS + Неправильный PUK-код + + + Wrong Transport PIN + LABEL ALL_PLATFORMS + Неправильный временный PIN-код + + + Wrong Smart-eID PIN + LABEL ALL_PLATFORMS + Неправильный PIN-код для Smart-eID + + + Wrong ID card PIN + LABEL ALL_PLATFORMS + Неправильный PIN-код идентификационной карты + + + Wrong new ID card PIN confirmation + LABEL ALL_PLATFORMS + Неправильное подтверждение нового PIN-кода идентификационной карты + + + Wrong new Smart-eID PIN confirmation + LABEL ALL_PLATFORMS + Неправильное подтверждение нового PIN-кода для Smart-eID + + + Continue + LABEL ALL_PLATFORMS + Продолжить + + + + InputSuccessView + + PUK is correct + INFO ALL_PLATFORMS + Правильный PUK-код + + + You now have <b>3 more attempts</b> to enter your correct <b>ID card PIN</b>. + INFO ALL_PLATFORMS + У вас есть ещё три попытки, чтобы ввести правильный PIN-код идентификационной карты. + + + Continue + LABEL ALL_PLATFORMS + Продолжить + + + CAN is correct + INFO ALL_PLATFORMS + Правильный CAN-код + + + Please enter your <b>6-digit ID card PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Введите 6-значный PIN-код идентификационной карты. Это ваша последняя попытка. + + + If you enter a wrong ID Card PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Если вы ещё раз введете неправильный PIN-код идентификационной карты, PIN-код будет заблокирован. Разблокировать его можно будет только через PUK-код. + + + Please enter your <b>5-digit Transport PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Введите 5-значный временный PIN-код. Это ваша последняя попытка. + + + If you enter a wrong Transport PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Если вы ещё раз введете неправильный временный PIN-код, PIN-код будет заблокирован. Разблокировать его можно будет только через PUK-код. + + + You now have <b>3 more attempts</b> to enter your correct <b>Transport PIN</b>. + INFO ALL_PLATFORMS + У вас есть ещё три попытки, чтобы ввести правильный временный PIN-код. @@ -1691,10 +1809,6 @@ LABEL ANDROID IOS Share log Поделиться файлом журнала - - Delete log - Удалить файл журнала - Delete all logs Удалить все файлы журнала @@ -1717,31 +1831,14 @@ LABEL ANDROID IOS LABEL DESKTOP Файлы журнала (*.log) - - Delete log - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Удалить файл журнала - The current log will be automatically deleted at exit. Текущий файл журнала будет автоматически удален при выходе. - - Delete old logs - LABEL DESKTOP - Удалить старые файлы журнала - Detach log viewer Показать файл журнала отдельно - - Delete selected log - LABEL DESKTOP - Удалить выбранный файл журнала - All old logs will be deleted. INFO DESKTOP All logfiles are about to be removed, user confirmation required. @@ -1749,13 +1846,6 @@ LABEL ANDROID IOS INFO ANDROID IOS All logfiles are about to be removed, user confirmation required. Все старые файлы журнала будут удалены. - - The log will be deleted. - INFO DESKTOP The current logfile is about to be removed, user confirmation required. ----------- -INFO ANDROID IOS The current logfile is about to be removed, user confirmation required. - Файл журнала будет удален. - Log LABEL ANDROID IOS @@ -1767,12 +1857,16 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Delete all logs - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Удалить все файлы журнала Delete - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Удалить @@ -1806,7 +1900,7 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r The log entry was copied to the clipboard. INFO DESKTOP Toast message used to confirm the copy of a log entry. - Запись журнала скопирована в буфер обмена. + Запись журнала скопирована в буфер обмена. @@ -1826,11 +1920,6 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r LABEL DESKTOP Справка - - Start page - LABEL ANDROID IOS - Начальная страница - Check device and ID card LABEL ANDROID IOS @@ -1848,22 +1937,22 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Two finger swipe to scroll. - - - - List of workflows with %1 items. - + Пролистывание двумя пальцами. Item %1 of %2 - + Элемент %1 из %2 Change PIN LABEL DESKTOP ---------- LABEL ANDROID IOS - Изменить PIN-код + Изменить PIN-код + + + Three finger swipe to scroll. + @@ -1885,14 +1974,14 @@ LABEL ANDROID IOS General - LABEL DESKTOP + LABEL DESKTOP +---------- +LABEL ANDROID IOS Общая информация Version information - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ANDROID IOS Информация о версии @@ -1907,11 +1996,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Примечания к версии - - Help & Feedback - LABEL ANDROID IOS - Помощь и обратная связь - Privacy statement LABEL ANDROID IOS @@ -1934,43 +2018,45 @@ LABEL ANDROID IOS Information - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Информация List of Providers LABEL ANDROID IOS - + Список провайдеров Data and logs LABEL DESKTOP - Диагностика и файлы журнала + Данные и файлы журнала FAQ - Frequently asked questions LABEL ANDROID IOS - Часто задаваемые вопросы + Часто задаваемые вопросы Contact LABEL ANDROID IOS - Поддержка + Контакты Show Logs LABEL ANDROID IOS - Файлы журнала + Показать файлы журнала Send log to the support LABEL ANDROID IOS - Сообщить об ошибке + Отправить файл журнала в службу поддержки Terms of use and software license LABEL ANDROID IOS - Лицензия на программное обеспечение + Условия использования и лицензия на программное обеспечение @@ -1988,12 +2074,12 @@ LABEL ANDROID IOS Show system data LABEL DESKTOP - Показать диагностику + Показать системные данные System data LABEL DESKTOP - Диагностика + Системные данные @@ -2003,35 +2089,20 @@ LABEL ANDROID IOS LABEL DESKTOP Открыть сайт - - Privacy statement - LABEL DESKTOP - Положение о конфиденциальности - - - Accessibility statement - LABEL DESKTOP - Заявление о доступности - - - Do you want to see a list of service providers? - LABEL DESKTOP - - List of Providers LABEL DESKTOP - + Список провайдеров FAQ - Frequently asked questions LABEL DESKTOP - Часто задаваемые вопросы + Часто задаваемые вопросы Contact LABEL DESKTOP - Поддержка + Контакты @@ -2045,25 +2116,6 @@ LABEL ANDROID IOS Назад - - NavigationButton - - Yes - Да - - - No - Нет - - - Continue - Продолжить - - - Back - Назад - - NavigationView @@ -2082,6 +2134,31 @@ LABEL ANDROID IOS Card reader Устройство чтения карт + + %1 of %2 + ANDROID IOS LABEL Relative position of current navigation tab in navigation view. %1 is replaced with the current tab's index, %2 with the total count of tabs + + + + Tab + ANDROID IOS LABEL + + + + Selection + IOS Selected navigation tab. + + + + Tab bar + IOS Name of a11y element of selected navigation tab. + + + + Selected + ANDROID Currently selected navigation tab of navigation view. + + NfcWorkflow @@ -2095,16 +2172,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Запустить сканирование NFC - - Unfortunately, this functionality is not available on your device. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - Данная функция недоступна для вашего устройства. - - - However, you can use a separate smartphone as card reader to utilize the eID function. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - Вы можете воспользоваться функцией онлайн-идентификации на другом смартфоне, используемом в качестве устройства чтения карт. - NFC is switched off. INFO ANDROID IOS NFC is available but needs to be activated in the settings of the smartphone. @@ -2153,25 +2220,55 @@ LABEL ANDROID IOS Please place your ID card on the top of the device's back side. INFO IOS The ID card may be inserted, the authentication process may be started. - Расположите идентификационную карту сверху на обратной стороне устройства. - - - Please place your ID card directly on the device's back side.<br/><br/>The exact position of the ID card is device dependent. The animations depict possible positions. Keep one position for several seconds before trying another one and do not move the ID card after contact was established. - INFO ANDROID The ID card may be inserted, the authentication process may be started. - Расположите идентификационную карту непосредственно на задней стороне устройства.<br/><br/>Точное положение идентификационной карты зависит от устройства. Возможное положение показано в анимации. Удерживайте идентификационную карту в одном положении несколько секунд, прежде чем поменять положение, и не смещайте ее после установки соединения. + Приложите идентификационную карту сверху к обратной стороне устройства. The device "%1" wants to use this smartphone as card reader and connect to your id card. INFO ANDROID IOS %1 will be replaced with the name of the device. Устройство «%1» планирует использовать данный смартфон в качестве устройства чтения карт и установить соединение с вашей идентификационной картой. + + The animations depict possible positions. + INFO ANDROID Text regarding ID card position animations + Возможное положение показано в анимации. + + + The exact position of the ID card is device dependent. + INFO ANDROID Text regarding different NFC chip positions on different smartphones + Точное положение идентификационной карты зависит от устройства. + + + Keep one position for several seconds before trying another one and do not move the ID card after contact was established. + INFO ANDROID Text that one ID card position should be kept for several seconds + Удерживайте идентификационную карту в одном положении несколько секунд, прежде чем поменять положение, и не смещайте ее после установки соединения. + + + Please place your ID card directly on the device's back side. + INFO ANDROID Text regarding the ID card position on the device + Приложите идентификационную карту непосредственно к задней стороне устройства. + + + This device cannot be used to read your ID card. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + To pair a smartphone select the <b>WiFi</b> option and click <b>Manage Pairings</b>. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + NumberField - The password is hidden. + The number is hidden. LABEL DESKTOP Screenreader text for the password field - Пароль скрыт. + You entered %1 of %2 digits. @@ -2179,19 +2276,19 @@ LABEL ANDROID IOS Вы ввели %1 из %2 знаков. - Press to hide the password + Press to hide the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Нажмите, чтобы скрыть пароль + - Press to show the password + Press to show the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Нажмите, чтобы показать пароль + - The password is visible. Digits entered so far: %1 + The number is visible. Digits entered so far: %1 LABEL DESKTOP Screenreader text for the password field - Пароль отображается. Цифры, введенные ранее: %1 + @@ -2203,10 +2300,12 @@ LABEL ANDROID IOS Delete last digit + LABEL ANDROID IOS A11y text for the "delete" button image. Удалить последний знак Submit + LABEL ANDROID IOS A11y text for the "submit" button image. Подтвердить @@ -2236,19 +2335,32 @@ LABEL ANDROID IOS Open %1 on your %2other device%3. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4 Откройте %1 в другом %2вашем устройстве%3. On that device go to %1Settings%2 and then %1Smartphone as card reader%2 resp. %1Manage pairings%2. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 3. %1 and %2 are surrounding tags for bold font. + LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 and %2 are surrounding tags for bold font. В данном устройстве перейдите в меню %1Настройки%2, а затем %1Смартфон в качестве устройства чтения карт%2 и в соответствующее меню %1Управлять сопряжениями%2. Choose this smartphone in the list to pair it. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4 Чтобы выполнить сопряжение, выберите данный смартфон в списке. + + Enter the pairing code "%1". + LABEL ANDROID IOS Provide pairing code. Step 4 of 4 + + + + + PairingFailedView + + Pairing to "%1" failed: + ERROR ALL_PLATFORMS An error occurred while pairing the device. + Сбой сопряжения «%1»: + PairingProcessInfo @@ -2273,6 +2385,18 @@ LABEL ANDROID IOS Убедитесь, что программа %1, установленная на смартфоне в качестве устройства чтения карт, имеет версию не ниже %2. + + PairingSuccessView + + Pairing with "%1" successful, it will be listed under "Paired devices". + INFO ALL_PLATFORMS The pairing with the SaC server was successful. + Сопряжение с «%1» успешно; оно будет указано в разделе «Сопряженные устройства». + + + The device may now be used as a card reader. + Теперь это устройство можно использовать для чтения карт. + + PasswordInfoContent @@ -2304,12 +2428,12 @@ LABEL ANDROID IOS Как выбрать безопасный PIN-код? - For your six-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + For your 6-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 1/3 - Не выбирайте для 6-значного PIN-кода комбинации, которые легко отгадать (например, «123456», дату своего рождения или любые другие цифры с идентификационной карты). + Не выбирайте для 6-значного PIN-кода комбинации, которые легко отгадать (например, 123456, дату своего рождения или любые другие цифры с идентификационной карты). - You can change your six-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. + You can change your 6-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 2/3 Изменить 6-значный PIN-код можно в любое время и неограниченное количество раз, если вы знаете свой действительный PIN-код. @@ -2326,24 +2450,24 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Что такое временный PIN-код? - Transport PIN information - LABEL ALL_PLATFORMS - Информация о временном PIN-коде + The Transport PIN is a %1one-time PIN%2 which is required for the initial %1setup of your ID card%2. Once you replace the %1Transport PIN with a card PIN%2, it is tied to your ID card and valid for all devices. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' + - The five-digit Transport PIN was sent to you in the PIN letter by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 1/3 - 5-значный временный PIN-код был отправлен вам в письме с PIN-кодом по почте после того, как вы заказали идентификационную карту. + Where do I find the Transport PIN? + LABEL ALL_PLATFORMS + - If you did not set a self-selected six-digit card PIN when you picked up your ID card, you can do so using the Transport PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 2/3 - Если при получении идентификационной карты вы не установили 6-значный PIN-код карты, это можно сделать с помощью временного PIN-кода. + The 5-digit Transport PIN is a %1one-time PIN%2, that you reveived per %1letter%2 when applying for the ID card. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 1/2 + - Once you have set a card PIN, the Transport PIN loses its validity. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 3/3 - После создания PIN-кода карты временный PIN-код перестает действовать. + When setting up your ID card, you will %1replace%2 this 5-digit %1Transport PIN with%2 a 6-digit, %1self chosen card PIN%2. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 2/2 + Where do I find the PUK? @@ -2351,14 +2475,9 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Где найти PUK-код? - PUK information - LABEL ALL_PLATFORMS - Информация о PUK-коде - - - The PUK is a ten-digit number that you can find in the PIN letter that was sent to you by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' - PUK-код — это 10-значный номер, который можно найти в письме с PIN-кодом, отправленном вам по почте после того, как вы заказали идентификационную карту. + The PUK is a %1 10-digit number%2 that you can find in the %1PIN letter%2 that was sent to you by mail after you %1applied for your ID card%2. You may find it to the %1right%2 of the 5-digit %1Transport PIN%2. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' + Why is the PUK required? @@ -2366,49 +2485,44 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Для чего необходим PUK-код? - The PUK is required if the card PIN has been entered incorrectly three times in a row. As a result, the card PIN is blocked. + The PUK is required if the %1card PIN has been entered incorrectly 3 times%2 in a row. As a result, the card PIN is blocked. By entering the PUK you will %1unblock the card PIN%2 and have %1 3 more attempts%2 to enter the correct PIN. INFO ALL_PLATFORMS Answer to the question 'Why is the PUK required?' - PUK-код необходим в том случае, если PIN-код карты введен неправильно три раза подряд. После этого PIN-код карты блокируется. + - What is the PUK's purpose? + My PUK does not work LABEL ALL_PLATFORMS - В чем назначение PUK-кода? - - - By entering the PUK, you unblock the card PIN and have another three chances to enter the correct PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the PUK's purpose?' - После ввода PUK-кода разблокируется PIN-код карты и появляется возможность ввести правильный PIN-код еще три раза. + - Why is the CAN required? - LABEL ALL_PLATFORMS - Для чего необходим CAN-код? + Make sure, that the letter at hand is the %1letter for your current ID card%2. The PIN letter is valid only for your current ID card. With a new ID card, you receive a new PIN letter with a new PUK. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + - CAN information - LABEL ALL_PLATFORMS - Информация о CAN + If you applied for a PIN Reset letter, make sure that you don't mix up the letters. The %1PIN letter you need contains the 5-digit Transport PIN and the PUK%2. The PIN Reset letter contains the 6-digit card PIN and the activation code. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + - When is the card access number (CAN) required? + Why is the CAN required? LABEL ALL_PLATFORMS - Когда необходим код доступа к карте (CAN-код)? + Для чего необходим CAN-код? - The card access number (CAN) is required when the card PIN has been entered incorrectly twice. + The card access number (CAN) is required when the %1card PIN has been entered incorrectly 2 times%2. INFO ALL_PLATFORMS Answer to the question 'When is the card access number (CAN) required?' - Код доступа к карте (CAN-код) требуется, если PIN-код карты дважды введен неправильно. + - Why do I have to enter the CAN before a third attempt? + Why do I have to enter the CAN before a 3rd attempt? LABEL ALL_PLATFORMS Почему нужно вводить CAN-код перед третьей попыткой? - A third incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that a third incorrect entry can only be made with direct access to your ID card. - INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a third attempt?' - Третий неверный ввод блокирует PIN-код, и вы больше не сможете использовать функцию eID до тех пор, пока он не будет разблокирован. Запрос CAN-кода гарантирует, что третий неправильный ввод может быть выполнен только при наличии прямого доступа к идентификационной карте. + A 3rd incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that %1direct access to your ID card%2 is given. + INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a 3rd attempt?' + Where can I find the CAN? @@ -2416,14 +2530,14 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Где найти CAN-код? - The CAN is a six-digit number that can be found on the bottom right of the front of the ID card. + The CAN is a 6-digit number that can be found on the %1bottom right%2 of the %1front of the ID card%2. INFO ALL_PLATFORMS Answer to the question 'Where can I find the CAN?' - CAN-код — это 6-значный номер, указанный в нижнем правом углу на передней стороне идентификационной карты. + - The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a six-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in red). + The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a 6-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in picture). INFO ALL_PLATFORMS Description text of CAN-allowed authentication - Код доступа (CAN) предоставляет доступ к сохраненным на идентификационной карте данным. CAN — это 6-значный номер, указанный на идентификационной карте спереди. Он расположен внизу справа рядом со сроком действия (выделен красным цветом). + Код доступа (CAN) предоставляет доступ к сохраненным на идентификационной карте данным. CAN — это 6-значный номер, указанный на идентификационной карте спереди. Он расположен внизу справа рядом со сроком действия (выделен красным цветом). Smart-eID blocking code @@ -2453,7 +2567,7 @@ LABEL ALL_PLATFORMS Знаете ли вы свой PIN-код? - You have not yet set a six-digit card PIN and cannot find the PIN letter with the Transport PIN? + You have not yet set a 6-digit card PIN and cannot find the PIN letter with the Transport PIN? INFO ALL_PLATFORMS Вы еще не установили 6-значный PIN-код карты и не можете найти письмо с PIN-кодом, где указан временный PIN-код? @@ -2463,135 +2577,193 @@ LABEL ALL_PLATFORMS Вы установили PIN-код карты при получении идентификационной карты или позже самостоятельно, но не можете его вспомнить? - Learn more about the two types of PIN + How do the PIN types differ? LABEL ALL_PLATFORMS - Узнайте больше о двух типах PIN-кодов - - - Types of PIN - LABEL ALL_PLATFORMS - Типы PIN-кодов + - Your ID card comes with a five-digit 'Transport PIN' which you need to replace with a six-digit PIN that you choose yourself. + Your ID card comes with a 5-digit %1Transport PIN%2 which you need to %1replace with%2 a 6-digit %1card PIN%2 that you choose yourself. INFO ALL_PLATFORMS Description text explaining the PINs 1/7 - К вашей идентификационной карте прилагается 5-значный временный PIN-код, который необходимо заменить на 6-значным PIN-кодом (его вы выберете сами). + - Five-digit Transport PIN + 5-digit Transport PIN LABEL ALL_PLATFORMS 5-значный временный PIN-код - Six-digit PIN + 6-digit PIN LABEL ALL_PLATFORMS 6-значный PIN-код - You can use the PIN Reset Service to request a new card PIN free of charge. - LABEL ALL_PLATFORMS - Вы можете воспользоваться службой сброса PIN-кода, чтобы бесплатно запросить новый PIN-код карты. - - - If you do not know either your Transport PIN or your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. - Если вы не знаете ни своего временного PIN-кода, ни PIN-кода карты, вы можете бесплатно запросить новый PIN-код, воспользовавшись службой сброса PIN-кода. - - - If you have forgotten your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - Если вы забыли PIN-код карты, вы можете бесплатно запросить новый PIN-код, воспользовавшись службой сброса PIN-кода. - - - The five-digit Transport PIN was sent to you by mail after you applied for your ID card. + The 5-digit Transport PIN is a %1one-time PIN%2 that was sent to you by %1mail%2 after you applied for your ID card. INFO ALL_PLATFORMS Description text explaining the PINs 2/7 - 5-значный временный PIN-код был отправлен вам по почте после того, как вы заказали идентификационную карту. + What is the Smart-eID PIN? LABEL ALL_PLATFORMS - + Что такое PIN-код для Smart-eID? Set up Smart-eID LABEL ALL_PLATFORMS - Создание Smart-eID + Создание Smart-eID - The Smart-eID PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. + The Smart-eID PIN is a 6-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' - + PIN-код для Smart-eID — это 6-значный PIN-код, который пользователь создает самостоятельно. Этот PIN-код необходим для использования Smart-eID. - For your six-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + For your 6-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 - + Не выбирайте в качестве 6-значного PIN-кода Smart-eID комбинации, которые легко отгадать, например «123456», дату своего рождения или любые другие цифры с идентификационной карты. - You can change your six-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. + You can change your 6-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 + Изменить 6-значный PIN-код для Smart-eID можно в любое время и неограниченное количество раз, если вы знаете свой действительный PIN-код для Smart-eID. + + + When you set up the eID function, you will %1replace%2 this 5-digit %1Transport PIN%2 with a 6-digit %1card PIN that you choose yourself%2. + INFO ALL_PLATFORMS Description text explaining the PINs 3/7 + + + + The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time. + INFO ALL_PLATFORMS Description text explaining the PINs 5/7 + PIN-код для Smart-eID состоит из шести знаков. Вы выбираете этот PIN-код сами при первой настройке Smart-eID. + + + You can change your card PIN and your Smart-eID PIN at any time in %1. + INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + Вы можете изменить PIN-код для своей Smart-eID в любое время в меню %1. + + + With this 6-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. + INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + Ввод 6-значного PIN-кода подтверждает в режиме онлайн то, что идентификационная карта или Smart-eID принадлежит вам. Никто не сможет использовать функцию eID без этого PIN-кода. + + + The card PIN is a 6-digit PIN that you set yourself. You always need this %1PIN%2 if you want to use the %1eID function%2. + INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' - The PIN can only be used once. When you set up the eID function, you will replace this five-digit Transport PIN with a six-digit card PIN that you choose yourself. - INFO ALL_PLATFORMS Description text explaining the PINs 3/7 - + You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the 5-digit Transport PIN. Only when you have set a 6-digit PIN of your own choice can you use the eID function and set up a Smart-eID. + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) + Задать PIN-код карты можно либо непосредственно при получении идентификационной карты в ведомстве по делам граждан (Bürgeramt), либо позже в %1, используя для этого 5-значный временный PIN-код. Только установив 6-значный PIN-код по своему выбору, вы можете использовать функцию eID и настраивать Smart-eID. - The six-digit card PIN is a number that you choose yourself when you set up the eID function for the first time. It replaces your five-digit Transport PIN. - INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + The card PIN was %1either%2... + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Intro - The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time. - INFO ALL_PLATFORMS Description text explaining the PINs 5/7 + set by you when picking up the ID card %1at the citiziens' office%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 1/3 - You can change your card PIN and your Smart-eID PIN at any time in %1. - INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + set %1in the %3 using%2 the 5-digit %1Transport PIN%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 2/3 - With this six-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. - INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + requested using the %1PIN Reset Service%2 - you may continue using the 6-digit card PIN from the letter or change it via "Change PIN" to a self chosen card PIN + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 3/3 - The card PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use the eID function with your ID card. - INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' + I just have a 5-digit Transport PIN + LABEL ALL_PLATFORMS - You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the five-digit Transport PIN. Only when you have set a six-digit PIN of your own choice can you use the eID function and set up a Smart-eID. - INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) + You need to change the %1 5-digit Transport PIN%2 to your personal card PIN. Use %1Change PIN > Transport PIN%2 from the startpage to do so. + INFO ALL_PLATFORMS Explanation if only the Transport PIN is at hand If you have forgotten your Smart-eID PIN, you can renew your Smart-eID and thereby set a new PIN. LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - + Если вы забыли PIN-код для Smart-eID, вы можете обновить свою Smart-eID и установить новый PIN-код. Where can I find the Smart-eID PIN? LABEL ALL_PLATFORMS - + Где найти PIN-код для Smart-eID? You have set the Smart-eID PIN while setting up the Smart-eID. INFO ALL_PLATFORMS Answer to the question 'Where can I find the Smart-eID PIN?' - + Вы устанавливаете PIN-код для Smart-eID при настройке Smart-eID. - With this six-digit PIN you prove online that the ID card belongs to you. No one can use the eID function without this PIN. + With this 6-digit PIN you prove online that the ID card belongs to you. %1No one can use the eID function without this PIN%2. INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - You can change your card PIN at any time in %1. + If you applied for a %1PIN Reset letter%2, a new card PIN was already set for you. You can change your card PIN at %1any time in %3%2. INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + + I can't recall my PIN + LABEL ALL_PLATFORMS + Я не могу вспомнить свой PIN-код + + + I can't recall my PUK + Я не могу вспомнить свой PUK-код + + + Set a new PIN + Создание новый PIN-код + + + My Transport PIN does not work + LABEL ALL_PLATFORMS + Мой временный PIN-код не работает + + + If your Transport PIN from the PIN letter does work, this might be caused by the following reasons: + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Introduction why the Transport PIN might not work. + Если ваш временный PIN-код, указанный к письме с PIN-кодом, это может иметь слежующие причины: + + + You already set a 6-digit PIN either at the competent authority or using the %1. + INFO ALL_PLATFORMS Information why the Transport PIN is void: a 6-digit PIN was already set + Вы уже создали 6-значный PIN-код в компетентном органе или через %1. + + + You applied for PIN Reset Letter (letter containing a 6-digit PIN and corresponding Activation Code). + INFO ALL_PLATFORMS Information why the Transport PIN is void: the PIN Reset Service was used + Вы запросили письмо для переустановки PIN-кода (письмо содержит 6-значный PIN-код и соответствующий код активации). + + + Once you set a 6-digit PIN, the Transport PIN is no longer valid. You may then only use the 6-digit PIN to authenticate yourself. + INFO ALL_PLATFORMS Information that the Transport PIN is void once a 6-digit PIN was set. + После установки 6-значного PIN-кода временный PIN-код становится недействительным. В дальнейшем для аутентификации может быть использован только 6-значный PIN-код. + + + The 6-digit card PIN is a %1number that you choose yourself%2 when you set up the eID function for the first time. It %1replaces%2 your %1 5-digit Transport PIN%2. + INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + + + + + PasswordInfoView + + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Совет + PersonalizationController @@ -2608,12 +2780,12 @@ LABEL ALL_PLATFORMS The Smart-eID issuing authority needs to read your ID card's data in order to store it on this device: INFO ANDROID IOS The user is informed that the ID card needs to be read to create a Smart-eID. - Орган, выдавший электронную идентификационную карту Smart-eID, должен считать данные вашей идентификационной карты для ее сохранения на этом устройстве. + Орган, выдавший электронную идентификационную карту Smart-eID, должен считать данные вашей идентификационной карты для ее сохранения на этом устройстве: By entering your ID card PIN, access to the following data of your ID card will be allowed to the mentioned provider: LABEL IOS_PHONE ANDROID_PHONE - При вводе PIN-кода идентификационной карты вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты. + При вводе PIN-кода идентификационной карты вы предоставляете указанному выше провайдеру доступ к следующим данным идентификационной карты: @@ -2629,9 +2801,9 @@ LABEL ALL_PLATFORMS Важная информация - Do not give your smartphone to third parties unattended, especially if it is already unlocked. + Do not give your smartphone to 3rd parties unattended, especially if it is already unlocked. LABEL ANDROID IOS - Не передавайте смартфон третьим лицам, особенно после разблокировки. + Не передавайте смартфон третьим лицам бесконтрольно, особенно после его разблокирования. Do not keep a note of the Smart-eID PIN in or on your smartphone. @@ -2639,9 +2811,9 @@ LABEL ALL_PLATFORMS Не храните PIN-код для Smart-eID на смартфоне и не записывайте на его корпусе. - Do not give your Smart-eID PIN to third parties. + Do not give your Smart-eID PIN to 3rd parties. LABEL ANDROID IOS - Не передавайте PIN-код для Smart-eID третьим лицам. + Не сообщайте свой PIN-код для Smart-eID третьим лицам. Update the operating system of your smartphone regularly. @@ -2661,7 +2833,7 @@ LABEL ALL_PLATFORMS If you uninstall the %1 or reset your smartphone, the Smart-eID must be set up again. LABEL ANDROID IOS - + При удалении %1 или сбросе настроек смартфона необходимо заново настраивать Smart-eID. @@ -2724,7 +2896,7 @@ LABEL ALL_PLATFORMS Please wait a moment, the current process is being finished. LABEL ANDROID IOS - + Подождите, текущий процесс завершается. @@ -2739,11 +2911,6 @@ LABEL ALL_PLATFORMS INFO ANDROID IOS Success message that the Smart-eID was created. Вы успешно создали Smart-eID. - - OK - LABEL ANDROID IOS - OK - Continue LABEL ANDROID IOS @@ -2769,6 +2936,16 @@ LABEL ALL_PLATFORMS LABEL ANDROID IOS Внимание: с помощью вашей идентификационной карты вы можете создать всего <b><u>одну</u></b> электронную идентификационную карту Smart-eID. Дополнительные попытки доступны (%1). + + Personalization failed + LABEL ANDROID IOS + Сбой персонализации + + + Back to start page + LABEL ANDROID IOS + Назад к начальной странице + PkiSwitch @@ -2812,21 +2989,36 @@ LABEL ALL_PLATFORMS - ProviderInfoSection + ProviderInfo See details under "more..." - LABEL DESKTOP - Подробнее см. в пункте «Дополнительные сведения». + LABEL ALL_PLATFORMS + Подробнее см. в пункте «Дополнительные сведения» Show more information about the service provider LABEL DESKTOP - Показать больше информации о провайдере службы + Показать больше информации о провайдере службы + + + You are about to identify yourself towards the following provider: + LABEL DESKTOP + Вы собираетесь пройти самоидентификацию для следующего провайдера: + + + Provider + LABEL ANDROID IOS + Провайдер + + + Touch for more details + LABEL ANDROID IOS + Нажмите для получения подробной информации Details about the provider LABEL DESKTOP - Подробная информация о провайдере + Подробная информация о провайдере @@ -2872,8 +3064,8 @@ LABEL DESKTOP Title of the proxy credentials popup. Произошла ошибка при управлении файлом журнала: %1 - Please describe the error that occurred. - Опишите возникшую ошибку. + Please describe the error that occurs. Our support is available to you in German and English. + Опишите возникшую ошибку. Мы предоставляем поддержку на немецком и английском языках. You may want to attach the logfile which can be saved from the error dialog. @@ -2904,6 +3096,44 @@ LABEL DESKTOP Title of the proxy credentials popup. Неизвестное устройство чтения карт + + RedirectView + + Remove the ID card from the card reader + INFO DESKTOP Hint to user that the ID card should be removed + Извлеките идентификационную карту из устройства чтоения карт + + + Remove the ID card from the NFC interface + INFO ANDROID IOS Hint to user that the ID card should be removed + Извлеките идентификационную карту из интерфейса NFC + + + If you have any questions or encounter any errors during the process, please contact the corresponding provider. + LABEL ALL_PLATFORMS + + + + You will be automatically redirected to the provider in a few seconds. If you are not automatically redirected, click on the "%1" button. + INFO ALL_PLATFORMS Redirect information when automatic redirect is enabled + + + + Press the button to complete the authentication and return to the provider. + INFO ALL_PLATFORMS Redirect information when automatic redirect is disabled + + + + Return to provider + LABEL ALL_PLATFORMS + Вернуться к провайдеру + + + Authentication successful + LABEL ALL_PLATFORMS + Аутентификация выполнена успешно + + ReleaseNotes @@ -2922,15 +3152,18 @@ LABEL ANDROID IOS RemoteReaderDelegate - Smartphone named "%1" - Имя смартфона «%1» + Smartphone named "%1". %2. + INFO DESKTOP Name and status of remote device. %1 is replaced with the name, %2 with the status + Имя смартфона «%1». %2. Press space to unpair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is paired. Нажмите пробел, чтобы отменить сопряжение смартфона «%1». Press space to pair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is unpaired. Нажмите пробел для сопряжения смартфона «%1». @@ -2955,10 +3188,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 is a placeholder-tag for the app name. Откройте %1 в вашем смартфоне в качестве устройства чтения карт. - - Both devices have to be connected to the same WiFi. - Оба устройства должны быть подключены к одной сети Wi-Fi. - On that device go to %1Card reader%2 and then %1Pair device%2 rsp. %1Pair new device%2. LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4. %1 and %2 are surrounding tags for bold font @@ -2979,6 +3208,10 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4. %1 is a placeholder-tag for the app name. Убедитесь, что программа %1, установленная на смартфоне в качестве устройства чтения карт, имеет версию не ниже %2. + + Both devices have to be on the same network (e.g. WiFi). + Оба устройства должны быть подключены к одной сети (например, Wi-Fi). + RemoteServiceController @@ -3008,11 +3241,6 @@ LABEL ANDROID IOS RemoteServiceView - - Pairing failed. Please start a new pairing process on your other device and enter the shown pairing code. - ERROR ANDROID IOS An error occurred while pairing the device. - Сбой сопряжения. Перезапустите сопряжение на другом устройстве и введите указанный код сопряжения. - WiFi not active LABEL ANDROID IOS @@ -3023,25 +3251,20 @@ LABEL ANDROID IOS LABEL ANDROID IOS Функция NFC не активирована - - Remote service not available - LABEL ANDROID IOS - Удаленная служба недоступна - Card access in progress LABEL ANDROID IOS Выполняется доступ к карте - Waiting for connection + Card reader ready LABEL ANDROID IOS - Ожидание соединения + Ожидание соединения - Waiting for connection from a paired device... + To do this, start a process on a paired device. INFO ANDROID IOS - Ожидание соединения сопряженного устройства… + Pairing code: <b>%1</b> @@ -3064,9 +3287,9 @@ LABEL ANDROID IOS Выполнить сопряжение устройства - Allow connection + Activate card reader LABEL ANDROID IOS - Разрешить подключение + Разрешить подключение You can use this Smartphone as a card reader for the %1 on other devices e.g. a laptop. @@ -3108,9 +3331,9 @@ To do this you first have to pair that device with this smartphone. Где следует вводить код сопряжения? - Enter the pairing code %1 in the %2 on your other device. + Enter the pairing code "%1" in the %2 on your other device. INFO ANDROID IOS - Введите код сопряжения %1 в поле %2 в другом вашем устройстве. + Введите код сопряжения "%1" в поле %2 в другом вашем устройстве. Cancel pairing @@ -3127,6 +3350,16 @@ To do this you first have to pair that device with this smartphone. INFO ANDROID IOS Теперь сопряженные устройства могут использовать этот смартфон в качестве устройства чтения карт. + + NFC is not available + LABEL ANDROID IOS + Функция NFC недоступна + + + Stop card reader + LABEL ANDROID IOS + + RemoteServiceViewRemote @@ -3190,13 +3423,18 @@ To do this you first have to pair that device with this smartphone. LABEL ANDROID IOS Нажмите для сопряжения + + Pairing the device ... + LABEL ANDROID IOS + Сопряжение устройства… + RemoteServiceWifiInfo - Both devices have to be connected to the same WiFi. + Both devices have to be on the same network (e.g. WiFi). INFO ANDROID IOS The remote service is active. Hint that both devices need to be connected to the same network. - Оба устройства должны быть подключены к одной сети Wi-Fi. + Оба устройства должны быть подключены к одной сети (например, Wi-Fi). @@ -3229,7 +3467,7 @@ To do this you first have to pair that device with this smartphone. Connected to %1. Please follow the instructions on the connected smartphone. INFO ANDROID IOS The connection to the smartphone was established, the ID card may be inserted. - + Подключено к %1. Следуйте инструкциям в подключенном смартфоне. Manage pairings @@ -3249,15 +3487,16 @@ To do this you first have to pair that device with this smartphone. ResultErrorView - - Details - Подробная информация - Error code: LABEL ANDROID IOS Код ошибки: + + Show Details + LABEL ANDROID IOS + Подробная информация + ResultView @@ -3286,26 +3525,20 @@ To do this you first have to pair that device with this smartphone. LABEL ANDROID IOS OK - - - RetryCounter - Remaining ID card PIN attempts: %1 - LABEL DESKTOP - Осталось попыток ввода PIN-кода идентификационной карты: %1 + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Совет SecurityAndPrivacySettings - Onscreen keypad + Numeric keypad LABEL DESKTOP - Экранная клавиатура - - - Use on screen keypad for PIN entry - LABEL DESKTOP - Использовать экранную клавиатуру для ввода PIN-кода + Экранная клавиатура Software updates @@ -3313,9 +3546,9 @@ To do this you first have to pair that device with this smartphone. Обновления программного обеспечения - Check at program start + Check for updates at program start LABEL DESKTOP - Проверить при запуске программы + Проверить при запуске программы Show update @@ -3348,19 +3581,19 @@ To do this you first have to pair that device with this smartphone. Нет информации об обновлениях, проверьте наличие доступных обновлений вручную. - Shuffle digits of on screen keypad + Shuffle keys LABEL DESKTOP - Случайное расположение кнопок клавиатуры + Перетасовать цифры экранной клавиатуры - Button animation + Hide key animations LABEL DESKTOP - Анимация кнопок экранной клавиатуры при нажатии + Анимация кнопок - Visually highlight key presses on screen keypad + Makes it difficult for outsiders to detect PIN entry LABEL DESKTOP - + Визуальное выделение нажатой клавиши на экранной клавиатуре @@ -3380,18 +3613,18 @@ To do this you first have to pair that device with this smartphone. LABEL DESKTOP Title of the self authentication result data view Считать данные - - OK - LABEL DESKTOP ----------- -LABEL ANDROID IOS - OK - Identify LABEL ANDROID IOS Идентифицировать + + Back to start page + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Назад к начальной странице + SelfAuthenticationView @@ -3418,9 +3651,7 @@ LABEL ANDROID IOS Use the button "See my personal data" to start the self-authentication service of the manufacturer of the %1 to display the data stored in the chip of your ID card. - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Используйте кнопку «Просмотреть персональные данные» для запуска службы самоаутентификации производителя %1, чтобы отобразить данные, сохраненные в чипсете вашей идентификационной карты. @@ -3433,13 +3664,18 @@ LABEL ANDROID IOS Self-authentication LABEL ANDROID IOS - + Самоаутентификация Hint LABEL ANDROID IOS Совет + + View the data stored on your ID card + LABEL ANDROID IOS + Посмотреть данные, сохраненные на идентификационной карте + SettingsView @@ -3471,11 +3707,14 @@ LABEL ANDROID IOS Security and privacy - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Безопасность и защита данных + + Numeric keypad + LABEL ANDROID IOS + Безопасность и защита данных + Debug options LABEL DESKTOP @@ -3506,14 +3745,14 @@ LABEL ANDROID IOS Ввести PIN-код на этом устройстве - Randomize the order of the on screen keypad buttons + Shuffle keys LABEL ANDROID IOS - Случайное расположение кнопок экранной клавиатуры + Случайное расположение кнопок экранной клавиатуры - Keypad animations + Hide key animations LABEL ANDROID IOS - Анимация кнопок + Анимация кнопок Skip rights page @@ -3540,11 +3779,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Использовать менее чувствительный режим - - Layout style - LABEL ANDROID IOS - Стиль макета - Create dummy entries LABEL ANDROID IOS @@ -3563,80 +3797,105 @@ LABEL ANDROID IOS Smart-eID LABEL ANDROID IOS - Smart-eID + Smart-eID Reset Smart-eID LABEL ANDROID IOS - Сбросить Smart-eID + Сбросить Smart-eID Reset Smart-eID data on your device LABEL ANDROID IOS - + Сбросить данные Smart-eID на вашем устройстве - Show Transport PIN reminder, store feedback and close reminder dialogs. + Show requested rights on this device as well LABEL ANDROID IOS - + Показывать запрошенные права также и в этом устройстве - Reset hideable dialogs + Manage pairings LABEL ANDROID IOS - + Управление сопряжениями - Show requested rights on this device as well + Show Transport PIN reminder, store feedback and close reminder dialogs. LABEL ANDROID IOS - Показывать запрошенные права также и в этом устройстве + Показывать напоминание временного PIN-кода, сохранять обратную связь и закрывать диалоговые окна с напоминаниями. - Manage pairings + Reset hideable dialogs LABEL ANDROID IOS - Управление сопряжениями + Сбросить скрываемые диалоговые окна Toggling will restart the %1 LABEL ANDROID IOS - + Переключение приведет к перезапуску %1 Use system font LABEL ANDROID IOS - + Использовать системный шрифт Appearance LABEL ANDROID IOS - + Внешний вид Add and remove devices LABEL ANDROID IOS - Управление сопряженными устройствами и добавление новых устройств + Добавить/удалить устройства On-site reading LABEL ANDROID IOS - Режим «Код CAN разрешен» + Чтение данных на месте Support CAN allowed mode for on-site reading LABEL ANDROID IOS - Поддержка режима «Код CAN разрешен» + Поддержка режима «Код CAN разрешен» для чтения данных на месте Allow test sample card usage LABEL ANDROID IOS - + Разрешить использование тестовой карты Simulate a test sample card in authentications LABEL ANDROID IOS + Моделировать тестовую карту в процессах аутентификации + + + Makes it difficult for outsiders to detect PIN entry + LABEL ANDROID IOS + Визуальное выделение нажатой клавиши на экранной клавиатуре + + + Use images instead of animations + LABEL ANDROID IOS + + + + Accessibility + LABEL ANDROID IOS + + + + Hide key animations when entering PIN + LABEL ANDROID IOS + + + + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. + LABEL ANDROID IOS - Visually highlight key presses on screen keypad + Manual redirection back to the provider LABEL ANDROID IOS @@ -3661,12 +3920,12 @@ LABEL ANDROID IOS Autostart Settings LABEL DESKTOP - + Настройки автозапуска The launch will add a tray icon to the notification area. INFO WINDOWS Additional information that Windows auto-start adds a symbol to the notification area. - + Запуск добавит значок в область оповещений на панели задач. @@ -3687,27 +3946,27 @@ LABEL ANDROID IOS Smart-eID LABEL ANDROID IOS - Smart-eID + Smart-eID Please wait a moment. LABEL ANDROID IOS - Подождите. + Подождите. Send log LABEL ANDROID IOS - Отправить файл журнала + Отправить файл журнала If you want to use that functionality again, you need to set up a new Smart-eID first. LABEL ANDROID IOS - Если вы хотите в будущем снова использовать этот функционал, необходимо сначала создать новую Smart-eID. + Если вы хотите в будущем снова использовать этот функционал, необходимо сначала создать новую Smart-eID. Reset Smart-eID LABEL ANDROID IOS - Сбросить Smart-eID + Сбросить Smart-eID @@ -3715,47 +3974,47 @@ LABEL ANDROID IOS Delete Smart-eID LABEL ANDROID IOS - Удалить Smart-eID + Удалить Smart-eID You have successfuly deleted your Smart-eID. LABEL ANDROID IOS - + Вы успешно удалили Smart-eID. The Smart-eID could not be successfully deleted from your device. LABEL ANDROID IOS - + Невозможно удалить Smart-eID из вашего устройства. Back to start page LABEL ANDROID IOS - + Назад к начальной странице You are about to delete the Smart-eID data that is currently stored on your device. LABEL ANDROID IOS - Вы собираетесь удалить данные Smart-eID, сохраненные на вашем устройстве. + Вы собираетесь удалить данные Smart-eID, сохраненные на вашем устройстве. Are you sure you want to delete the Smart-eID? LABEL ANDROID IOS - Удалить Smart-eID? + Удалить Smart-eID? Delete LABEL ANDROID IOS - Удалить + Удалить Deleting Smart-eID LABEL ANDROID IOS - Удаление Smart-eID + Удаление Smart-eID Delete the Smart-eID LABEL ANDROID IOS - + Удалить Smart-eID @@ -3793,7 +4052,7 @@ LABEL ANDROID IOS With the Smart-eID you may also use the online identification function without the ID card. LABEL ANDROID IOS - + С помощью Smart-eID вы также можете использовать функцию онлайн-идентификации без идентификационной карты. @@ -3801,37 +4060,37 @@ LABEL ANDROID IOS Reset Smart-eID LABEL ANDROID IOS - Сбросить Smart-eID + Сбросить Smart-eID You have successfully reset your Smart-eID. LABEL ANDROID IOS - + Вы успешно сбросили настройки Smart-eID. You are about to reset your Smart-eID data. This can also be used for troubleshooting as well. LABEL ANDROID IOS - + Вы собираетесь сбросить данные Smart-eID. Это также может потребоваться для устранения ошибок. Are you sure you want to reset the Smart-eID? LABEL ANDROID IOS - + Сбросить настройки Smart-eID? Reset LABEL ANDROID IOS - + Сбросить Resetting Smart-eID LABEL ANDROID IOS - Сброс Smart-eID + Сброс Smart-eID Reset the Smart-eID LABEL ANDROID IOS - + Сбросить Smart-eID @@ -3859,27 +4118,27 @@ LABEL ANDROID IOS Delete Smart-eID data from your device LABEL ANDROID IOS - + Удалить данные Smart-eID из вашего устройства Try Smart-eID LABEL ANDROID IOS - + Попробовать Smart-eID Show Smart-eID data LABEL ANDROID IOS - + Показать данные Smart-eID Change Smart-eID PIN LABEL ANDROID IOS - Изменить PIN-код для Smart-eID + Изменить PIN-код для Smart-eID Change the chosen Smart-eID PIN LABEL ANDROID IOS - + Изменить PIN-код для выбранной Smart-eID @@ -3890,9 +4149,9 @@ LABEL ANDROID IOS Smart-eID - You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your six-digit ID card PIN and an internet connection. + You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Вы собираетесь создать Smart-eID на устройстве. Для этого требуется идентификационная карта, 6-значный PIN-код идентификационной карты и подключение к Интернету. + Вы собираетесь создать Smart-eID на устройстве. Для продолжения вам потребуются идентификационная карта, 6-значный PIN-код идентификационной карты и подключение к Интернету. Set up Smart-eID @@ -3902,15 +4161,15 @@ LABEL ANDROID IOS Smart-eID setup LABEL ANDROID IOS - + Настройка Smart-eID SmartUpdateStartView - You are about to renew your Smart-eID. In order to proceed, you need your ID card, your six-digit ID card PIN and an internet connection. + You are about to renew your Smart-eID. In order to proceed, you need your ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Вы собираетесь обновить Smart-eID. Для этого требуется идентификационная карта, 6-значный PIN-код идентификационной карты и подключение к Интернету. + Вы собираетесь обновить Smart-eID. Для продолжения вам потребуются идентификационная карта, 6-значный PIN-код идентификационной карты и подключение к Интернету. Please note that your current Smart-eID is invalidated during the process and will not be usable until the update process is completed. @@ -3925,12 +4184,12 @@ LABEL ANDROID IOS Renew the Smart-eID LABEL ANDROID IOS - + Обновить Smart-eID Smart-eID renewal LABEL ANDROID IOS - + Обновление Smart-eID @@ -4026,7 +4285,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The device "%1" wants to access your Smart-eID. INFO ANDROID IOS %1 will be replaced with the name of the device. - + Устройство «%1» запрашивает доступ к вашей Smart-eID. @@ -4052,6 +4311,26 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Оценить приложение + + SuggestionData + + Hint + Совет + + + + TabbedPane + + Tab selected + LABEL DESKTOP + Вкладка выбрана + + + %1 of %2 + LABEL DESKTOP %1 is the current selected Page of %2 Pages + + + TabbedReaderView @@ -4067,6 +4346,10 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u USB card reader USB-устройство чтения карт + + Found new USB card reader that is suitable for the ID card. The workflow may now be continued. + Найдено новое USB-устройство чтения карт, подходящее для идентификационной карты. Теперь можно продолжить процесс. + TechnologySwitch @@ -4090,6 +4373,16 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ANDROID IOS SIM + + %1 mode is active. + INFO ANDROID IOS A11y text on button indicating the currently active technology. %1 will be replaced with the name of the technology (e.g. NFC). + Режим %1 активирован. + + + Click here to change the mode to %1. + INFO ANDROID IOS A11y text on button to switch to another technology. %1 will be replaced with the name of the technology (e.g. NFC). + Нажмите сюда, чтобы перейти к режиму %1. + TitleBar @@ -4112,11 +4405,17 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Show in-app notifications of %1 + LABEL DESKTOP Показать внутренние оповещения в приложении %1 Title bar LABEL DESKTOP + Строка заголовка + + + Hide in-app notifications of %1 + LABEL DESKTOP @@ -4136,9 +4435,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u TransportPinReminderView - Do you know your six-digit ID card PIN? + Do you know your 6-digit ID card PIN? LABEL ANDROID IOS - Вы знаете 6-значный PIN-код идентификационной карты? + Вы знаете 6-значный PIN-код своей идентификационной карты? No @@ -4151,14 +4450,14 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Да - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. LABEL ANDROID IOS - Онлайн-идентификация с помощью временного PIN-кода невозможна. Для использования функции eID необходим 6-значный PIN-код идентификационной карты, который пользователь создает самостоятельно. + Онлайн-идентификация с помощью временного PIN-кода невозможна. Для использования функции eID необходим 6-значный PIN-код идентификационной карты, который пользователь создает самостоятельно. - To set up a Smart-eID you also need to have assigned a six-digit PIN beforehand. + To set up a Smart-eID you also need to have assigned a 6-digit PIN beforehand. LABEL ANDROID IOS - + Чтобы настроить Smart-eID, необходимо предварительно задать 6-значный PIN-код. @@ -4230,16 +4529,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u UpdateViewButtonRow - - Skip update - LABEL DESKTOP User choice to skip this update, the automatic update check will *not* inform about this update again. - Пропустить обновление - - - Remind me later - LABEL DESKTOP The available update is shown again after next automatic update check. - Напомнить позже - Open App Store LABEL DESKTOP Open the Mac App Store on macOS @@ -4316,6 +4605,21 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ANDROID IOS Расширенные настройки деактивированы. + + Open website + LABEL DESKTOP + Открыть сайт + + + Privacy statement + LABEL DESKTOP + Положение о конфиденциальности + + + Accessibility statement + LABEL DESKTOP + Заявление о доступности + WhiteListSurveyView @@ -4364,14 +4668,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Отправить - - WorkflowInfoList - - The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. - INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. - Сопряжение устройства "%1" не было выполнено, поскольку оно не отвечало на попытки соединения. Снова выполните сопряжение устройства для его использования в качестве устройства чтения карт. - - governikus::AccessRoleAndRightsUtil @@ -4535,7 +4831,32 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Reason: INFO ALL_PLATFORMS Failure code (string) of current workflow error. - Причина + Причина: + + + Redirect failed + LABEL ALL_PLATFORMS + Сбой переадресации + + + Authentication failed + LABEL ALL_PLATFORMS + Сбой аутентификации + + + Authentication successful + LABEL ALL_PLATFORMS + Аутентификация выполнена успешно + + + Return to provider + LABEL ALL_PLATFORMS + Вернуться к провайдеру + + + Back to start page + LABEL ALL_PLATFORMS + Назад к начальной странице @@ -4799,12 +5120,12 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Сбой обнаружения антивируса. - Third party firewalls cannot be detected on Windows 7. + 3rd party firewalls cannot be detected on Windows 7. LABEL DESKTOP Невозможно обнаружить брандмауэры третьих сторон в Windows 7. - No third party firewalls detected + No 3rd party firewalls detected LABEL DESKTOP Брандмауэры третьих сторон не обнаружены @@ -4819,9 +5140,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Актуальное состояние: %1 - Firewalls from third party vendors + Firewalls from 3rd party vendors LABEL DESKTOP - Брандмауэры сторонних провайдеров + Брандмауэры сторонних поставщиков Outgoing %1 rule @@ -4896,7 +5217,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u dd.MM.yyyy, hh:mm:ss LABEL DESKTOP Datetime format according to https://doc.qt.io/qt/qdate.html#toString and https://doc.qt.io/qt/qtime.html#toString - dd.MM.yyyy, hh:mm:ss + дд.ММ.гггг, чч:мм:сс Last connection: %1 @@ -4963,6 +5284,11 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL DESKTOP Не привязано + + Encountered error: %1 + LABEL DESKTOP + Обнаруженная ошибка: %1 + governikus::ECardApiResult @@ -5355,9 +5681,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u PIN-код не заблокирован. - The entered PUK has already been used ten times and can no longer be used to unblock the PIN. + The entered PUK has already been used 10 times and can no longer be used to unblock the PIN. ERROR ALL_PLATFORMS The card declined the PUK since it was entered wrongfully 10 times. - Введенный PUK-код уже вводился десять раз и больше не может использоваться для разблокировки PIN-кода. + введенный PUK-код уже вводился 10 раз и больше не может использоваться для разблокирования PIN-кода. The new PIN and the confirmation do not match. @@ -5400,9 +5726,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Произошла ошибка при установке соединения со смартфоном, используемым в качестве устройства чтения карт (SaC). - The smartphone to be paired has rejected the connection. Please check the pairing code. If no pairing code is shown activate the pairing mode. + The smartphone to be paired has rejected the connection. Please check the pairing code. ERROR ALL_PLATFORMS The requested connection to the smartphone card reader (SaK) was rejected by the device. - Смартфон, предназначенный для сопряжения, отклонил соединение. Проверьте код сопряжения. Если код сопряжения не отображается, активируйте режим сопряжения. + Смартфон, предназначенный для сопряжения, отклонил соединение. Проверьте код сопряжения. File not found. @@ -5442,22 +5768,22 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Failed to get the ServiceInformation of the Smart-eID. ERROR ALL_PLATFORMS Failed to get the ServiceInformation of the Smart-eID - + Не удалось получить сервисную информацию о Smart-eID. The authentication to the personalization service failed. ERROR ALL_PLATFORMS No sessionID, required for a personalization, was received - + Сбой аутентификации в службе персонализации. - The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN three times. You may personalize a new Smart-eID to resolve the issue. + The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN 3 times. You may personalize a new Smart-eID to resolve the issue. ERROR ALL_PLATFORMS The existing Smart-eID was invalidated. - + Smart-eID больше не готова к использованию. Причиной может быть неправильный ввод PIN-кода для Smart-eID три раза. Вы можете персонализировать новую Smart-eID, чтобы устранить проблему. The preparation of the Smart-eID failed. ERROR ANDROID The preparation of the Smart-eID Applet failed - + Сбой подготовки Smart-eID. The program did not receive a StartPaosResponse message from the server. @@ -5467,22 +5793,22 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The server could not process the client request. ERROR_MASKED ALL_PLATFORMS - + Серверу не удалось обработать клиентский запрос. The service encountered an internal error while processing a request. ERROR ALL_PLATFORMS A server has responded with an HTTP error code 5xx. - + Служба столкнулась с внутренней ошибкой при обработке запроса. The service reported an error while processing a client request. ERROR ALL_PLATFORMS A server has responded with an HTTP error code 4xx. - + Служба сообщила об ошибке при обработке клиентского запроса. %1 Support LABEL ALL_PLATFORMS Link text to the app support. %1 is the app name. - %1 Support + %1 Поддержка @@ -5519,7 +5845,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u - governikus::LocalIfdReaderManagerPlugIn + governikus::LocalIfdReaderManagerPlugin Connection closed by remote with status: %1. Соединение закрыто дистанционно со статусом: %1. @@ -5595,82 +5921,120 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u hh:mm:ss LABEL ALL_PLATFORMS Time format according to https://doc.qt.io/qt/qtime.html#toString - hh:mm:ss + чч:мм:сс governikus::NumberModel - You have entered an incorrect, five-digit Transport PIN. You have two further attempts to enter the correct Transport PIN. - INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. - Вы ввели неправильный 5-значный временный PIN-код. Осталось две попытки ввода временного PIN-кода. + You have entered an incorrect, 6-digit Smart-eID PIN. You have <b>2 further attempts</b> to enter the correct Smart-eID PIN. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. + Вы ввели неправильный 6-значный PIN-код для Smart-eID. Осталось две попытки ввода PIN-кода для Smart-eID. - You have entered an incorrect, six-digit Smart-eID PIN. You have two further attempts to enter the correct Smart-eID PIN. - INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. - Вы ввели неправильный 6-значный PIN-код для Smart-eID. Осталось две попытки ввода PIN-кода для Smart-eID. + You have entered an incorrect, 5-digit Transport PIN 3 times, your <b>Transport PIN is now blocked</b>. To remove the block, the <b>10-digit PUK</b> must be entered first. + INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. + Вы трижды ввели неправильный 5-значный временный PIN-код; ваш временный PIN-код заблокирован. Для разблокирования сначала введите 10-значный PUK-код. - You have entered an incorrect, six-digit ID card PIN. You have two further attempts to enter the correct ID card PIN. - INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. - Вы ввели неправильный 6-значный PIN-код идентификационной карты. Осталось две попытки ввода PIN-кода идентификационной карты. + You have entered an incorrect, 6-digit Smart-eID PIN 3 times. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. + INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. + Вы трижды ввели неправильный 6-значный PIN-код для Smart-eID. Теперь ваша электронная идентификационная карта Smart-eID недействительна. Чтобы снова использовать электронную идентификационную карту Smart-eID, необходимо заново создать ее на начальной странице. - You have entered an incorrect, five-digit Transport PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. - Вы дважды ввели неправильный 5-значный временный PIN-код. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. + You have entered an incorrect, 10-digit PUK. Please try again. + INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. + Вы ввели неправильный 10-значный PUK-код. Повторите попытку. - You have entered an incorrect, six-digit ID card PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. - Вы дважды ввели неправильный 6-значный PIN-код идентификационной карты. Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. + You have entered an <b>incorrect, 6-digit Smart-eID PIN 2 times</b>. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a 3rd wrong attempt could invalidate the Smart-eID. + Вы дважды ввели неправильный 6-значный PIN-код для Smart-eID. После третьей попытки неправильного ввода вы больше не сможете использовать Smart-eID, и ее придется настроить еще раз. - You have entered an incorrect, five-digit Transport PIN thrice, your Transport PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Вы трижды ввели неправильный 5-значный временный PIN-код, ваш временный PIN-код заблокирован. Для разблокировки введите 10-значный PUK-код. + The input does not match. Please choose a new Smart-eID PIN. + ALL_PLATFORMS Error message if the new pin confirmation mismatches. + Введенные данные не совпадают. Выберите новый PIN-код для Smart-eID. - You have entered an incorrect, six-digit Smart-eID PIN thrice. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. - INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. - Вы трижды ввели неправильный 6-значный PIN-код для Smart-eID. Теперь ваша электронная идентификационная карта Smart-eID недействительна. Чтобы снова использовать электронную идентификационную карту Smart-eID, необходимо заново создать ее на начальной странице. + The input does not match. Please choose a new ID card PIN. + Введенные данные не совпадают. Выберите новый PIN-код идентификационной карты. + + + You have entered an incorrect, 6-digit ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 1/2 + Вы ввели неправильный 6-значный PIN-код идентификационной карты. + + + You have <b>2 further attempts</b> to enter the correct ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 2/2 + У вас осталось две попытки, чтобы ввести правильный PIN-код идентификационной карты. + + + You have entered an <b>incorrect, 6-digit ID card PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Вы дважды ввели неправильный 6-значный PIN-код идентификационной карты. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Вы трижды ввели неправильный 6-значный PIN-код идентификационной карты, PIN-код идентификационной карты заблокирован. Для разблокировки введите 10-значный PUK-код. + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN in the <b>bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 +---------- +INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 + Для третьей попытки сначала введите 6-значный код доступа (CAN). Код CAN указан внизу справа на передней стороне идентификационной карты. + + + You have entered an incorrect, 6-digit ID card PIN 3 times. Your <b>ID card PIN is now blocked</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 1/2 + Вы трижды ввели неправильный 6-значный PIN-код идентификационной карты. PIN-код идентификационной карты заблокирован. + + + To remove the block, the <b>10-digit PUK</b> must be entered first. You can find the PUK in the bottom <b>right next</b> to the Transport PIN in the <b>authority's letter</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 2/2 + Для разблокирования сначала введите 10-значный PUK-код. PUK-код указан возле временного PIN-кода внизу справа на передней стороне письма компетентного органа. - You have entered an incorrect, six-digit Card Access Number (CAN). Please try again. + You have entered an <b>incorrect Card Access Number (CAN)</b>. Please try again. You can find your CAN in the <b>bottom right on the front of your ID card</b>. INFO ALL_PLATFORMS The CAN was entered wrongfully and needs to be supplied again. - Вы ввели неправильный 6-значный код доступа (CAN). Повторите попытку. + Вы ввели неправильный код доступа (CAN). Повторите попытку. Код CAN указан внизу справа на передней стороне идентификационной капты. - You have entered an incorrect, ten-digit PUK. Please try again. - INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. - Вы ввели неправильный 10-значный PUK-код. Повторите попытку. + You have entered an incorrect, 5-digit Transport PIN. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. Part 1/2 + Вы ввели неправильный 5-значный временный PIN-код. - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a third wrong attempt could invalidate the Smart-eID. - + You have <b>2 further attempts</b> to enter the correct Transport PIN. The 5-digit Transport PIN may be found on the <b>bottom left of your PIN letter</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt.Part 2/2 + У вас осталось две попытки, чтобы ввести правильный временный PIN-код. 5-значный временный PIN код указан внизу слева в письме с PIN-кодом. - The input does not match. Please choose a new Smart-eID PIN. - ALL_PLATFORMS Error message if the new pin confirmation mismatches. - + You have entered an <b>incorrect, 5-digit Transport PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Вы дважды ввели неправильный 5-значный временный PIN-код. - The input does not match. Please choose a new ID card PIN. - + <b>An incorrect PIN has been entered 2 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 1/2 + <b>PIN-код дважды введен неправильно</b> при последнем использовании вашей идентификационной карты. + + + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN <b>in the bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 2/2 + Для третьей попытки сначала <b>введите 6-значный код доступа (CAN)</b>. Код CAN<b>указан внизу справа на передней стороне идентификационной карты</b>. + + + <b>An incorrect PIN has been entered 3 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 1/2 + <b>PIN-код трижды введен неправильно</b> при последнем использовании вашей идентификационной карты. + + + Therefor you have to enter the <b>PUK</b> first to <b>unlock the ID card PIN</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 2/2 + Для этого введите сначала <b>PUK-код</b>, чтобы <b>разблокировать PIN-код идентификационной карты</b>. governikus::PinResetInformationModel - - https://www.personalausweisportal.de/EN - https://www.personalausweisportal.de/EN - You cannot use the PUK to reset your previously set card PIN. If you forgot your card PIN, you can use the PIN Reset Service to request a new PIN. LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. @@ -5681,20 +6045,71 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ALL_PLATFORMS Перейти к службе сброса PIN-кода - - You can request activation of the eID function without charge. - LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated - Вы можете запросить активацию функции eID без дополнительной оплаты. - Go to Activation Service LABEL ALL_PLATFORMS Перейти к службе активации - Request a new card PIN free of charge to be able to use the eID function again. + Find competent authority + LABEL ALL_PLATFORMS + Найти компетентный орган + + + To find your competent authority you may visit servicesuche.bund.de. + Найти нужный компетентный орган можно на сайте servicesuche.bund.de. + + + If you don't have your Transport PIN letter and no access to the PUK, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. + Если вы не получили письмо с временным PIN-кодом и у вас нет доступа к PUK-коду, можно обратиться в компетентный орган и там задать новый PIN-код идентификационной карты. + + + You may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK +---------- +LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Вы можете обратиться в компетентный орган и там установить новый PIN-код идентификационной карты. + + + Please contact the competent authority to activate the eID function. + LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + Свяжитесь с компетентным органом, чтобы активировать функцию eID. + + + If you know neither your Transport PIN nor your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Если вы не знаете ни своего временного PIN-кода, ни PIN-кода идентификационной карты, можно обратиться в компетентный орган и там задать новый PIN-код идентификационной карты. + + + If you cannot recall your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Если вы не можете вспомнить PIN-код идентификационной карты, можно обратиться в компетентный орган и там задать новый PIN-код идентификационной карты. + + + Request a new card PIN to be able to use the eID function again. LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK - Запросите новый PIN-код карты бесплатно, чтобы снова иметь возможность использовать функцию eID. + Запросите новый PIN-код карты, чтобы снова иметь возможность использовать функцию eID. + + + You can request activation of the eID function. + LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + Вы можете запросить активацию функции eID. + + + You can use the PIN Reset Service to request a new card PIN. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Вы можете воспользоваться службой сброса PIN-кода, чтобы запросить новый PIN-код карты. + + + If you do not know either your Transport PIN or your card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Если вы не знаете ни своего временного PIN-кода, ни PIN-кода карты, можно запросить новый PIN-код, воспользовавшись службой сброса PIN-кода. + + + If you have forgotten your ID card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Если вы забыли PIN-код идентификационной карты, можно запросить новый PIN-код, воспользовавшись службой сброса PIN-кода. @@ -5807,6 +6222,11 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ALL_PLATFORMS Нажмите для сопряжения + + was + LABEL ALL_PLATFORMS Describes the former name of the device and is shown as: "New_Name (was Old_Name)" + прежнее название + governikus::RemoteServiceModel @@ -5823,15 +6243,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The NFC radio standard is required for communication with the ID card. -Unfortunately NFC is not available on your device. - INFO ALL_PLATFORMS The device does not offer NFC. - Для обмена данными с идентификационной картой требуется стандарт радиосвязи NFC. - -К сожалению, NFC недоступен на вашем устройстве. - - - The NFC radio standard is required for communication with the ID card. - Please enable NFC to use your smartphone as a card reader (SaC). INFO ALL_PLATFORMS NFC is available but not active. Для обмена данными с идентификационной картой требуется стандарт радиосвязи NFC. @@ -5839,9 +6250,19 @@ Please enable NFC to use your smartphone as a card reader (SaC). Активируйте NFC, чтобы использовать смартфон в качестве устройства чтения карт (SaC). - Pairing with %1 successful. - LABEL ALL_PLATFORMS - Сопряжение с %1 выполнено успешно. + This device cannot be used to read your ID card. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + @@ -5867,17 +6288,19 @@ Please enable NFC to use your smartphone as a card reader (SaC). dd.MM.yyyy LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString - dd.MM.yyyy + дд.ММ.гггг xx.MM.yyyy - LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day - xx.MM.yyyy + LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day +---------- +LABEL ALL_PLATFORMS Additional date format with unknown day + хх.ММ.гггг xx.xx.yyyy LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day and month - xx.xx.yyyy + хх.хх.гггг Family name @@ -5945,72 +6368,72 @@ Please enable NFC to use your smartphone as a card reader (SaC). The online check for the Smart-eID support on your device failed. Please note that this process requires an internet connection. ERROR ANDROID IOS The check for Smart-eID support failed without any specific reason. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством. Обратите внимание на то, что для данного процесса требуется интернет-соединение. The online check for the Smart-eID support on your device failed because the server is currently facing too many requests. Please try again later. ERROR ANDROID IOS The check for Smart-eID support failed because the server is overloaded. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством, поскольку в данный момент на сервер поступает слишком много запросов. Повторите попытку позднее. The online check for the Smart-eID support on your device failed because the server is currently under maintenance. Please try again later. ERROR ANDROID IOS The check for Smart-eID support failed because the server is being maintained. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством из-за технических работ на сервере. Повторите попытку позднее. The Smart-eID data and provisioning could not be successfully deleted from your device. Please note that this process requires an internet connection. ERROR ANDROID IOS Deletion of the Smart-eID failed without a specific reason. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства. Обратите внимание на то, что для данного процесса требуется интернет-соединение. The Smart-eID data and provisioning could not be successfully deleted from your device because the server is currently facing too many requests. Please try again later. ERROR ANDROID IOS Deletion of the Smart-eID failed because the server is overloaded. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства, поскольку в данный момент на сервер поступает слишком много запросов. Повторите попытку позднее. The Smart-eID data and provisioning could not be successfully deleted from your device because the server is currently under maintenance. Please try again later. ERROR ANDROID IOS Deletion of the Smart-eID failed because the server is being maintained. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства из-за технических работ на сервере. Повторите попытку позднее. The Smart-eID data and provisioning could not be successfully deleted from your device. In order to access the necessary device storage, active NFC functionality is required. Please activate NFC and restart the process. ERROR ANDROID IOS Deletion of the Smart-eID failed because NFC is not activated. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства. Для доступа к требуемой памяти устройства необходимо активировать функцию NFC. Активируйте NFC и перезапустите процесс. The online check for the Smart-eID support on your device failed. In order to access the necessary device storage, active NFC functionality is required. Please activate NFC and try again. ERROR ANDROID IOS The check for Smart-eID support failed because the NFC functionality is not activated. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством. Для доступа к требуемой памяти устройства необходимо активировать функцию NFC. Активируйте NFC и повторите попытку. The online check for the Smart-eID support on your device failed. The Google Play Integrity Check failed. ERROR ANDROID IOS The check for Smart-eID support failed because Google Play Integrity Check failed. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством. Сбой проверки целостности Google Play. The online check for the Smart-eID support on your device failed. An authentication issue occurred (e.g. a resource was accessed without authorization or an unauthorized app tried to access a security component). ERROR ANDROID IOS The check for Smart-eID support failed because an authorization issue occurred. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством. Возникла проблема при аутентификации (например, доступ к ресурсу получен без авторизации, или неавторизованное приложение попыталось получить доступ к компоненту безопасности). The Smart-eID data and provisioning could not be successfully deleted from your device. The Google Play Integrity Check failed. ERROR ANDROID IOS Deletion of the Smart-eID failed because the Google Play Integrity Check failed. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства. Сбой проверки целостности Google Play. The Smart-eID data and provisioning could not be successfully deleted from your device. An authentication issue occurred (e.g. a resource was accessed without authorization or an unauthorized app tried to access a security component). ERROR ANDROID IOS Deletion of the Smart-eID failed because an authorization issue occurred. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства. Возникла проблема при аутентификации (например, доступ к ресурсу получен без авторизации, или неавторизованное приложение попыталось получить доступ к компоненту безопасности). The online check for the Smart-eID support on your device failed. Please ensure that you have an internet connection and your antivirus software and firewall are not blocking the connection. ERROR ANDROID IOS The check for Smart-eID support failed because a network connection error occurred. - + Сбой онлайн-проверки поддержки Smart-eID вашим устройством. Убедитесь в том, что установлено интернет-соединение и что антивирусное ПО и брандмауэр не блокируют соединение. The Smart-eID data and provisioning could not be successfully deleted from your device. Please ensure that you have an internet connection and your antivirus software and firewall are not blocking the connection. ERROR ANDROID IOS Deletion of the Smart-eID failed because a network connection error occurred. - + Невозможно удалить данные и подготовку Smart-eID из вашего устройства. Убедитесь в том, что установлено интернет-соединение и что антивирусное ПО и брандмауэр не блокируют соединение. @@ -6036,15 +6459,10 @@ Please enable NFC to use your smartphone as a card reader (SaC). governikus::StateConnectCard - - The used card reader does not meet the technical requirements (Extended Length not supported). - INFO IOS - Используемое устройство чтения карт не соответствует техническим требованиям (не поддерживается расширенная длина). - The used ID card type is not accepted by the server. INFO IOS - + Тип используемой идентификационной карты не принимается сервером. @@ -6052,7 +6470,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). Cleaning up old Smart-eID LABEL ANDROID IOS - Очистка старой Smart-eID + Очистка старой Smart-eID @@ -6139,7 +6557,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). Installing Smart-eID LABEL ANDROID IOS - Установка Smart-eID + Установка Smart-eID @@ -6158,10 +6576,10 @@ Please enable NFC to use your smartphone as a card reader (SaC). - remove the mobile phone case (if present) - connect the smartphone with a charging cable INFO The NFC signal is weak or unstable. The scan is stopped with this information in the iOS dialog. - Слабый сигнал NFC. Выполните следующее. -— Измените положение карты. -— Снимите чехол с мобильного телефона (при наличии). -— Подключите смартфон к зарядному кабелю. + Слабый сигнал NFC. Выполните следующее: +- Измените положение карты +- Снимите чехол с мобильного телефона (при наличии) +- Подключите смартфон к зарядному кабелю @@ -6169,11 +6587,11 @@ Please enable NFC to use your smartphone as a card reader (SaC). Checking Smart-eID status LABEL ANDROID IOS - Проверка статуса Smart-eID + Проверка статуса Smart-eID - governikus::SurveyModel + governikus::Survey Vendor Производитель @@ -6230,21 +6648,21 @@ Please enable NFC to use your smartphone as a card reader (SaC). - governikus::UIPlugInProxy + governikus::UiPluginProxy Reverse proxy plugin is enabled Активирован плагин обратного прокси-сервера - governikus::UIPlugInQml + governikus::UiPluginQml Information Информация - governikus::UIPlugInWebService + governikus::UiPluginWebService An unknown program uses the required port (%1). Please exit the other program and try again! ERROR ALL_PLATFORMS An unknown programme is using the local port on which the AA2 listens. @@ -6320,9 +6738,9 @@ Please enable NFC to use your smartphone as a card reader (SaC). Сообщить сейчас - The connection to the browser was lost. No forwarding was executed. Please try to call the URL again manually: %1 + The connection to the browser was lost while redirecting to the provider (%1). No automatic redirection could be performed. ERROR ALL_PLATFORMS The connection to the browser was lost/timed out.. - Прервано соединение с браузером. Не удалось выполнить переадресацию. Повторите попытку вызвать URL вручную: %1 + При перенаправлении к провайдеру (%1) было потеряно соединение с браузером. Не удалось выполнить автоматическое перенаправление. @@ -6338,109 +6756,32 @@ Please enable NFC to use your smartphone as a card reader (SaC). The used Smart-eID is not accepted by the server. Please restart the remote service on your connected smartphone and try again with a physical ID card. INFO ALL_PLATFORMS - + Используемая Smart-eID не принимается сервером. Перезапустите удаленную службу в подключенном смартфоне и повторите попытку, используя физическую идентификационную карту. The used Smart-eID is not accepted by the server. Please stop the remote service and use another Smart-eID or contact the service provider. INFO ALL_PLATFORMS - + Используемая Smart-eID не принимается сервером. Остановите удаленную службу и используйте другую Smart-eID или свяжитесь с провайдером услуг. The used ID card is not accepted by the server. Please remove the ID card from your device or card reader and use a Smart-eID or contact the service provider. INFO ALL_PLATFORMS - + Используемая идентификационная карта не принимается сервером. Удалите идентификационную карту из вашего устройства или из устройства чтения карт и используйте Smart-eID или свяжитесь с провайдером услуг. Renew your Smart-eID and set a new PIN in the Smart-eID menu. LABEL ANDROID IOS The hint text that is shwon right above the redirect button that appears when a user tried to usa an unusable Smart-eID - + Обновите Smart-eID и установите новый PIN-код в меню Smart-eID. Go to Smart-eID menu LABEL ANDROID IOS The text on the redirect button that appears when the user tried to use an unusable Smart-eID - - - - - main - - Another application uses %1 - INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. - Другое приложение использует %1 - - - The user interface of the %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. - Пользовательский интерфейс %1 закрыт. - - - The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. - Программа по-прежнему доступна через значок на панели задач. Нажмите на символ %1, чтобы снова открыть пользовательский интерфейс. - - - Do not show this dialog again. - LABEL DESKTOP - Не показывать этот диалог снова. - - - This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. - Текущий процесс будет прерван, а пользовательский интерфейс %1 скрыт. Вы можете перезапустить процесс в любое время. - - - Abort operation - INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active - Отмена операции - - - Failed to retrieve update information. - INFO DESKTOP Message that the update data is invalid and can't be used. - Сбой загрузки информации об обновлении. - - - An update is available (version %1). - INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. - Доступно обновление (версия %1). - - - Developer Mode: Enabled! - LABEL DESKTOP - Режим разработчика: активирован! - - - Disable - LABEL DESKTOP Global button to disable developer mode. - Деактивировать - - - Detached log viewer - Средство просмотра файлов журнала - - - To close the app, quickly press the back button twice. - INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). - Чтобы закрыть приложение, дважды быстро нажмите кнопку «Назад». - - - The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. - Программа по-прежнему доступна через значок в строке меню. Нажмите на символ %1, чтобы снова открыть пользовательский интерфейс. - - - The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. - INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. - + Перейти в меню Smart-eID - The %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. - - - - This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. - INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. - + Set a new PIN + LABEL ALL_PLATFORMS Hint title to assist the user on how to set a new PIN + Установите новый PIN-код diff --git a/resources/translations/ausweisapp2_uk.ts b/resources/translations/ausweisapp_uk.ts similarity index 76% rename from resources/translations/ausweisapp2_uk.ts rename to resources/translations/ausweisapp_uk.ts index 87240c9bc..8760377cb 100644 --- a/resources/translations/ausweisapp2_uk.ts +++ b/resources/translations/ausweisapp_uk.ts @@ -4,8 +4,14 @@ DvcsAttributes - revision - 56dc58807a8c + 828ae9a4549a + revision + 828ae9a4549a + + + 2.2.0 + version + 2.2.0 @@ -26,6 +32,88 @@ Виявлено проблеми з мережею, виконується спроба зв’язатися з сервером протягом 30 секунд. + + App + + The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. + Програма залишається доступною через піктограму на панелі меню. Натисніть піктограму %1, щоб знову відкрити інтерфейс користувача. + + + The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. + Програма залишається доступною через піктограму в системному лотку. Натисніть піктограму %1, щоб знову відкрити інтерфейс користувача. + + + Another application uses %1 + INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. + Інша програма використовує %1 + + + The user interface of the %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. + Інтерфейс користувача %1 закрито. + + + Do not show this dialog again. + LABEL DESKTOP + Більше не показувати це діалогове вікно. + + + The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. + INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. + Програму %1 буде вимкнено, і автентифікація більше не буде можливою. Щоб ідентифікувати себе для постачальника послуг, вам потрібно буде перезапустити програму %1. + + + The %1 is closed. + INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. + Програму %1 закрито. + + + This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. + INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. + Це скасує поточну операцію та приховає інтерфейс користувача %1. Ви можете перезапустити операцію в будь-який час. + + + This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. + INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. + Це скасує поточну операцію та вимкне програму %1. Щоб перезапустити операцію, потрібно перезапустити програму %1. + + + Abort operation + INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active + Перервати операцію + + + Failed to retrieve update information. + INFO DESKTOP Message that the update data is invalid and can't be used. + Не вдалося отримати інформацію про оновлення. + + + An update is available (version %1). + INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. + Доступне оновлення (версія %1). + + + Developer Mode: Enabled! + LABEL DESKTOP + Режим розробника: Увімкнено! + + + Disable + LABEL DESKTOP Global button to disable developer mode. + Вимкнути + + + Detached log viewer + Відключений засіб перегляду журналів + + + To close the app, press the back button 2 times. + INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). + Щоб закрити програму, 2 рази натисніть кнопку «Назад». + + AuthController @@ -64,9 +152,9 @@ Зверніть увагу на дисплей свого пристрою читання карток. - A wrong PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO ANDROID IOS The PIN was entered wrongfully two times, the third attempts requires additional CAN verification, hint where the CAN is found. - На вашій ID-картці двічі введено неправильний PIN-код. Для третьої спроби спочатку введіть шестизначний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + A wrong PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + INFO ANDROID IOS The PIN was entered wrongfully two times, the 3rd attempts requires additional CAN verification, hint where the CAN is found. + На вашій ID-картці 2 рази введено неправильний PIN-код. Для 3-ї спроби спочатку введіть 6-значний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. Send log @@ -78,6 +166,16 @@ LABEL ANDROID IOS A11y button to confirm the PIN and start the provider authentication Виконайте автентифікацію у провайдера + + Authentication failed + LABEL ANDROID IOS + Не вдалося виконати автентифікацію + + + Return to provider + LABEL ANDROID IOS + Повернутися до постачальника + AuthView @@ -163,12 +261,12 @@ INFO DESKTOP Generic progress status message during authentication.Виконайте автентифікацію у провайдера - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. - Онлайн-ідентифікація за допомогою транспортного PIN-коду неможлива. Самостійно обраний шестизначний PIN-код ID-картки обов’язковий для використання функції eID. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. + Онлайн-ідентифікація за допомогою транспортного PIN-коду неможлива. Самостійно обраний 6-значний PIN-код ID-картки обов’язковий для використання функції eID. - Do you know your six-digit ID card PIN? - Ви знаєте шестизначний PIN-код своєї ID-картки? + Do you know your 6-digit ID card PIN? + Ви знаєте 6-значний PIN-код своєї ID-картки? The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. @@ -275,8 +373,9 @@ INFO DESKTOP Generic progress status message during authentication. CardReaderDelegate - Press space to open the link in your browser - Натисніть пробіл, щоб відкрити посилання у браузері + Press space to open link. + INFO DESKTOP Text read by screen reader if the text contains a web link to a card reader driver which may be opened. + Натисніть пробіл, щоб відкрити посилання. @@ -300,7 +399,11 @@ INFO DESKTOP Generic progress status message during authentication. No connected card reader found. - + Не знайдено підключеного пристрою читання карток. + + + List of connected card readers. + Перелік підключених пристроїв читання карток. @@ -315,11 +418,6 @@ LABEL ANDROID IOS ChangePinController - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO ANDROID IOS The ID card has just been unblocked and the user can now continue with their PIN change. - PIN-код вашої ID-картки розблоковано. Тепер у вас є ще три спроби змінити PIN-код. - Setting new Smart-eID PIN LABEL ANDROID IOS Processing screen label while the card communication is running after the new Smart-eID PIN has been entered during PIN change process. @@ -356,19 +454,19 @@ LABEL ANDROID IOS Зверніть увагу на дисплей свого пристрою читання карток. - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. + A wrong ID card PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. INFO ANDROID IOS The wrong ID card PIN was entered twice, the next attempt requires additional verifcation via CAN. - На вашій ID-картці було двічі введено неправильний PIN-код. Для третьої спроби спочатку введіть шестизначний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + На вашій ID-картці було 2 рази введено неправильний PIN-код. Для 3-ї спроби спочатку введіть 6-значний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. + You have entered an incorrect, 6-digit ID card PIN 3 times, your ID card PIN is now blocked. To remove the block, the 10-digit PUK must be entered first. INFO ANDROID IOS The ID card PIN (including the CAN) was entered wrongfully three times, the PUK is required to unlock the ID card. - Ви тричі ввели неправильний шестизначний PIN-код ID-картки. Тепер PIN-код вашої ID-картки заблоковано. Щоб видалити блокування, потрібно спочатку ввести десятизначний PUK-код. + Ви 3 рази ввели неправильний 6-значний PIN-код ID-картки. Тепер PIN-код вашої ID-картки заблоковано. Щоб видалити блокування, потрібно спочатку ввести 10-значний PUK-код. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO ANDROID IOS - Зверніть увагу, що ви можете використати п’ятизначний транспортний PIN-код лише один раз, щоб змінити його на шестизначний PIN-код ID-картки. Якщо ви вже встановили шестизначний PIN-код ID-картки, п’ятизначний транспортний PIN-код більше не дійсний. + Back to start page + LABEL ANDROID IOS + Повернутися до початкової сторінки @@ -392,11 +490,6 @@ LABEL ANDROID IOS INFO DESKTOP Processing screen text while the card communication is running after the PIN has been entered during PIN change process. Не рухайте ID-картку. - - Your ID card PIN is unblocked. You now have three more attempts to change your PIN. - INFO DESKTOP The ID card has just been unblocked and the user can now continue with their ID card PIN change. - PIN-код вашої ID-картки розблоковано. Тепер у вас є ще три спроби змінити PIN-код. - Weak NFC signal. Please - change the card position @@ -417,20 +510,15 @@ LABEL ANDROID IOS - переконайтеся, що картку правильно розміщено на пристрої читання; - не переміщуйте картку, поки до неї здійснюється доступ - - Change Transport PIN - LABEL ANDROID IOS - Змінити транспортний PIN-код - The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. INFO DESKTOP The paired devices was removed since it did not respond to connection attempts. It needs to be paired again if it should be used as card reader. Пару з пристроєм «%1» було скасовано, оскільки він не реагував на спроби підключення. Створіть пару з пристроєм знову, щоб використовувати його як пристрій читання карток. - Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid. - INFO DESKTOP - Зверніть увагу, що ви можете використати п’ятизначний транспортний PIN-код лише один раз, щоб змінити його на шестизначний PIN-код ID-картки. Якщо ви вже встановили шестизначний PIN-код ID-картки, п’ятизначний транспортний PIN-код більше не дійсний. + Back to start page + LABEL DESKTOP + Повернутися до початкової сторінки @@ -441,24 +529,24 @@ LABEL ANDROID IOS Якого типу ваш PIN-код? - Six-digit PIN + 6-digit PIN LABEL ALL_PLATFORMS - Шестизначний PIN-код + 6-значний PIN-код - Set by yourself + Set by yourself or received by the PIN Reset Service LABEL ALL_PLATFORMS - Встановлений вами самостійно + Встановлений вами самостійно - Five-digit Transport PIN + 5-digit Transport PIN LABEL ALL_PLATFORMS - П’ятизначний транспортний PIN-код + 5-значний транспортний PIN-код - Received by mail in PIN letter + Received by letter while ordering your ID card LABEL ALL_PLATFORMS - Отриманий поштою в листі з PIN-кодом + Отриманий поштою в листі з PIN-кодом No PIN @@ -560,16 +648,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Доступ до ID-картки успішно отримано - - Online identification feature disabled - LABEL ANDROID IOS - Функцію онлайн-ідентифікації вимкнено - - - Online identification feature enabled - LABEL ANDROID IOS - Функцію онлайн-ідентифікації ввімкнено - ID card PIN suspended LABEL ANDROID IOS @@ -585,6 +663,16 @@ LABEL ANDROID IOS LABEL ANDROID IOS Функціональна ID-картка + + eID function disabled + LABEL ANDROID IOS + Функцію eID вимкнено + + + eID function enabled + LABEL ANDROID IOS + Функцію eID увімкнено + CheckIDCardSuggestionView @@ -599,9 +687,9 @@ LABEL ANDROID IOS Немає NFC - Your mobile device has no NFC interface. This is required to read the ID card. However, you can use a separate smartphone as card reader to utilize the eID function.<br><br>You can find smartphones compatible with the %1 on our website. + Your mobile device has no NFC interface. This is required to read the ID card. To use the eID function on this device you may pair a NFC capable smartphone as a card reader.<br><br>To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>.<br><br>You can find smartphones compatible with the %1 on our website. LABEL ANDROID IOS - Ваш мобільний пристрій не має інтерфейсу NFC. Він потрібен для читання ID-картки. Однак ви можете використовувати окремий смартфон як пристрій читання карток, щоб застосовувати функцію eID.<br><br>Ви можете знайти смартфони, сумісні з %1, на нашому сайті. + Ваш мобільний пристрій не має інтерфейсу NFC. Він потрібен для читання ID-картки. Однак ви можете використовувати окремий смартфон як пристрій читання карток, щоб застосовувати функцію eID.<br><br>Ви можете знайти смартфони, сумісні з %1, на нашому сайті. Open website @@ -613,11 +701,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Підтримувану картку не виявлено - - No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check.<br><br>Tip: Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. - LABEL ANDROID IOS - Жодної підтримуваної ID-картки не було виявлено. Програма %1 підтримує:<p><ul><li>Німецькі ID-картки</li><li>Електронні посвідки на проживання (eAT)</li><li>Картки eID</li></ul></p>Якщо ви скористалися одним із вищезазначених документів, але це повідомлення про помилку все одно з’являється, перезапустіть перевірку.<br><br>Порада. Спробуйте змінити положення картки, не рухайте ID-картку під час перевірки та переконайтеся, що поблизу пристрою немає інших карток NFC (наприклад, кредитних карток). - Retry LABEL ANDROID IOS @@ -643,11 +726,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Не вдалося встановити стабільне з’єднання з вашою ID-карткою.<br><br>Почніть перевірку ще раз. Спробуйте змінити положення картки та не рухайте її під час тесту.<br><br>Якщо з’єднання з ID-карткою не вдається встановити навіть у різних положеннях, це означає, що інтерфейс NFC вашого мобільного пристрою не може забезпечити ID-картку достатньою потужністю.<br><br>Ви можете знайти смартфони, сумісні з %1, на нашому <a href="%2">сайті</a>. - - Online identification feature disabled - LABEL ANDROID IOS - Функцію онлайн-ідентифікації вимкнено - OK LABEL ANDROID IOS @@ -659,9 +737,9 @@ LABEL ANDROID IOS PIN-код ID-картки призупинено - The ID card PIN has been entered incorrectly twice in a row. This is why you must first enter the six-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. + The ID card PIN has been entered incorrectly 2 times in a row. This is why you must first enter the 6-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.<br><br>You may now try the function: "See my personal data". There you can also use the CAN to unblock the ID card PIN. LABEL ANDROID IOS - PIN-код ID-картки було введено неправильно двічі поспіль. Тому для наступного процесу ідентифікації вам потрібно спочатку ввести шестизначний номер доступу до картки (CAN). Ви можете знайти його в нижньому правому куті на лицьовому боці своєї ID-картки.<br><br>Тепер ви можете спробувати скористатися функцією: «Дивитися мої особисті дані». Там ви також зможете скористатися номером CAN, щоб розблокувати PIN-код ID-картки. + PIN-код ID-картки було введено неправильно 2 рази поспіль. Тому для наступного процесу ідентифікації вам потрібно спочатку ввести 6-значний номер доступу до картки (CAN). Ви можете знайти його в нижньому правому куті на лицьовому боці своєї ID-картки.<br><br>Тепер ви можете спробувати скористатися функцією: «Дивитися мої особисті дані». Там ви також зможете скористатися номером CAN, щоб розблокувати PIN-код ID-картки. Continue @@ -674,9 +752,34 @@ LABEL ANDROID IOS PIN-код ID-картки заблоковано - The ID card PIN has been entered incorrectly thrice. Therefore, you must first enter the ten-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + The ID card PIN has been entered incorrectly 3 times. Therefore, you must first enter the 10-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.<br><br>You may now try the function: "See my personal data". Have your PUK ready to unlock the ID card PIN. + LABEL ANDROID IOS + PIN-код ID-картки було введено неправильно 3 рази. Тому під час наступного процесу автентифікації вам спочатку буде потрібно ввести 10-значний PUK-код. Ви можете знайти його в листі з PIN-кодом, який ви отримали після подання заявки на отримання ID-картки.<br><br>Тепер ви можете спробувати скористатися функцією: «Дивитися мої особисті дані». Підготуйте PUK-код для розблокування PIN-коду ID-картки. + + + Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device. + LABEL ANDROID IOS + Спробуйте змінити положення картки, не рухайте ID-картку під час перевірки та переконайтеся, що поблизу пристрою немає інших карток NFC (наприклад, кредитних карток). + + + No supported ID card was detected. The %1 supports:<p><ul><li>German ID cards</li><li>Electronic residence permits (eAT)</li><li>eID cards for citizen of the EU/EEA/</li></ul></p>If you have used one of the above documents and this error message still appears, please restart the check. + LABEL ANDROID IOS + Жодної підтримуваної ID-картки не було виявлено. Програма %1 підтримує:<p><ul><li>Німецькі ID-картки</li><li>Електронні посвідки на проживання (eAT)</li><li>Картки eID для громадян ЄС/ЄЕЗ</li></ul></p>Якщо ви скористалися одним із вищезазначених документів, але це повідомлення про помилку все одно з’являється, перезапустіть перевірку. + + + eID function disabled + LABEL ANDROID IOS + Функцію eID вимкнено + + + Activate the eID function. + LABEL ANDROID IOS Hint when a workflow failed because the eID function was not activated + Активуйте функцію eID. + + + List of compatible devices LABEL ANDROID IOS - PIN-код ID-картки було введено неправильно тричі. Тому під час наступного процесу автентифікації вам спочатку буде потрібно ввести десятизначний PUK-код. Ви можете знайти його в листі з PIN-кодом, який ви отримали після подання заявки на отримання ID-картки.<br><br>Тепер ви можете спробувати скористатися функцією: «Дивитися мої особисті дані». Підготуйте PUK-код для розблокування PIN-коду ID-картки. + @@ -692,9 +795,9 @@ LABEL ANDROID IOS Для використання функції онлайн-ідентифікації ваш пристрій має відповідати певним технічним вимогам. Крім того, має бути активовано функцію онлайн-ідентифікації. - Check if your smartphone and ID card are ready for use. + Check if your device & ID card are ready for use LABEL ANDROID IOS - Перевірте, чи ваш смартфон та ID-картка готові до використання. + Перевірте, чи ваш пристрій та ID-картка готові до використання Start check @@ -725,92 +828,92 @@ LABEL ANDROID IOS Unknown result code: %1 LABEL ANDROID IOS - Невідомий код результату: %1 + Невідомий код результату: %1 Please wait a moment. LABEL ANDROID IOS - Трохи зачекайте. + Трохи зачекайте. Updating Smart-eID status... LABEL ANDROID IOS - Триває оновлення статусу Smart-eID… + Триває оновлення статусу Smart-eID… Check device and ID card LABEL ANDROID IOS - Перевірити пристрій та ID-картку + Перевірити пристрій та ID-картку Your mobile device does not meet the technical requirements for Smart-eID.<br><br>You may check if your device and ID card are suitable to use the eID function. LABEL ANDROID IOS - Ваш мобільний пристрій не відповідає технічним вимогам щодо Smart-eID.<br><br>Ви можете перевірити, чи підходять ваш пристрій та ID-картка для використання функції eID. + Ваш мобільний пристрій не відповідає технічним вимогам щодо Smart-eID.<br><br>Ви можете перевірити, чи підходять ваш пристрій та ID-картка для використання функції eID. Smart-eID not supported LABEL ANDROID IOS - Smart-eID не підтримується + Smart-eID не підтримується Possible causes are: LABEL ANDROID IOS - Можливі причини: + Можливі причини: The setup has not been completed. LABEL ANDROID IOS - Налаштування не завершено. + Налаштування не завершено. - The Smart-eID PIN has been entered incorrectly three times. + The Smart-eID PIN has been entered incorrectly 3 times. LABEL ANDROID IOS - PIN-код Smart-eID було введено неправильно тричі. + PIN-код Smart-eID було введено неправильно 3 рази. The %1 has been uninstalled temporarily. LABEL ANDROID IOS - Програму %1 тимчасово видалено. + Програму %1 тимчасово видалено. You may continue with the setup of the Smart-eID. LABEL ANDROID IOS - + Ви можете продовжити налаштування Smart-eID. Continue LABEL ANDROID IOS - Продовжити + Продовжити Your device meets the technical requirements for Smart-eID. You may now continue the setup process. LABEL ANDROID IOS - + Ваш пристрій відповідає технічним вимогам щодо Smart-eID. Тепер ви можете продовжити процес налаштування. Smart-eID supported LABEL ANDROID IOS - + Smart-eID підтримується Your device meets the technical requirements for Smart-eID, however, the Smart-eID that was set up is invalid. LABEL ANDROID IOS LABEL ANDROID IOS - + Ваш пристрій відповідає технічним вимогам щодо Smart-eID, але налаштований Smart-eID є недійсним. Smart-eID invalid LABEL ANDROID IOS - + Smart-eID недійсний Smart-eID check failed LABEL ANDROID IOS - + Не вдалося перевірити Smart-eID Back LABEL ANDROID IOS - Назад + Назад @@ -825,54 +928,55 @@ LABEL ANDROID IOS LABEL DESKTOP Створення пари з пристроєм… - - Pairing to "%1" failed: - ERROR DESKTOP An error occurred while pairing the device. - Не вдалося створити пару з пристроєм «%1»: - DarkModeButtons System LABEL ALL_PLATFORMS - Система + Система Dark LABEL ALL_PLATFORMS - + Темний Light LABEL ALL_PLATFORMS - + Світлий Set the app appearance to system mode LABEL ALL_PLATFORMS - + Налаштувати зовнішній вигляд програми відповідно на режим системи Set the app appearance to dark mode LABEL ALL_PLATFORMS - + Налаштувати зовнішній вигляд програми на темний режим Set the app appearance to light mode LABEL ALL_PLATFORMS - + Налаштувати зовнішній вигляд програми на світлий режим DataGroup - selected - вибрано + %1, optional right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + - not selected - не вибрано + %1, required right, element %2 of %3 + LABEL DESKTOP +---------- +LABEL ANDROID IOS + @@ -905,12 +1009,12 @@ LABEL ANDROID IOS Reset hideable dialogs LABEL DESKTOP - + Скинути приховані діалоги Show Transport PIN reminder, store feedback and close reminder dialogs. LABEL DESKTOP - + Показувати нагадування про транспортний PIN-код, зберігати відгуки й закривати діалоги з нагадуваннями. @@ -930,11 +1034,13 @@ LABEL ANDROID IOS DetachedLogView Select log: + LABEL DESKTOP Виберіть журнал: - Font size: - Розмір шрифту: + Zoom: + LABEL DESKTOP + Збільшення: Save log @@ -1027,17 +1133,17 @@ LABEL ANDROID IOS Allow test sample card usage LABEL DESKTOP - + Дозволити використання картки тестового зразка Internal card simulator LABEL DESKTOP - Внутрішній симулятор картки + Внутрішній симулятор картки The developer mode deactivates some security checks and the authentication process will continue even if some errors occur. Skipped errors will be shown as notifications. The developer mode is only usable with the test PKI. LABEL DESKTOP - Режим розробника орієнтований на інтеграторів/розробників нових сервісних програм. Тому режим розробника працює лише в тестовій PKI. Після активації режиму розробника деякі тести безпеки деактивуються. Це означає, що процес автентифікації продовжується, хоча під час використання в нормальному режимі роботи програма %1 зазвичай перериває процес із повідомленням про помилку. Інформація про проігноровану помилку в режимі розробника відображається в прикріпленому вікні під програмою %1. + Режим розробника деактивує деякі перевірки безпеки, а процес автентифікації продовжиться, навіть якщо виникнуть помилки. Пропущені помилки будуть показані як сповіщення. Режим розробника можна використовувати лише з тестовою PKI. @@ -1072,20 +1178,20 @@ LABEL ANDROID IOS System data LABEL DESKTOP - Діагностика + Дані системи Save system data to textfile - Зберегти діагностику в текстовий файл + Збереження даних системи в текстовий файл SystemData - Діагностика + Дані системи Save system data LABEL DESKTOP - Зберегти діагностику + Зберегти дані системи @@ -1167,283 +1273,191 @@ LABEL IOS_PHONE ANDROID_PHONE You are about to identify yourself towards the following provider: - LABEL DESKTOP ----------- -LABEL IOS_PHONE ANDROID_PHONE + LABEL IOS ANDROID Ви збираєтеся ідентифікувати себе для такого постачальника: - - Provider - LABEL IOS_PHONE ANDROID_PHONE - Постачальник - - - Touch for more details - LABEL IOS_PHONE ANDROID_PHONE - Торкніться, щоб отримати докладніші відомості - EnterPasswordView - - Attempts - LABEL DESKTOP - Спроби - Enter CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть CAN-код Enter PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть PUK-код Enter pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть код створення пари - Enter new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Уведіть новий PIN-код ID-картки + Choose new ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Уведіть новий PIN-код ID-картки Confirm new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Підтвердьте новий PIN-код ID-картки Enter Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть транспортний PIN-код Enter ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть PIN-код ID-картки - Please enter the five-digit Transport PIN. - INFO DESKTOP The AA2 expects the Transport PIN with five digits. ----------- -INFO ANDROID IOS The Transport PIN is required by AA2, it needs to be change to an actual PIN. - Уведіть п’ятизначний транспортний PIN-код. - - - Please enter your current six-digit ID card PIN. - INFO DESKTOP The AA2 expects the current ID card PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current ID card PIN with six digits in a PIN change. - Уведіть поточний шестизначний PIN-код ID-картки. - - - Please enter your six-digit ID card PIN. - INFO DESKTOP The AA2 expects a ID card PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a ID card PIN with six digits in an authentication. - Уведіть шестизначний PIN-код ID-картки. - - - Please enter the six-digit Card Access Number (CAN). You can find it in the bottom right on the front of the ID card. - INFO DESKTOP The user is required to enter the six-digit CAN in CAN-allowed authentication. ----------- -INFO ANDROID IOS The user is required to enter the six-digit CAN in CAN-allowed authentication. - Уведіть шестизначний номер доступу до картки (CAN). Ви можете знайти його в нижньому правому куті на лицьовому боці своєї ID-картки. - - - A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card. - INFO DESKTOP The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. ----------- -INFO ANDROID IOS The wrong ID card PIN was entered twice, the third attempt requires the CAN for additional verification, hint where the CAN is found. - На вашій ID-картці було двічі введено неправильний PIN-код. Для третьої спроби спочатку введіть шестизначний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + Please enter the 5-digit Transport PIN. + INFO ALL_PLATFORMS The Transport PIN is required by AA, it needs to be change to an actual PIN. This is the description for the main text. + Уведіть 5-значний транспортний PIN-код. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO DESKTOP The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. ----------- -INFO ANDROID IOS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. - Ви тричі ввели неправильний шестизначний PIN-код ID-картки. Тепер PIN-код вашої ID-картки заблоковано. Щоб видалити блокування, потрібно спочатку ввести десятизначний PUK-код. + Please enter your current 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects the current ID card PIN with six digits in a PIN change. This is the description for the main text. + Уведіть поточний 6-значний PIN-код ID-картки. - Please enter a new six-digit ID card PIN now. - INFO DESKTOP A new six-digit ID card PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit ID card PIN needs to be supplied. - Уведіть новий шестизначний PIN-код ID-картки. + Please enter your 6-digit ID card PIN. + INFO ALL_PLATFORMS The AA2 expects a ID card PIN with six digits in an authentication. This is the description for the main text. + Уведіть 6-значний PIN-код ID-картки. - Please confirm your new six-digit ID card PIN. - INFO DESKTOP The new ID card PIN needs to be entered again for verification. ----------- -INFO ANDROID IOS The new ID card PIN needs to be confirmed. - Підтвердьте новий шестизначний PIN-код ID-картки. + You will enter this 6-digit PIN every time you want to use your ID card online. + INFO ALL_PLATFORMS A new 6-digit ID card PIN needs to be supplied. This is the description for the main text. + Уведіть новий 6-значний PIN-код ID-картки. - Unknown password type: - INFO DESKTOP Error message during PIN/CAN/PUK input procedure, the requested password type is unknown; internal error. - Невідомий тип пароля: + The PIN is going to be tied to your ID card. It always stays the same regardless of the device you want to use your ID card with. + INFO ALL_PLATFORMS The new ID card PIN needs to be confirmed. This is the description for the main text. + Підтвердьте новий 6-значний PIN-код ID-картки. - Do you have a five-digit Transport PIN? - LABEL ANDROID IOS Button to start a change of the Transport PIN. - Чи є у вас п’ятизначний транспортний PIN-код? + Do you have a 5-digit Transport PIN? + LABEL ALL_PLATFORMS Button to start a change of the Transport PIN. + Чи є у вас 5-значний транспортний PIN-код? Enter Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the large main text below the icon. Уведіть PIN-код Smart-eID - Enter new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Уведіть новий PIN-код Smart-eID + Choose new Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Уведіть новий PIN-код Smart-eID Confirm new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Підтвердьте новий PIN-код Smart-eID - You have entered an incorrect, six-digit Smart-eID PIN twice. An incorrect third attempt will invalidate your Smart-eID and you will have to set it up again. - INFO DESKTOP The wrong Smart-eID PIN was entered twice on the Smart-eID - Ви двічі ввели неправильний шестизначний PIN-код Smart-eID. Якщо його втретє буде введено неправильно, ваш Smart-eID стане недійсним і вам доведеться знову його налаштувати. + You will enter this 6-digit PIN every time you want to use your Smart-eID. + INFO ALL_PLATFORMS A new 6-digit Smart-eID PIN needs to be supplied. This is the description for the main text. + Уведіть новий-значний 6 PIN-код Smart-eID. - Please confirm your new six-digit Smart-eID PIN. - INFO DESKTOP The new Smart-eID PIN needs to be confirmed. ----------- -INFO ANDROID IOS The new Smart-eID PIN needs to be confirmed. - Підтвердьте новий шестизначний PIN-код Smart-eID. - - - Please enter a new six-digit Smart-eID PIN now. - INFO DESKTOP A new six-digit Smart-eID PIN needs to be supplied. ----------- -INFO ANDROID IOS A new six-digit Smart-eID PIN needs to be supplied. - Уведіть новий шестизначний PIN-код Smart-eID. + The PIN is going to be tied to your Smart-eID. It always stays the same regardless of the service you want to use your Smart-eID with. + INFO ALL_PLATFORMS The new Smart-eID PIN needs to be confirmed. This is the description for the main text. + Підтвердьте новий 6-значний PIN-код Smart-eID. Enter the pairing code shown on the device you want to pair. - INFO ANDROID IOS The pairing code for the smartphone is required. + INFO MOBILE The pairing code for the smartphone is required. This is the description for the main text. Уведіть код створення пари, показаний на пристрої, з яким потрібно створити пару. - Please enter your current six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects the current Smart-eID PIN with six digits in a PIN change. ----------- -INFO ANDROID IOS The AA2 expects the current Smart-eID PIN with six digits in a PIN change. - Уведіть поточний шестизначний PIN-код Smart-eID. + Please enter your current 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects the current Smart-eID PIN with six digits in a PIN change. This is the description for the main text. + Уведіть поточний 6-значний PIN-код Smart-eID. - Please enter your six-digit Smart-eID PIN. - INFO DESKTOP The AA2 expects a Smart-eID PIN with six digits in an authentication. ----------- -INFO ANDROID IOS The AA2 expects a Smart-eID PIN with six digits in an authentication. - Уведіть шестизначний PIN-код Smart-eID. + Please enter your 6-digit Smart-eID PIN. + INFO ALL_PLATFORMS The AA expects a Smart-eID PIN with six digits in an authentication. This is the description for the main text. + Уведіть 6-значний PIN-код Smart-eID. - Do you have a six-digit ID card PIN? - LABEL ANDROID IOS Button to switch to a six-digit ID card PIN. - У вас є шестизначний PIN-код ID-картки? + Do you have a 6-digit ID card PIN? + LABEL ALL_PLATFORMS Button to switch to a 6-digit ID card PIN. + У вас є 6-значний PIN-код ID-картки? - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice on the Smart-eID - + You have entered an incorrect, 6-digit Smart-eID PIN 2 times. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered twice on the Smart-eID + Ви 2 рази ввели неправильний 6-значний PIN-код Smart-eID. Після наступної невдалої спроби ви більше не зможете використовувати свій Smart-eID і вам потрібно буде налаштувати його знову. Send CAN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати CAN Send PUK - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати PUK Send pairing code - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати код створення пари Send new ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати новий PIN-код ID-картки Send Transport PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати транспортний PIN-код Send Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати PIN-код Smart-eID Send new Smart-eID PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати новий PIN-код Smart-eID Send ID card PIN - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. Надіслати PIN-код ID-картки - Send confirmation of new ID card PIN - LABEL ANDROID IOS - + Enter the pairing code shown on your smartphone. + INFO DESKTOP The pairing code needs to be supplied. This is the description for the main text. + Введіть код створення пари, який відображається на вашому смартфоні. - Send confirmation of new Smart-eID PIN - LABEL ANDROID IOS - + Please enter the CAN. You can find the CAN in the bottom right on the front of the ID card. + INFO ALL_PLATFORMS The user is required to enter the 6-digit CAN. This is the description for the main text. + Уведіть номер CAN. Номер CAN можна знайти в нижньому правому куті на лицьовому боці ID-картки. - Enter the pairing code shown on your smartphone. - INFO DESKTOP The pairing code needs to be supplied. - Введіть код створення пари, який відображається на вашому смартфоні. + Please enter your 10-digit PUK. + INFO ALL_PLATFORMS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. This is the description for the main text. + Уведіть 10-значний PUK-код. + + + Confirm ID card PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Підтвердьте новий PIN-код ID-картки + + + Confirm Smart-eID PIN + LABEL ALL_PLATFORMS This is the large main text below the icon. + Підтвердьте новий PIN-код Smart-eID @@ -1451,17 +1465,17 @@ LABEL ANDROID IOS collapse LABEL ANDROID IOS - + Згорнути expand LABEL ANDROID IOS - + Розгорнути Currently selected is %1 LABEL ANDROID IOS - + Наразі обрано %1 @@ -1474,9 +1488,9 @@ LABEL ANDROID IOS GText - Press space to open link: %1 - INFO ALL_PLATFORMS Text read by screen reader if the text contains a weblink which may be opened. - Натисніть пробіл, щоб відкрити посилання: %1 + Press space to open link + INFO DESKTOP Text read by screen reader if the text contains a weblink which may be opened. + Натисніть пробіл, щоб відкрити посилання @@ -1488,11 +1502,6 @@ LABEL ANDROID IOS GeneralSettings - - Language selection - LABEL DESKTOP - Вибір мови - Behavior LABEL DESKTOP @@ -1521,41 +1530,66 @@ LABEL ANDROID IOS Appearance LABEL DESKTOP - + Зовнішній вигляд Use the system font LABEL DESKTOP - + Використовувати шрифт системи Toggling will restart the %1 LABEL DESKTOP - + Перемикання призведе до перезапуску %1 Close %1 after authentication LABEL DESKTOP - Закрити після автентифікації + Закрити %1 після автентифікації Show notifications inside of %1 LABEL DESKTOP - Використовувати внутрішні сповіщення + Показувати сповіщення всередині %1 Auto-start %1 after boot and add a tray icon LABEL WINDOWS Text for auto-start option - Виконати автозапуск %1 після завантаження + Виконати автозапуск %1 після завантаження та додати піктограму до системного лотка + + + Change language + LABEL DESKTOP + Змінити мову + + + Use images instead of animations + LABEL DESKTOP + + + + Accessibility + LABEL DESKTOP + - - - GeneralWorkflow - Attempts + Hide key animations when entering PIN LABEL DESKTOP - Спроби + + + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. + LABEL DESKTOP + + + + Manual redirection back to the provider + LABEL DESKTOP + + + + + GeneralWorkflow Step %1 of 3 Крок %1 із 3 @@ -1586,9 +1620,9 @@ LABEL ANDROID IOS ID-картку не виявлено. Розташуйте ID-картку на пристрої читання карток. - No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and available. Open the reader settings to configure readers and get more information about supported readers. + No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and ready. Open the reader settings to configure readers and get more information about supported readers. INFO DESKTOP AA2 is waiting for the card reader or the ID card. - Пристрій читання карток не виявлено. Переконайтеся, що USB-пристрій читання карток підключено, або смартфон як пристрій читання карток з’єднаний та доступний. Відкрийте параметри пристрою читання, щоб налаштувати пристрої читання та отримати більше інформації про підтримувані пристрої читання карток. + Пристрій читання карток не виявлено. Переконайтеся, що USB-пристрій читання карток підключено, або смартфон як пристрій читання карток з’єднаний та доступний. Відкрийте параметри пристрою читання, щоб налаштувати пристрої читання та отримати більше інформації про підтримувані пристрої читання карток. Please observe the display of your card reader. @@ -1603,22 +1637,106 @@ LABEL ANDROID IOS No ID card detected. Please follow the instructions on your smartphone (connected to %1) to use it as card reader. INFO DESKTOP The AA2 is waiting for the smartphone to be placed on the id. - + ID-картку не виявлено. Дотримуйтесь інструкцій на своєму смартфоні (підключеному до %1), щоб використовувати його як пристрій читання карток. Please follow the instructions on your smartphone (connected to %1) or put the ID card on the card reader. INFO DESKTOP The AA2 is waiting for an ID card to be inserted into the card reader (or smartphone for that matter). - + Дотримуйтесь інструкцій на своєму смартфоні (підключеному до %1), або покладіть ID-картку на пристрій читання карток. + + + The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. + INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. + Пару з пристроєм "%1" було скасовано, оскільки він не реагував на спроби підключення. Створіть пару з пристроєм знову, щоб використовувати його як пристрій читання карток. - Hint + InputErrorView - Hint - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Підказка + Wrong CAN + LABEL ALL_PLATFORMS + Неправильний номер CAN + + + Wrong PUK + LABEL ALL_PLATFORMS + Неправильний номер PUK + + + Wrong Transport PIN + LABEL ALL_PLATFORMS + Неправильний транспортний PIN-код + + + Wrong Smart-eID PIN + LABEL ALL_PLATFORMS + Неправильний PIN-код Smart-eID + + + Wrong ID card PIN + LABEL ALL_PLATFORMS + Неправильний PIN-код ID-картки + + + Wrong new ID card PIN confirmation + LABEL ALL_PLATFORMS + Неправильне підтвердження нового PIN-коду ID-картки + + + Wrong new Smart-eID PIN confirmation + LABEL ALL_PLATFORMS + Неправильне підтвердження нового PIN-коду Smart-eID + + + Continue + LABEL ALL_PLATFORMS + Продовжити + + + + InputSuccessView + + PUK is correct + INFO ALL_PLATFORMS + PUK-код правильний + + + You now have <b>3 more attempts</b> to enter your correct <b>ID card PIN</b>. + INFO ALL_PLATFORMS + Залишилося ще 3 спроби, щоб увести правильний PIN-код ID-картки. + + + Continue + LABEL ALL_PLATFORMS + Продовжити + + + CAN is correct + INFO ALL_PLATFORMS + CAN-код правильний + + + Please enter your <b>6-digit ID card PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Уведіть 6-значний PIN-код ID-картки. Це ваша остання спроба. + + + If you enter a wrong ID Card PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Якщо ви знову введете неправильний PIN-код ID-картки, PIN-код буде заблоковано. Це блокування можна зняти лише за допомогою PUK-коду. + + + Please enter your <b>5-digit Transport PIN</b>. <b>This is your last attempt</b>. + INFO ALL_PLATFORMS + Уведіть 5-значний транспортний PIN-код. Це ваша остання спроба. + + + If you enter a wrong Transport PIN again, the PIN will be blocked. This block may only be removed using the PUK. + Якщо ви знову введете неправильний транспортний PIN-код, PIN-код буде заблоковано. Це блокування можна зняти лише за допомогою PUK-коду. + + + You now have <b>3 more attempts</b> to enter your correct <b>Transport PIN</b>. + INFO ALL_PLATFORMS + Залишилося ще 3 спроби, щоб увести правильний транспортний PIN-код. @@ -1691,10 +1809,6 @@ LABEL ANDROID IOS Share log Надати спільний доступ до журналу - - Delete log - Видалити журнал - Delete all logs Видалити всі журнали @@ -1717,31 +1831,14 @@ LABEL ANDROID IOS LABEL DESKTOP Файли журналів (*.log) - - Delete log - LABEL DESKTOP ----------- -LABEL ANDROID IOS - Видалити журнал - The current log will be automatically deleted at exit. Поточний журнал буде автоматично видалено під час виходу. - - Delete old logs - LABEL DESKTOP - Видалити старі журнали - Detach log viewer Відключити засіб перегляду журналів - - Delete selected log - LABEL DESKTOP - Видалити вибраний журнал - All old logs will be deleted. INFO DESKTOP All logfiles are about to be removed, user confirmation required. @@ -1749,13 +1846,6 @@ LABEL ANDROID IOS INFO ANDROID IOS All logfiles are about to be removed, user confirmation required. Усі старі журнали буде видалено. - - The log will be deleted. - INFO DESKTOP The current logfile is about to be removed, user confirmation required. ----------- -INFO ANDROID IOS The current logfile is about to be removed, user confirmation required. - Журнал буде видалено. - Log LABEL ANDROID IOS @@ -1767,12 +1857,16 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Delete all logs - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Видалити всі журнали Delete - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Видалити @@ -1806,7 +1900,7 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r The log entry was copied to the clipboard. INFO DESKTOP Toast message used to confirm the copy of a log entry. - Запис журналу скопійовано до буфера обміну. + Запис журналу скопійовано до буфера обміну. @@ -1826,11 +1920,6 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r LABEL DESKTOP Довідка - - Start page - LABEL ANDROID IOS - Початкова сторінка - Check device and ID card LABEL ANDROID IOS @@ -1848,22 +1937,22 @@ INFO ANDROID IOS The current logfile is about to be removed, user confirmation r Two finger swipe to scroll. - - - - List of workflows with %1 items. - + Проведіть двома пальцями, щоб прокрутити. Item %1 of %2 - + Елемент %1 із %2 Change PIN LABEL DESKTOP ---------- LABEL ANDROID IOS - Змінити PIN-код + Змінити PIN-код + + + Three finger swipe to scroll. + @@ -1885,14 +1974,14 @@ LABEL ANDROID IOS General - LABEL DESKTOP + LABEL DESKTOP +---------- +LABEL ANDROID IOS Загальні Version information - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL ANDROID IOS Інформація про версію @@ -1907,11 +1996,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Примітки до випуску - - Help & Feedback - LABEL ANDROID IOS - Довідка та зворотний зв’язок - Privacy statement LABEL ANDROID IOS @@ -1934,43 +2018,45 @@ LABEL ANDROID IOS Information - LABEL ANDROID IOS + LABEL DESKTOP +---------- +LABEL ANDROID IOS Інформація List of Providers LABEL ANDROID IOS - + Перелік постачальників Data and logs LABEL DESKTOP - Діагностика й журнали + Дані та журнали FAQ - Frequently asked questions LABEL ANDROID IOS - Запитання й відповіді + Поширені запитання й відповіді на них Contact LABEL ANDROID IOS - Підтримка + Контакти Show Logs LABEL ANDROID IOS - Журнали + Показати журнали Send log to the support LABEL ANDROID IOS - Повідомити про помилку + Надіслати журнал до служби підтримки Terms of use and software license LABEL ANDROID IOS - Ліцензія на програмне забезпечення + Умови використання та ліцензія на програмне забезпечення @@ -1988,12 +2074,12 @@ LABEL ANDROID IOS Show system data LABEL DESKTOP - Показати діагностику + Показати дані системи System data LABEL DESKTOP - Діагностика + Дані системи @@ -2003,35 +2089,20 @@ LABEL ANDROID IOS LABEL DESKTOP Відкрити сайт - - Privacy statement - LABEL DESKTOP - Заява про конфіденційність - - - Accessibility statement - LABEL DESKTOP - Заява про спеціальні можливості - - - Do you want to see a list of service providers? - LABEL DESKTOP - - List of Providers LABEL DESKTOP - + Перелік постачальників FAQ - Frequently asked questions LABEL DESKTOP - Запитання й відповіді + Поширені запитання й відповіді на них Contact LABEL DESKTOP - Підтримка + Контакти @@ -2045,25 +2116,6 @@ LABEL ANDROID IOS Назад - - NavigationButton - - Yes - Так - - - No - Ні - - - Continue - Продовжити - - - Back - Назад - - NavigationView @@ -2082,6 +2134,31 @@ LABEL ANDROID IOS Card reader Пристрій читання карток + + %1 of %2 + ANDROID IOS LABEL Relative position of current navigation tab in navigation view. %1 is replaced with the current tab's index, %2 with the total count of tabs + + + + Tab + ANDROID IOS LABEL + + + + Selection + IOS Selected navigation tab. + + + + Tab bar + IOS Name of a11y element of selected navigation tab. + + + + Selected + ANDROID Currently selected navigation tab of navigation view. + + NfcWorkflow @@ -2095,16 +2172,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Почати сканування NFC - - Unfortunately, this functionality is not available on your device. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - На жаль, ця функція недоступна на вашому пристрої. - - - However, you can use a separate smartphone as card reader to utilize the eID function. - INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - Однак ви можете використовувати окремий смартфон як пристрій читання карток, щоб застосовувати функцію онлайн-ідентифікації. - NFC is switched off. INFO ANDROID IOS NFC is available but needs to be activated in the settings of the smartphone. @@ -2155,23 +2222,53 @@ LABEL ANDROID IOS INFO IOS The ID card may be inserted, the authentication process may be started. Покладіть свою ID-картку на задню панель пристрою. - - Please place your ID card directly on the device's back side.<br/><br/>The exact position of the ID card is device dependent. The animations depict possible positions. Keep one position for several seconds before trying another one and do not move the ID card after contact was established. - INFO ANDROID The ID card may be inserted, the authentication process may be started. - Покладіть ID-картку безпосередньо на задній бік пристрою.<br/><br/>Точне положення ID-картки залежить від пристрою. На анімації показано можливі положення. Утримуйте ID-картку в одному положенні кілька секунд, перш ніж спробувати інше, і не переміщайте її після встановлення контакту. - The device "%1" wants to use this smartphone as card reader and connect to your id card. INFO ANDROID IOS %1 will be replaced with the name of the device. Пристрій «%1» намагається використовувати цей смартфон як пристрій читання карток і встановити з’єднання з вашою ID-карткою. + + The animations depict possible positions. + INFO ANDROID Text regarding ID card position animations + На анімації показано можливі положення. + + + The exact position of the ID card is device dependent. + INFO ANDROID Text regarding different NFC chip positions on different smartphones + Точне положення ID-картки залежить від пристрою. + + + Keep one position for several seconds before trying another one and do not move the ID card after contact was established. + INFO ANDROID Text that one ID card position should be kept for several seconds + Утримуйте ID-картку в одному положенні кілька секунд, перш ніж спробувати інше, і не переміщайте її після встановлення контакту. + + + Please place your ID card directly on the device's back side. + INFO ANDROID Text regarding the ID card position on the device + Покладіть ID-картку безпосередньо на задній бік пристрою. + + + This device cannot be used to read your ID card. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + To pair a smartphone select the <b>WiFi</b> option and click <b>Manage Pairings</b>. + INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + + NumberField - The password is hidden. + The number is hidden. LABEL DESKTOP Screenreader text for the password field - Пароль приховано. + You entered %1 of %2 digits. @@ -2179,19 +2276,19 @@ LABEL ANDROID IOS Ви ввели %1 з %2 знаків. - Press to hide the password + Press to hide the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Натисніть, щоб приховати пароль + - Press to show the password + Press to show the number LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - Натисніть, щоб показати пароль + - The password is visible. Digits entered so far: %1 + The number is visible. Digits entered so far: %1 LABEL DESKTOP Screenreader text for the password field - Пароль показано. Наразі введені цифри: %1 + @@ -2203,10 +2300,12 @@ LABEL ANDROID IOS Delete last digit + LABEL ANDROID IOS A11y text for the "delete" button image. Видалити останній знак Submit + LABEL ANDROID IOS A11y text for the "submit" button image. Підтвердити @@ -2236,19 +2335,32 @@ LABEL ANDROID IOS Open %1 on your %2other device%3. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4 Відкрийте %1 на своєму %2іншому пристрої%3. On that device go to %1Settings%2 and then %1Smartphone as card reader%2 resp. %1Manage pairings%2. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 3. %1 and %2 are surrounding tags for bold font. + LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 and %2 are surrounding tags for bold font. Перейдіть на тому пристрої до розділу %1Параметри%2, а тоді виберіть %1Смартфон як пристрій читання карток%2 і %1Керування створенням пари%2. Choose this smartphone in the list to pair it. - LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 3 + LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4 Виберіть цей смартфон у переліку, щоб створити з ним пару. + + Enter the pairing code "%1". + LABEL ANDROID IOS Provide pairing code. Step 4 of 4 + + + + + PairingFailedView + + Pairing to "%1" failed: + ERROR ALL_PLATFORMS An error occurred while pairing the device. + Не вдалося створити пару з пристроєм «%1»: + PairingProcessInfo @@ -2273,6 +2385,18 @@ LABEL ANDROID IOS Переконайтеся, що %1 на вашому смартфоні як пристрiй читання карток має версію не нижче %2. + + PairingSuccessView + + Pairing with "%1" successful, it will be listed under "Paired devices". + INFO ALL_PLATFORMS The pairing with the SaC server was successful. + Пару із пристроєм «%1» створено, його буде додано до переліку «З’єднані пристрої». + + + The device may now be used as a card reader. + Тепер пристрій можна використовувати як пристрій читання карток. + + PasswordInfoContent @@ -2304,14 +2428,14 @@ LABEL ANDROID IOS Як вибрати безпечний PIN-код? - For your six-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + For your 6-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 1/3 - Для свого шестизначного PIN-коду виберіть комбінацію цифр, яку неможливо вгадати. Наприклад, не використовуйте ані послідовність цифр «123456», ані дату народження, ані жодні інші числа, надруковані на вашій ID-картці. + Для свого 6-значного PIN-коду виберіть комбінацію цифр, яку неможливо вгадати. Наприклад, не використовуйте ані послідовність цифр «123456», ані дату народження, ані жодні інші числа, надруковані на вашій ID-картці. - You can change your six-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. + You can change your 6-digit PIN at any time and an unlimited number of times as long as you know your valid PIN. INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 2/3 - Ви можете змінювати свій шестизначний PIN-код у будь-який час і необмежену кількість разів, якщо ви знаєте свій дійсний PIN-код. + Ви можете змінювати свій 6-значний PIN-код у будь-який час і необмежену кількість разів, якщо ви знаєте свій дійсний PIN-код. Keep your PIN secret and change it if another person becomes aware of it. @@ -2326,24 +2450,24 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Що таке транспортний PIN-код? - Transport PIN information - LABEL ALL_PLATFORMS - Інформація про транспортний PIN-код + The Transport PIN is a %1one-time PIN%2 which is required for the initial %1setup of your ID card%2. Once you replace the %1Transport PIN with a card PIN%2, it is tied to your ID card and valid for all devices. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' + - The five-digit Transport PIN was sent to you in the PIN letter by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 1/3 - П’ятизначний транспортний PIN-код був надісланий вам у листі з PIN-кодом поштою після того, як ви подали заяву на отримання ID-картки. + Where do I find the Transport PIN? + LABEL ALL_PLATFORMS + - If you did not set a self-selected six-digit card PIN when you picked up your ID card, you can do so using the Transport PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 2/3 - Якщо ви не встановили самостійно обраний шестизначний PIN-код картки, коли забирали ID-картку, ви можете зробити це за допомогою транспортного PIN-коду. + The 5-digit Transport PIN is a %1one-time PIN%2, that you reveived per %1letter%2 when applying for the ID card. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 1/2 + - Once you have set a card PIN, the Transport PIN loses its validity. - INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' paragraph 3/3 - Після встановлення PIN-коду картки транспортний PIN-код втрачає чинність. + When setting up your ID card, you will %1replace%2 this 5-digit %1Transport PIN with%2 a 6-digit, %1self chosen card PIN%2. + INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 2/2 + Where do I find the PUK? @@ -2351,14 +2475,9 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Де я можу дізнатися PUK-код картки? - PUK information - LABEL ALL_PLATFORMS - Інформація про PUK-код - - - The PUK is a ten-digit number that you can find in the PIN letter that was sent to you by mail after you applied for your ID card. - INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' - PUK-код – це десятизначний номер, який ви можете знайти в листі з PIN-кодом, надісланому вам поштою після того, як ви подали заяву на отримання ID-картки. + The PUK is a %1 10-digit number%2 that you can find in the %1PIN letter%2 that was sent to you by mail after you %1applied for your ID card%2. You may find it to the %1right%2 of the 5-digit %1Transport PIN%2. + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' + Why is the PUK required? @@ -2366,49 +2485,44 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Навіщо потрібен PUK-код? - The PUK is required if the card PIN has been entered incorrectly three times in a row. As a result, the card PIN is blocked. + The PUK is required if the %1card PIN has been entered incorrectly 3 times%2 in a row. As a result, the card PIN is blocked. By entering the PUK you will %1unblock the card PIN%2 and have %1 3 more attempts%2 to enter the correct PIN. INFO ALL_PLATFORMS Answer to the question 'Why is the PUK required?' - PUK-код потрібен, якщо PIN-код-картки було введено неправильно тричі поспіль. Внаслідок цього PIN-код-картки блокується. + - What is the PUK's purpose? + My PUK does not work LABEL ALL_PLATFORMS - Для чого призначений PUK-код? - - - By entering the PUK, you unblock the card PIN and have another three chances to enter the correct PIN. - INFO ALL_PLATFORMS Answer to the question 'What is the PUK's purpose?' - Ввівши PUK-код, ви розблоковуєте PIN-код картки й маєте ще три спроби ввести правильний PIN-код. + - Why is the CAN required? - LABEL ALL_PLATFORMS - Навіщо потрібен CAN-код? + Make sure, that the letter at hand is the %1letter for your current ID card%2. The PIN letter is valid only for your current ID card. With a new ID card, you receive a new PIN letter with a new PUK. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + - CAN information - LABEL ALL_PLATFORMS - Інформація про CAN-код + If you applied for a PIN Reset letter, make sure that you don't mix up the letters. The %1PIN letter you need contains the 5-digit Transport PIN and the PUK%2. The PIN Reset letter contains the 6-digit card PIN and the activation code. + INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + - When is the card access number (CAN) required? + Why is the CAN required? LABEL ALL_PLATFORMS - Коли потрібен номер доступу до картки (CAN)? + Навіщо потрібен CAN-код? - The card access number (CAN) is required when the card PIN has been entered incorrectly twice. + The card access number (CAN) is required when the %1card PIN has been entered incorrectly 2 times%2. INFO ALL_PLATFORMS Answer to the question 'When is the card access number (CAN) required?' - Номер доступу до картки (CAN) потрібен, коли PIN-код картки було двічі введено неправильно. + - Why do I have to enter the CAN before a third attempt? + Why do I have to enter the CAN before a 3rd attempt? LABEL ALL_PLATFORMS - Чому потрібно вводити CAN-код перед третьою спробою? + Чому потрібно вводити CAN-код перед 3-ю спробою? - A third incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that a third incorrect entry can only be made with direct access to your ID card. - INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a third attempt?' - Третє неправильне введення призведе до блокування PIN-коду, і ви більше не зможете користуватися функцією eID, доки його не буде розблоковано. Запит CAN-коду гарантує, що третє неправильне введення може бути зроблене лише за умови прямого доступу до вашої ID-картки. + A 3rd incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that %1direct access to your ID card%2 is given. + INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a 3rd attempt?' + Where can I find the CAN? @@ -2416,14 +2530,14 @@ INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart- Де я можу дізнатися CAN-код картки? - The CAN is a six-digit number that can be found on the bottom right of the front of the ID card. + The CAN is a 6-digit number that can be found on the %1bottom right%2 of the %1front of the ID card%2. INFO ALL_PLATFORMS Answer to the question 'Where can I find the CAN?' - CAN-код – це шестизначний номер, який можна знайти в нижній правій частині лицьового боку ID-картки. + - The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a six-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in red). + The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a 6-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in picture). INFO ALL_PLATFORMS Description text of CAN-allowed authentication - Номер доступу до картки (CAN) дає змогу отримати доступ до вихідних даних ID-картки. CAN – це шестизначний номер, який можна знайти на лицьовій стороні ID-картки. Він розташований унизу праворуч від терміну дії (позначено червоним). + Номер доступу до картки (CAN) дає змогу отримати доступ до вихідних даних ID-картки. CAN – це 6-значний номер, який можна знайти на лицьовій стороні ID-картки. Він розташований унизу праворуч від терміну дії (позначено червоним). Smart-eID blocking code @@ -2453,9 +2567,9 @@ LABEL ALL_PLATFORMS Ви не знаєте свій PIN-код? - You have not yet set a six-digit card PIN and cannot find the PIN letter with the Transport PIN? + You have not yet set a 6-digit card PIN and cannot find the PIN letter with the Transport PIN? INFO ALL_PLATFORMS - Ви ще не встановили шестизначний PIN-код картки й не можете знайти лист із транспортним PIN-кодом? + Ви ще не встановили 6-значний PIN-код картки й не можете знайти лист із транспортним PIN-кодом? You set a card PIN when picking up your ID card or later by yourself, but you can no longer remember it? @@ -2463,135 +2577,193 @@ LABEL ALL_PLATFORMS Ви встановили PIN-код картки під час отримання ID-картки або пізніше самостійно, але вже не пам’ятаєте його? - Learn more about the two types of PIN + How do the PIN types differ? LABEL ALL_PLATFORMS - Дізнайтеся більше про два типи PIN-кодів + - Types of PIN - LABEL ALL_PLATFORMS - Типи PIN-кодів + Your ID card comes with a 5-digit %1Transport PIN%2 which you need to %1replace with%2 a 6-digit %1card PIN%2 that you choose yourself. + INFO ALL_PLATFORMS Description text explaining the PINs 1/7 + - Your ID card comes with a five-digit 'Transport PIN' which you need to replace with a six-digit PIN that you choose yourself. - INFO ALL_PLATFORMS Description text explaining the PINs 1/7 - До вашої ID-картки додається п’ятизначний « PIN-код», який вам потрібно змінити на шестизначний PIN-код, який ви обираєте самостійно. + 5-digit Transport PIN + LABEL ALL_PLATFORMS + 5-значний транспортний PIN-код - Five-digit Transport PIN + 6-digit PIN LABEL ALL_PLATFORMS - П’ятизначний транспортний PIN-код + 6-значний PIN-код + + + The 5-digit Transport PIN is a %1one-time PIN%2 that was sent to you by %1mail%2 after you applied for your ID card. + INFO ALL_PLATFORMS Description text explaining the PINs 2/7 + - Six-digit PIN + What is the Smart-eID PIN? LABEL ALL_PLATFORMS - Шестизначний PIN-код + Що таке PIN-код Smart-eID? - You can use the PIN Reset Service to request a new card PIN free of charge. + Set up Smart-eID LABEL ALL_PLATFORMS - Ви можете скористатися службою скидання PIN-коду, щоб безкоштовно надіслати запит на новий PIN-код картки. + Налаштувати Smart-eID - If you do not know either your Transport PIN or your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. - Якщо ви не знаєте ні транспортний PIN-код, ні PIN-код картки, ви можете безкоштовно надіслати запит на новий PIN-код, скориставшись службою скидання PIN-коду. + The Smart-eID PIN is a 6-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. + INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' + PIN-код Smart-eID – це 6-значний PIN-код, який ви встановлюєте самостійно. Цей PIN-код обов’язковий, якщо ви хочете використовувати свій Smart-eID. - If you have forgotten your card PIN, you can request a new PIN free of charge using the PIN Reset Service. - LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - Якщо ви забули PIN-код картки, ви можете безкоштовно надіслати запит на новий PIN-код, скориставшись службою скидання PIN-коду. + For your 6-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. + INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 + Для свого 6-значного PIN-коду Smart-eID виберіть комбінацію цифр, яку неможливо вгадати. Наприклад, не використовуйте ані послідовність цифр «123456», ані дату свого народження, ані жодні інші числа, надруковані на вашій ID-картці. - The five-digit Transport PIN was sent to you by mail after you applied for your ID card. - INFO ALL_PLATFORMS Description text explaining the PINs 2/7 - 5-значний транспортний PIN-код був надісланий вам у листі поштою після того, як ви подали заяву на отримання ID-картки. + You can change your 6-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. + INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 + Ви можете змінювати свій 6-значний PIN-код Smart-eID у будь-який час і необмежену кількість разів, якщо ви знаєте свій дійсний PIN-код Smart-eID. - What is the Smart-eID PIN? - LABEL ALL_PLATFORMS + When you set up the eID function, you will %1replace%2 this 5-digit %1Transport PIN%2 with a 6-digit %1card PIN that you choose yourself%2. + INFO ALL_PLATFORMS Description text explaining the PINs 3/7 - Set up Smart-eID - LABEL ALL_PLATFORMS - Налаштувати Smart-eID + The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time. + INFO ALL_PLATFORMS Description text explaining the PINs 5/7 + PIN-код Smart-eID також має шість цифр. Цей PIN-код ви також обираєте самостійно під час першого налаштування Smart-eID. - The Smart-eID PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID. - INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' - + You can change your card PIN and your Smart-eID PIN at any time in %1. + INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + Ви можете змінити PIN-код картки та PIN-код Smart-eID у будь-який момент у %1. - For your six-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither "123456", nor your date of birth, nor any other numbers printed on your ID card. - INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 - + With this 6-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. + INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + За допомогою цього 6-значного PIN-коду ви підтверджуєте онлайн, що ID-картка або Smart-eID належить саме вам. Без цього PIN-коду ніхто не зможе скористатися функцію eID. - You can change your six-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN. - INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 + The card PIN is a 6-digit PIN that you set yourself. You always need this %1PIN%2 if you want to use the %1eID function%2. + INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' - The PIN can only be used once. When you set up the eID function, you will replace this five-digit Transport PIN with a six-digit card PIN that you choose yourself. - INFO ALL_PLATFORMS Description text explaining the PINs 3/7 - + You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the 5-digit Transport PIN. Only when you have set a 6-digit PIN of your own choice can you use the eID function and set up a Smart-eID. + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) + Ви встановлюєте PIN-код картки безпосередньо під час отримання ID-картки у відділі обслуговування громадян (Bürgeramt) або пізніше в %1 за допомогою 5-значного транспортного PIN-коду. Використовувати функцію eID можна лише після самостійного встановлення 6-значного PIN-коду й налаштування Smart-eID. - The six-digit card PIN is a number that you choose yourself when you set up the eID function for the first time. It replaces your five-digit Transport PIN. - INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + The card PIN was %1either%2... + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Intro - The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time. - INFO ALL_PLATFORMS Description text explaining the PINs 5/7 + set by you when picking up the ID card %1at the citiziens' office%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 1/3 - You can change your card PIN and your Smart-eID PIN at any time in %1. - INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + set %1in the %3 using%2 the 5-digit %1Transport PIN%2 + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 2/3 - With this six-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN. - INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + requested using the %1PIN Reset Service%2 - you may continue using the 6-digit card PIN from the letter or change it via "Change PIN" to a self chosen card PIN + INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 3/3 - The card PIN is a six-digit PIN that you set yourself. You always need this PIN if you want to use the eID function with your ID card. - INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' + I just have a 5-digit Transport PIN + LABEL ALL_PLATFORMS - You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the five-digit Transport PIN. Only when you have set a six-digit PIN of your own choice can you use the eID function and set up a Smart-eID. - INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) + You need to change the %1 5-digit Transport PIN%2 to your personal card PIN. Use %1Change PIN > Transport PIN%2 from the startpage to do so. + INFO ALL_PLATFORMS Explanation if only the Transport PIN is at hand If you have forgotten your Smart-eID PIN, you can renew your Smart-eID and thereby set a new PIN. LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. - + Якщо ви забули свій PIN-код Smart-eID, ви можете відновити свій Smart-eID і таким чином встановити новий PIN-код. Where can I find the Smart-eID PIN? LABEL ALL_PLATFORMS - + Де я можу дізнатися PIN-код Smart-eID? You have set the Smart-eID PIN while setting up the Smart-eID. INFO ALL_PLATFORMS Answer to the question 'Where can I find the Smart-eID PIN?' - + Ви встановили PIN-код Smart-eID під час налаштування Smart-eID. - With this six-digit PIN you prove online that the ID card belongs to you. No one can use the eID function without this PIN. + With this 6-digit PIN you prove online that the ID card belongs to you. %1No one can use the eID function without this PIN%2. INFO ALL_PLATFORMS Description text explaining the PINs 6/7 - You can change your card PIN at any time in %1. + If you applied for a %1PIN Reset letter%2, a new card PIN was already set for you. You can change your card PIN at %1any time in %3%2. INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + + I can't recall my PIN + LABEL ALL_PLATFORMS + Не можу згадати свій PIN-код + + + I can't recall my PUK + Не можу згадати свій PUK-код + + + Set a new PIN + Установити новий PIN-код + + + My Transport PIN does not work + LABEL ALL_PLATFORMS + Мій транспортний PIN-код не працює + + + If your Transport PIN from the PIN letter does work, this might be caused by the following reasons: + LABEL ALL_PLATFORMS INFO ALL_PLATFORMS Introduction why the Transport PIN might not work. + Якщо ваш транспортний PIN-код, надісланий листом із PIN-кодом, не працює, це може бути викликано такими причинами: + + + You already set a 6-digit PIN either at the competent authority or using the %1. + INFO ALL_PLATFORMS Information why the Transport PIN is void: a 6-digit PIN was already set + Ви вже встановили 6-значний PIN-код або в компетентному органі, або за допомогою %1. + + + You applied for PIN Reset Letter (letter containing a 6-digit PIN and corresponding Activation Code). + INFO ALL_PLATFORMS Information why the Transport PIN is void: the PIN Reset Service was used + Ви подали заявку на отримання листа для скидання PIN-коду (лист, що містить 6-значний PIN-код і відповідний код активації). + + + Once you set a 6-digit PIN, the Transport PIN is no longer valid. You may then only use the 6-digit PIN to authenticate yourself. + INFO ALL_PLATFORMS Information that the Transport PIN is void once a 6-digit PIN was set. + Якщо ви встановили 6-значний PIN-код, транспортний PIN-код більше не дійсний. Після цього для автентифікації своєї особи ви можете використовувати лише 6-значний PIN-код. + + + The 6-digit card PIN is a %1number that you choose yourself%2 when you set up the eID function for the first time. It %1replaces%2 your %1 5-digit Transport PIN%2. + INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + + + + + PasswordInfoView + + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Підказка + PersonalizationController @@ -2629,7 +2801,7 @@ LABEL ALL_PLATFORMS Важливе повідомлення - Do not give your smartphone to third parties unattended, especially if it is already unlocked. + Do not give your smartphone to 3rd parties unattended, especially if it is already unlocked. LABEL ANDROID IOS Не давайте свій смартфон третім особам без нагляду, особливо якщо його вже розблоковано. @@ -2639,7 +2811,7 @@ LABEL ALL_PLATFORMS Не записуйте PIN-код Smart-eID у своєму смартфоні або на ньому. - Do not give your Smart-eID PIN to third parties. + Do not give your Smart-eID PIN to 3rd parties. LABEL ANDROID IOS Не передавайте свій PIN-код Smart-eID третім особам. @@ -2661,7 +2833,7 @@ LABEL ALL_PLATFORMS If you uninstall the %1 or reset your smartphone, the Smart-eID must be set up again. LABEL ANDROID IOS - + Якщо ви видалите %1 або скинете налаштування смартфона, Smart-eID потрібно буде налаштувати заново. @@ -2724,7 +2896,7 @@ LABEL ALL_PLATFORMS Please wait a moment, the current process is being finished. LABEL ANDROID IOS - + Трохи зачекайте, завершується поточний процес. @@ -2739,11 +2911,6 @@ LABEL ALL_PLATFORMS INFO ANDROID IOS Success message that the Smart-eID was created. Ви успішно налаштували Smart-eID. - - OK - LABEL ANDROID IOS - OK - Continue LABEL ANDROID IOS @@ -2769,6 +2936,16 @@ LABEL ALL_PLATFORMS LABEL ANDROID IOS Увага: ви можете налаштувати лише <b><u>один</u></b> Smart-eID для своєї ID-картки. Подальші налаштування можна виконати %1. + + Personalization failed + LABEL ANDROID IOS + Не вдалося виконати персоналізацію + + + Back to start page + LABEL ANDROID IOS + Повернутися до початкової сторінки + PkiSwitch @@ -2812,21 +2989,36 @@ LABEL ALL_PLATFORMS - ProviderInfoSection + ProviderInfo See details under "more..." - LABEL DESKTOP + LABEL ALL_PLATFORMS Див. відомості в розділі «Додаткова інформація» Show more information about the service provider LABEL DESKTOP - Показати додаткову інформацію про постачальника послуг + Показати додаткову інформацію про постачальника послуг + + + You are about to identify yourself towards the following provider: + LABEL DESKTOP + Ви збираєтеся ідентифікувати себе для такого постачальника: + + + Provider + LABEL ANDROID IOS + Постачальник + + + Touch for more details + LABEL ANDROID IOS + Торкніться, щоб отримати докладніші відомості Details about the provider LABEL DESKTOP - Відомості про постачальника + Відомості про постачальника @@ -2872,8 +3064,8 @@ LABEL DESKTOP Title of the proxy credentials popup. Під час обробки журналу сталася помилка: %1 - Please describe the error that occurred. - Опишіть помилку, яка сталася. + Please describe the error that occurs. Our support is available to you in German and English. + Опишіть помилку, яка сталася. Наша підтримка доступна німецькою та англійською мовами. You may want to attach the logfile which can be saved from the error dialog. @@ -2904,6 +3096,44 @@ LABEL DESKTOP Title of the proxy credentials popup. Невідомий пристрій читання + + RedirectView + + Remove the ID card from the card reader + INFO DESKTOP Hint to user that the ID card should be removed + Вийміть ID-картку із пристрою читання карток + + + Remove the ID card from the NFC interface + INFO ANDROID IOS Hint to user that the ID card should be removed + Вийміть ID-картку з інтерфейсу NFC + + + If you have any questions or encounter any errors during the process, please contact the corresponding provider. + LABEL ALL_PLATFORMS + + + + You will be automatically redirected to the provider in a few seconds. If you are not automatically redirected, click on the "%1" button. + INFO ALL_PLATFORMS Redirect information when automatic redirect is enabled + + + + Press the button to complete the authentication and return to the provider. + INFO ALL_PLATFORMS Redirect information when automatic redirect is disabled + + + + Return to provider + LABEL ALL_PLATFORMS + Повернутися до постачальника + + + Authentication successful + LABEL ALL_PLATFORMS + Автентифікацію виконано успішно + + ReleaseNotes @@ -2922,15 +3152,18 @@ LABEL ANDROID IOS RemoteReaderDelegate - Smartphone named "%1" - Смартфон під іменем «%1» + Smartphone named "%1". %2. + INFO DESKTOP Name and status of remote device. %1 is replaced with the name, %2 with the status + Смартфон під іменем «%1». %2. Press space to unpair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is paired. Натисніть пробіл, щоб скасувати пару зі смартфоном «%1». Press space to pair the smartphone "%1". + INFO DESKTOP Text for activation action if the device is unpaired. Натисніть пробіл, щоб створити пару зі смартфоном «%1». @@ -2955,10 +3188,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 is a placeholder-tag for the app name. Відкрийте %1 на своєму смартфоні як пристрій читання карток. - - Both devices have to be connected to the same WiFi. - Обидва пристрої мають бути підключені до однієї мережі Wi-Fi. - On that device go to %1Card reader%2 and then %1Pair device%2 rsp. %1Pair new device%2. LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4. %1 and %2 are surrounding tags for bold font @@ -2979,6 +3208,10 @@ LABEL ANDROID IOS LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4. %1 is a placeholder-tag for the app name. Переконайтеся, що %1 на вашому смартфоні як пристрiй читання карток має версію не нижче %2. + + Both devices have to be on the same network (e.g. WiFi). + Обидва пристрої мають бути в одній мережі (наприклад, Wi-Fi). + RemoteServiceController @@ -3008,11 +3241,6 @@ LABEL ANDROID IOS RemoteServiceView - - Pairing failed. Please start a new pairing process on your other device and enter the shown pairing code. - ERROR ANDROID IOS An error occurred while pairing the device. - Не вдалося створити пару. Почніть новий процес створення пари на іншому пристрої та введіть показаний код створення пари. - WiFi not active LABEL ANDROID IOS @@ -3023,25 +3251,20 @@ LABEL ANDROID IOS LABEL ANDROID IOS NFC неактивна - - Remote service not available - LABEL ANDROID IOS - Віддалена служба недоступна - Card access in progress LABEL ANDROID IOS Виконується доступ до картки - Waiting for connection + Card reader ready LABEL ANDROID IOS - Очікування підключення + Очікування підключення - Waiting for connection from a paired device... + To do this, start a process on a paired device. INFO ANDROID IOS - Очікування підключення від пристрою, з яким створено пару… + Pairing code: <b>%1</b> @@ -3064,9 +3287,9 @@ LABEL ANDROID IOS Створити пару з пристроєм - Allow connection + Activate card reader LABEL ANDROID IOS - Дозволити з’єднання + Дозволити з’єднання You can use this Smartphone as a card reader for the %1 on other devices e.g. a laptop. @@ -3108,9 +3331,9 @@ To do this you first have to pair that device with this smartphone. Куди вводити код створення пари? - Enter the pairing code %1 in the %2 on your other device. + Enter the pairing code "%1" in the %2 on your other device. INFO ANDROID IOS - Введіть код створення пари %1 у %2 на своєму іншому пристрої. + Введіть код створення пари "%1" у %2 на своєму іншому пристрої. Cancel pairing @@ -3127,6 +3350,16 @@ To do this you first have to pair that device with this smartphone. INFO ANDROID IOS Тепер з’єднані пристрої можуть використовувати цей смартфон як пристрій читання карток. + + NFC is not available + LABEL ANDROID IOS + NFC недоступно + + + Stop card reader + LABEL ANDROID IOS + + RemoteServiceViewRemote @@ -3190,13 +3423,18 @@ To do this you first have to pair that device with this smartphone. LABEL ANDROID IOS Натисніть, щоб створити пару + + Pairing the device ... + LABEL ANDROID IOS + Створення пари з пристроєм… + RemoteServiceWifiInfo - Both devices have to be connected to the same WiFi. + Both devices have to be on the same network (e.g. WiFi). INFO ANDROID IOS The remote service is active. Hint that both devices need to be connected to the same network. - Обидва пристрої мають бути підключені до однієї мережі Wi-Fi. + Обидва пристрої мають бути в одній мережі (наприклад, Wi-Fi). @@ -3229,7 +3467,7 @@ To do this you first have to pair that device with this smartphone. Connected to %1. Please follow the instructions on the connected smartphone. INFO ANDROID IOS The connection to the smartphone was established, the ID card may be inserted. - + Підключено до %1. Дотримуйтесь інструкцій на підключеному смартфоні. Manage pairings @@ -3249,15 +3487,16 @@ To do this you first have to pair that device with this smartphone. ResultErrorView - - Details - Відомості - Error code: LABEL ANDROID IOS Код помилки: + + Show Details + LABEL ANDROID IOS + Відомості + ResultView @@ -3286,26 +3525,20 @@ To do this you first have to pair that device with this smartphone. LABEL ANDROID IOS OK - - - RetryCounter - Remaining ID card PIN attempts: %1 - LABEL DESKTOP - Залишилося стільки спроб введення PIN-коду ID-картки: %1 + Hint + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Підказка SecurityAndPrivacySettings - Onscreen keypad - LABEL DESKTOP - Екранна клавіатура - - - Use on screen keypad for PIN entry + Numeric keypad LABEL DESKTOP - Використовувати екранну клавіатуру для введення PIN-коду + Екранна клавіатура Software updates @@ -3313,9 +3546,9 @@ To do this you first have to pair that device with this smartphone. Оновлення програмного забезпечення - Check at program start + Check for updates at program start LABEL DESKTOP - Перевіряти під час запуску програми + Перевіряти під час запуску програми Show update @@ -3348,19 +3581,19 @@ To do this you first have to pair that device with this smartphone. Інформація про оновлення недоступна, перевірте наявність оновлення вручну. - Shuffle digits of on screen keypad + Shuffle keys LABEL DESKTOP - Кнопки клавіатури в довільному порядку + Перемішати цифри на екранній клавіатурі - Button animation + Hide key animations LABEL DESKTOP - Візуальний відгук під час натискання кнопок клавіатури + Анімація кнопок - Visually highlight key presses on screen keypad + Makes it difficult for outsiders to detect PIN entry LABEL DESKTOP - + Візуальне виділення натискань кнопок на екранній клавіатурі @@ -3380,18 +3613,18 @@ To do this you first have to pair that device with this smartphone. LABEL DESKTOP Title of the self authentication result data view Зчитати дані - - OK - LABEL DESKTOP ----------- -LABEL ANDROID IOS - OK - Identify LABEL ANDROID IOS Ідентифікувати + + Back to start page + LABEL DESKTOP +---------- +LABEL ANDROID IOS + Повернутися до початкової сторінки + SelfAuthenticationView @@ -3418,9 +3651,7 @@ LABEL ANDROID IOS Use the button "See my personal data" to start the self-authentication service of the manufacturer of the %1 to display the data stored in the chip of your ID card. - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Використовуйте кнопку «Дивитися мої особисті дані», щоб запустити службу самоавтентифікації виробника %1 й відобразити дані, збережені в мікросхемі вашої ID-картки. @@ -3433,13 +3664,18 @@ LABEL ANDROID IOS Self-authentication LABEL ANDROID IOS - + Самоавтентифікація Hint LABEL ANDROID IOS Підказка + + View the data stored on your ID card + LABEL ANDROID IOS + Переглянути дані, що зберігаються на вашій ID-картці + SettingsView @@ -3471,11 +3707,14 @@ LABEL ANDROID IOS Security and privacy - LABEL DESKTOP ----------- -LABEL ANDROID IOS + LABEL DESKTOP Безпека й конфіденційність + + Numeric keypad + LABEL ANDROID IOS + Безпека й конфіденційність + Debug options LABEL DESKTOP @@ -3506,14 +3745,14 @@ LABEL ANDROID IOS Введіть PIN-код на цьому пристрої - Randomize the order of the on screen keypad buttons + Shuffle keys LABEL ANDROID IOS - Налаштувати довільний порядок кнопок на екранній клавіатурі + Налаштувати довільний порядок кнопок на екранній клавіатурі - Keypad animations + Hide key animations LABEL ANDROID IOS - Анімація клавіатури + Анімація клавіатури Skip rights page @@ -3540,11 +3779,6 @@ LABEL ANDROID IOS LABEL ANDROID IOS Використовувати стійкіший режим - - Layout style - LABEL ANDROID IOS - Стиль макета - Create dummy entries LABEL ANDROID IOS @@ -3563,80 +3797,105 @@ LABEL ANDROID IOS Smart-eID LABEL ANDROID IOS - Smart-eID + Smart-eID Reset Smart-eID LABEL ANDROID IOS - Скинути Smart-eID + Скинути Smart-eID Reset Smart-eID data on your device LABEL ANDROID IOS - + Скиньте дані Smart-eID на своєму пристрої - Show Transport PIN reminder, store feedback and close reminder dialogs. + Show requested rights on this device as well LABEL ANDROID IOS - + Показати запит на права також на цьому пристрої - Reset hideable dialogs + Manage pairings LABEL ANDROID IOS - + Керування створенням пари - Show requested rights on this device as well + Show Transport PIN reminder, store feedback and close reminder dialogs. LABEL ANDROID IOS - Показати запит на права також на цьому пристрої + Показувати нагадування про транспортний PIN-код, зберігати відгуки й закривати діалоги з нагадуваннями. - Manage pairings + Reset hideable dialogs LABEL ANDROID IOS - Керування створенням пари + Скинути приховані діалоги Toggling will restart the %1 LABEL ANDROID IOS - + Перемикання призведе до перезапуску %1 Use system font LABEL ANDROID IOS - + Використовувати шрифт системи Appearance LABEL ANDROID IOS - + Зовнішній вигляд Add and remove devices LABEL ANDROID IOS - Керування з’єднаними пристроями й додавання нових пристроїв + Додавання та видалення пристроїв On-site reading LABEL ANDROID IOS - Дозволений режим CAN + Зчитування на місці Support CAN allowed mode for on-site reading LABEL ANDROID IOS - Підтримувати дозволений режим CAN + Підтримка дозволеного режиму CAN для зчитування на місці Allow test sample card usage LABEL ANDROID IOS - + Дозволити використання картки тестового зразка Simulate a test sample card in authentications LABEL ANDROID IOS + Імітація картки тестового зразка в автентифікації + + + Makes it difficult for outsiders to detect PIN entry + LABEL ANDROID IOS + Візуальне виділення натискань кнопок на екранній клавіатурі + + + Use images instead of animations + LABEL ANDROID IOS + + + + Accessibility + LABEL ANDROID IOS - Visually highlight key presses on screen keypad + Hide key animations when entering PIN + LABEL ANDROID IOS + + + + After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds. + LABEL ANDROID IOS + + + + Manual redirection back to the provider LABEL ANDROID IOS @@ -3661,12 +3920,12 @@ LABEL ANDROID IOS Autostart Settings LABEL DESKTOP - + Налаштування автозапуску The launch will add a tray icon to the notification area. INFO WINDOWS Additional information that Windows auto-start adds a symbol to the notification area. - + Після запуску піктограму системного лотка буде додано до області сповіщень. @@ -3687,27 +3946,27 @@ LABEL ANDROID IOS Smart-eID LABEL ANDROID IOS - Smart-eID + Smart-eID Please wait a moment. LABEL ANDROID IOS - Трохи зачекайте. + Трохи зачекайте. Send log LABEL ANDROID IOS - Надіслати журнал + Надіслати журнал If you want to use that functionality again, you need to set up a new Smart-eID first. LABEL ANDROID IOS - Якщо ви хочете знову використовувати цю функцію, вам спочатку потрібно налаштувати новий Smart-eID. + Якщо ви хочете знову використовувати цю функцію, вам спочатку потрібно налаштувати новий Smart-eID. Reset Smart-eID LABEL ANDROID IOS - Скинути Smart-eID + Скинути Smart-eID @@ -3715,47 +3974,47 @@ LABEL ANDROID IOS Delete Smart-eID LABEL ANDROID IOS - Видалити Smart-eID + Видалити Smart-eID You have successfuly deleted your Smart-eID. LABEL ANDROID IOS - + Ви видалили свій Smart-eID. The Smart-eID could not be successfully deleted from your device. LABEL ANDROID IOS - + Не вдалося видалити Smart-eID з вашого пристрою. Back to start page LABEL ANDROID IOS - + Повернутися до початкової сторінки You are about to delete the Smart-eID data that is currently stored on your device. LABEL ANDROID IOS - Ви збираєтеся видалити дані Smart-eID, які зараз зберігаються на вашому пристрої. + Ви збираєтеся видалити дані Smart-eID, які зараз зберігаються на вашому пристрої. Are you sure you want to delete the Smart-eID? LABEL ANDROID IOS - Справді видалити Smart-eID? + Справді видалити Smart-eID? Delete LABEL ANDROID IOS - Видалити + Видалити Deleting Smart-eID LABEL ANDROID IOS - Видалення Smart-eID + Видалення Smart-eID Delete the Smart-eID LABEL ANDROID IOS - + Видалити Smart-eID @@ -3793,7 +4052,7 @@ LABEL ANDROID IOS With the Smart-eID you may also use the online identification function without the ID card. LABEL ANDROID IOS - + За допомогою Smart-eID ви також можете користуватися функцією онлайн-ідентифікації без ID-картки. @@ -3801,37 +4060,37 @@ LABEL ANDROID IOS Reset Smart-eID LABEL ANDROID IOS - Скинути Smart-eID + Скинути Smart-eID You have successfully reset your Smart-eID. LABEL ANDROID IOS - + Ви скинули свій Smart-eID. You are about to reset your Smart-eID data. This can also be used for troubleshooting as well. LABEL ANDROID IOS - + Ви збираєтеся скинути дані свого Smart-eID. Це також можна використовувати для усунення несправностей. Are you sure you want to reset the Smart-eID? LABEL ANDROID IOS - + Справді скинуте Smart-eID? Reset LABEL ANDROID IOS - + Скинути Resetting Smart-eID LABEL ANDROID IOS - Скидання Smart-eID + Скидання Smart-eID Reset the Smart-eID LABEL ANDROID IOS - + Скинути Smart-eID @@ -3859,27 +4118,27 @@ LABEL ANDROID IOS Delete Smart-eID data from your device LABEL ANDROID IOS - + Видалити дані Smart-eID з вашого пристрою Try Smart-eID LABEL ANDROID IOS - + Спробувати Smart-eID Show Smart-eID data LABEL ANDROID IOS - + Показати дані Smart-eID Change Smart-eID PIN LABEL ANDROID IOS - Змінити PIN-код Smart-eID + Змінити PIN-код Smart-eID Change the chosen Smart-eID PIN LABEL ANDROID IOS - + Змінити вибраний PIN-код Smart-eID @@ -3890,9 +4149,9 @@ LABEL ANDROID IOS Smart-eID - You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your six-digit ID card PIN and an internet connection. + You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Ви збираєтеся налаштувати Smart-eID на своєму пристрої. Щоб продовжити, вам потрібні ID-картка, шестизначний PIN-код ID-картки й підключення до Інтернету. + Ви збираєтеся налаштувати Smart-eID на своєму пристрої. Щоб продовжити, вам потрібні ID-картка, 6-значний PIN-код ID-картки й підключення до Інтернету. Set up Smart-eID @@ -3902,15 +4161,15 @@ LABEL ANDROID IOS Smart-eID setup LABEL ANDROID IOS - + Налаштування Smart-eID SmartUpdateStartView - You are about to renew your Smart-eID. In order to proceed, you need your ID card, your six-digit ID card PIN and an internet connection. + You are about to renew your Smart-eID. In order to proceed, you need your ID card, your 6-digit ID card PIN and an internet connection. LABEL ANDROID IOS - Ви збираєтеся поновити свій Smart-eID. Щоб продовжити, вам потрібні ID-картка, шестизначний PIN-код ID-картки й підключення до Інтернету. + Ви збираєтеся поновити свій Smart-eID. Щоб продовжити, вам потрібні ID-картка, 6-значний PIN-код ID-картки й підключення до Інтернету. Please note that your current Smart-eID is invalidated during the process and will not be usable until the update process is completed. @@ -3925,12 +4184,12 @@ LABEL ANDROID IOS Renew the Smart-eID LABEL ANDROID IOS - + Поновити Smart-eID Smart-eID renewal LABEL ANDROID IOS - + Поновлення Smart-eID @@ -4026,7 +4285,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The device "%1" wants to access your Smart-eID. INFO ANDROID IOS %1 will be replaced with the name of the device. - + Пристрій «%1» хоче отримати доступ до вашого Smart-eID. @@ -4052,6 +4311,26 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Оцінити програму + + SuggestionData + + Hint + Підказка + + + + TabbedPane + + Tab selected + LABEL DESKTOP + Вибрано вкладку + + + %1 of %2 + LABEL DESKTOP %1 is the current selected Page of %2 Pages + + + TabbedReaderView @@ -4067,6 +4346,10 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u USB card reader USB-пристрій читання карток + + Found new USB card reader that is suitable for the ID card. The workflow may now be continued. + Знайдено новий USB-пристрій читання карток, який підходить для ID-картки. Тепер робочий процес можна продовжити. + TechnologySwitch @@ -4090,6 +4373,16 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ANDROID IOS SIM + + %1 mode is active. + INFO ANDROID IOS A11y text on button indicating the currently active technology. %1 will be replaced with the name of the technology (e.g. NFC). + %1 режим активовано. + + + Click here to change the mode to %1. + INFO ANDROID IOS A11y text on button to switch to another technology. %1 will be replaced with the name of the technology (e.g. NFC). + Натисніть тут, щоб змінити режим на %1. + TitleBar @@ -4112,11 +4405,17 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Show in-app notifications of %1 + LABEL DESKTOP Показувати сповіщення в програмі щодо %1 Title bar LABEL DESKTOP + Рядок заголовка + + + Hide in-app notifications of %1 + LABEL DESKTOP @@ -4136,9 +4435,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u TransportPinReminderView - Do you know your six-digit ID card PIN? + Do you know your 6-digit ID card PIN? LABEL ANDROID IOS - Ви знаєте шестизначний PIN-код своєї ID-картки? + Ви знаєте 6-значний PIN-код своєї ID-картки? No @@ -4151,14 +4450,14 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Так - Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function. + Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function. LABEL ANDROID IOS - Онлайн-ідентифікація за допомогою транспортного PIN-коду неможлива. Самостійно обраний шестизначний PIN-код ID-картки обов’язковий для використання функції eID. + Онлайн-ідентифікація за допомогою транспортного PIN-коду неможлива. Самостійно обраний 6-значний PIN-код ID-картки обов’язковий для використання функції eID. - To set up a Smart-eID you also need to have assigned a six-digit PIN beforehand. + To set up a Smart-eID you also need to have assigned a 6-digit PIN beforehand. LABEL ANDROID IOS - + Щоб налаштувати Smart-eID, вам також потрібен заздалегідь присвоєний 6-значний PIN-код. @@ -4230,16 +4529,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u UpdateViewButtonRow - - Skip update - LABEL DESKTOP User choice to skip this update, the automatic update check will *not* inform about this update again. - Пропустити оновлення - - - Remind me later - LABEL DESKTOP The available update is shown again after next automatic update check. - Нагадати пізніше - Open App Store LABEL DESKTOP Open the Mac App Store on macOS @@ -4316,6 +4605,21 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ANDROID IOS Розширені параметри деактивовано. + + Open website + LABEL DESKTOP + Відкрити сайт + + + Privacy statement + LABEL DESKTOP + Заява про конфіденційність + + + Accessibility statement + LABEL DESKTOP + Заява про спеціальні можливості + WhiteListSurveyView @@ -4364,14 +4668,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Надіслати - - WorkflowInfoList - - The device "%1" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader. - INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. - Пару з пристроєм "%1" було скасовано, оскільки він не реагував на спроби підключення. Створіть пару з пристроєм знову, щоб використовувати його як пристрій читання карток. - - governikus::AccessRoleAndRightsUtil @@ -4537,6 +4833,31 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u INFO ALL_PLATFORMS Failure code (string) of current workflow error. Причина: + + Redirect failed + LABEL ALL_PLATFORMS + Не вдалося виконати переспрямування + + + Authentication failed + LABEL ALL_PLATFORMS + Не вдалося виконати автентифікацію + + + Authentication successful + LABEL ALL_PLATFORMS + Автентифікацію виконано успішно + + + Return to provider + LABEL ALL_PLATFORMS + Повернутися до постачальника + + + Back to start page + LABEL ALL_PLATFORMS + Повернутися до початкової сторінки + governikus::CardInfo @@ -4799,12 +5120,12 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Не вдалося виявити антивірусну програму. - Third party firewalls cannot be detected on Windows 7. + 3rd party firewalls cannot be detected on Windows 7. LABEL DESKTOP Брандмауери сторонніх розробників неможливо виявити у Windows 7. - No third party firewalls detected + No 3rd party firewalls detected LABEL DESKTOP Брандмауери сторонніх розробників не виявлено @@ -4819,7 +5140,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Актуально: %1 - Firewalls from third party vendors + Firewalls from 3rd party vendors LABEL DESKTOP Брандмауери від сторонніх постачальників @@ -4896,7 +5217,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u dd.MM.yyyy, hh:mm:ss LABEL DESKTOP Datetime format according to https://doc.qt.io/qt/qdate.html#toString and https://doc.qt.io/qt/qtime.html#toString - dd.MM.yyyy, hh:mm:ss + дд.ММ.рррр, гг:хх:сс Last connection: %1 @@ -4963,6 +5284,11 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL DESKTOP Не зв’язані + + Encountered error: %1 + LABEL DESKTOP + Виявлена помилка: %1 + governikus::ECardApiResult @@ -5355,9 +5681,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u PIN-код не заблоковано. - The entered PUK has already been used ten times and can no longer be used to unblock the PIN. + The entered PUK has already been used 10 times and can no longer be used to unblock the PIN. ERROR ALL_PLATFORMS The card declined the PUK since it was entered wrongfully 10 times. - Введений PUK-код уже використано десять разів, і його більше не можна використовувати для розблокування PIN-коду. + Введений PUK-код уже використано 10 разів, і його більше не можна використовувати для розблокування PIN-коду. The new PIN and the confirmation do not match. @@ -5400,9 +5726,9 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Сталася помилка під час спроби встановити з’єднання зі смартфоном як пристроєм читання карток (SaC). - The smartphone to be paired has rejected the connection. Please check the pairing code. If no pairing code is shown activate the pairing mode. + The smartphone to be paired has rejected the connection. Please check the pairing code. ERROR ALL_PLATFORMS The requested connection to the smartphone card reader (SaK) was rejected by the device. - Смартфон, з яким потрібно створити пару, відхилив з’єднання. Перевірте код створення пари. Якщо не показано код створення пари, активуйте режим створення пари. + Смартфон, з яким потрібно створити пару, відхилив з’єднання. Перевірте код створення пари. File not found. @@ -5442,22 +5768,22 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u Failed to get the ServiceInformation of the Smart-eID. ERROR ALL_PLATFORMS Failed to get the ServiceInformation of the Smart-eID - + Не вдалося отримати службову інформацію Smart-eID. The authentication to the personalization service failed. ERROR ALL_PLATFORMS No sessionID, required for a personalization, was received - + Не вдалося виконати автентифікацію до служби персоналізації. - The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN three times. You may personalize a new Smart-eID to resolve the issue. + The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN 3 times. You may personalize a new Smart-eID to resolve the issue. ERROR ALL_PLATFORMS The existing Smart-eID was invalidated. - + Ваш Smart-eID більше не готовий до використання. Це могло статися через те, що неправильний PIN-код Smart-eID було введено 3 рази. Ви можете персоналізувати новий Smart-eID, щоб вирішити проблему. The preparation of the Smart-eID failed. ERROR ANDROID The preparation of the Smart-eID Applet failed - + Не вдалося виконати підготовку Smart-eID. The program did not receive a StartPaosResponse message from the server. @@ -5467,17 +5793,17 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The server could not process the client request. ERROR_MASKED ALL_PLATFORMS - + Сервер не зміг обробити запит клієнта. The service encountered an internal error while processing a request. ERROR ALL_PLATFORMS A server has responded with an HTTP error code 5xx. - + Сервіс виявив внутрішню помилку під час обробки запиту. The service reported an error while processing a client request. ERROR ALL_PLATFORMS A server has responded with an HTTP error code 4xx. - + Сервіс повідомив про помилку під час обробки запиту клієнта. %1 Support @@ -5519,7 +5845,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u - governikus::LocalIfdReaderManagerPlugIn + governikus::LocalIfdReaderManagerPlugin Connection closed by remote with status: %1. З’єднання закрито віддалено зі статусом: %1. @@ -5535,7 +5861,7 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u dd.MM.yyyy hh:mm:ss LABEL ALL_PLATFORMS Datetime format according to https://doc.qt.io/qt/qdate.html#toString and https://doc.qt.io/qt/qtime.html#toString - dd.MM.yyyy hh:mm:ss + дд.ММ.рррр гг:хх:сс The logfile is disabled. @@ -5595,82 +5921,120 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u hh:mm:ss LABEL ALL_PLATFORMS Time format according to https://doc.qt.io/qt/qtime.html#toString - hh:mm:ss + гг:хх:сс governikus::NumberModel - You have entered an incorrect, five-digit Transport PIN. You have two further attempts to enter the correct Transport PIN. - INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. - Ви ввели неправильний п’ятизначний транспортний PIN-код. Залишилося ще дві спроби введення транспортного PIN-коду. + You have entered an incorrect, 6-digit Smart-eID PIN. You have <b>2 further attempts</b> to enter the correct Smart-eID PIN. + INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. + Ви ввели неправильний 6-значний PIN-код Smart-eID. Залишилося ще 2 спроби введення PIN-коду Smart-eID. - You have entered an incorrect, six-digit Smart-eID PIN. You have two further attempts to enter the correct Smart-eID PIN. - INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. - Ви ввели неправильний шестизначний PIN-код Smart-eID. Залишилося ще дві спроби введення PIN-коду Smart-eID. + You have entered an incorrect, 5-digit Transport PIN 3 times, your <b>Transport PIN is now blocked</b>. To remove the block, the <b>10-digit PUK</b> must be entered first. + INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. + Ви 3 рази ввели неправильний 5-значний транспортний PIN-код. Тепер ваш транспортний PIN-код заблоковано. Щоб видалити блокування, потрібно спочатку ввести 10-значний PUK-код. - You have entered an incorrect, six-digit ID card PIN. You have two further attempts to enter the correct ID card PIN. - INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. - Ви ввели неправильний шестизначний PIN-код ID-картки. Залишилося ще дві спроби введення PIN-коду ID-картки. + You have entered an incorrect, 6-digit Smart-eID PIN 3 times. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. + INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. + Ви 3 рази ввели неправильний 6-значний PIN-код Smart-eID. Ваш Smart-eID тепер недійсний. Щоб знову використовувати Smart-eID, його потрібно налаштувати за допомогою покрокового налаштування на початковій сторінці. - You have entered an incorrect, five-digit Transport PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. - Ви двічі ввели неправильний п’ятизначний транспортний PIN-код. Для третьої спроби спочатку потрібно ввести шестизначний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + You have entered an incorrect, 10-digit PUK. Please try again. + INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. + Ви ввели неправильний 10-значний PUK-код. Повторіть спробу. - You have entered an incorrect, six-digit ID card PIN twice. For a third attempt, the six-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card. - INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. - Ви двічі ввели неправильний шестизначний PIN-код ID-картки. Для третьої спроби спочатку потрібно ввести шестизначний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + You have entered an <b>incorrect, 6-digit Smart-eID PIN 2 times</b>. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. + INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a 3rd wrong attempt could invalidate the Smart-eID. + Ви 2 рази ввели неправильний 6-значний PIN-код Smart-eID. Після наступної невдалої спроби ви більше не зможете використовувати свій Smart-eID і вам потрібно буде налаштувати його знову. - You have entered an incorrect, five-digit Transport PIN thrice, your Transport PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Ви тричі ввели неправильний п’ятизначний транспортний PIN-код. Тепер ваш транспортний PIN-код заблоковано. Щоб видалити блокування, потрібно спочатку ввести десятизначний PUK-код. + The input does not match. Please choose a new Smart-eID PIN. + ALL_PLATFORMS Error message if the new pin confirmation mismatches. + Вхідні дані не збігаються. Оберіть новий PIN-код Smart-eID. - You have entered an incorrect, six-digit Smart-eID PIN thrice. Your Smart-eID is now invalidated. To use a Smart-eID again you have to set one up in the guided setup on the start page. - INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. - Ви тричі ввели неправильний шестизначний PIN-код Smart-eID. Ваш Smart-eID тепер недійсний. Щоб знову використовувати Smart-eID, його потрібно налаштувати за допомогою покрокового налаштування на початковій сторінці. + The input does not match. Please choose a new ID card PIN. + Вхідні дані не збігаються. Оберіть новий PIN-код ID-картки. + + + You have entered an incorrect, 6-digit ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 1/2 + Ви ввели неправильний 6-значний PIN-код ID-картки. + + + You have <b>2 further attempts</b> to enter the correct ID card PIN. + INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 2/2 + Залишилося ще 2 спроби введення PIN-коду ID-картки. - You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first. - INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - Ви тричі ввели неправильний шестизначний PIN-код ID-картки. Тепер PIN-код вашої ID-картки заблоковано. Щоб видалити блокування, потрібно спочатку ввести десятизначний PUK-код. + You have entered an <b>incorrect, 6-digit ID card PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Ви ввели неправильний 6-значний PIN-код ID-картки 2 рази. - You have entered an incorrect, six-digit Card Access Number (CAN). Please try again. + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN in the <b>bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 +---------- +INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 + Для 3-ї спроби спочатку потрібно ввести 6-значний номер доступу до картки (CAN). Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. + + + You have entered an incorrect, 6-digit ID card PIN 3 times. Your <b>ID card PIN is now blocked</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 1/2 + Ви ввели неправильний 6-значний PIN-код ID-картки 3 рази. PIN-код вашої ID-картки заблоковано. + + + To remove the block, the <b>10-digit PUK</b> must be entered first. You can find the PUK in the bottom <b>right next</b> to the Transport PIN in the <b>authority's letter</b>. + INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 2/2 + Щоб видалити блокування, потрібно спочатку ввести 10-значний PUK-код. PUK-код можна знайти в листі від органу влади в нижньому правому куті поряд із транспортним PIN-кодом. + + + You have entered an <b>incorrect Card Access Number (CAN)</b>. Please try again. You can find your CAN in the <b>bottom right on the front of your ID card</b>. INFO ALL_PLATFORMS The CAN was entered wrongfully and needs to be supplied again. - Ви ввели неправильний шестизначний номер доступу до картки (CAN). Повторіть спробу. + Ви ввели неправильний номер доступу до картки (CAN). Повторіть спробу. Ви можете знайти номер CAN у нижньому правому куті на лицьовому боці своєї ID-картки. - You have entered an incorrect, ten-digit PUK. Please try again. - INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. - Ви ввели неправильний десятизначний PUK-код. Повторіть спробу. + You have entered an incorrect, 5-digit Transport PIN. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. Part 1/2 + Ви ввели неправильний 5-значний транспортний PIN-код. - You have entered an incorrect, six-digit Smart-eID PIN twice. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again. - INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a third wrong attempt could invalidate the Smart-eID. - + You have <b>2 further attempts</b> to enter the correct Transport PIN. The 5-digit Transport PIN may be found on the <b>bottom left of your PIN letter</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt.Part 2/2 + Залишилося ще 2 спроби введення транспортного PIN-коду. 5-значний транспортний PIN-код можна знайти в нижній лівій частині листа з PIN-кодом. - The input does not match. Please choose a new Smart-eID PIN. - ALL_PLATFORMS Error message if the new pin confirmation mismatches. - + You have entered an <b>incorrect, 5-digit Transport PIN 2 times</b>. + INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + Ви ввели неправильний 5-значний транспортний PIN 2 рази. - The input does not match. Please choose a new ID card PIN. - + <b>An incorrect PIN has been entered 2 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 1/2 + Під час останнього використання вашої ID-картки <b>було 2 рази введено неправильний PIN-код</b>. + + + For a 3rd attempt, the <b>6-digit Card Access Number (CAN)</b> must be entered first. You can find your CAN <b>in the bottom right on the front of your ID card</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 2/2 + Для 3-ї спроби спочатку потрібно ввести <b>6-значний номер доступу до картки (CAN)</b>. Ви можете знайти номер CAN <b>у нижньому правому куті на лицьовому боці своєї ID-картки</b>. + + + <b>An incorrect PIN has been entered 3 times</b> at the last use of your ID card. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 1/2 + Під час останнього використання вашої ID-картки <b>було 3 рази введено неправильний PIN-код</b>. + + + Therefor you have to enter the <b>PUK</b> first to <b>unlock the ID card PIN</b>. + INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 2/2 + Для цього вам потрібно спочатку ввести <b>PUK-код</b>, щоб <b>розблокувати PIN-код ID-картки</b>. governikus::PinResetInformationModel - - https://www.personalausweisportal.de/EN - https://www.personalausweisportal.de/EN - You cannot use the PUK to reset your previously set card PIN. If you forgot your card PIN, you can use the PIN Reset Service to request a new PIN. LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. @@ -5681,20 +6045,71 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ALL_PLATFORMS Перейти до служби скидання PIN-коду - - You can request activation of the eID function without charge. - LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated - Ви можете надіслати запит на безкоштовну активацію функції eID. - Go to Activation Service LABEL ALL_PLATFORMS Перейти до служби активації - Request a new card PIN free of charge to be able to use the eID function again. + Find competent authority + LABEL ALL_PLATFORMS + Знайти компетентний орган + + + To find your competent authority you may visit servicesuche.bund.de. + Знайти свій компетентний орган можна, відвідавши servicesuche.bund.de. + + + If you don't have your Transport PIN letter and no access to the PUK, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. + Якщо у вас немає листа із транспортним PIN-кодом і немає доступу до PUK-коду, ви можете звернутися до компетентного органу і встановити там новий PIN-код ID-картки. + + + You may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK +---------- +LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Ви можете звернутися до компетентного органу і встановити там новий PIN-код ID-картки. + + + Please contact the competent authority to activate the eID function. + LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + Зверніться до компетентного органу, щоб активувати функцію eID. + + + If you know neither your Transport PIN nor your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + Якщо ви не знаєте ні транспортного PIN-коду, ні PIN-коду своєї ID-картки, ви можете звернутися до компетентного органу і встановити там новий PIN-код ID-картки. + + + If you cannot recall your ID card PIN, you may turn to the competent authority and set a new ID card PIN there. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Якщо ви не можете згадати PIN-код ID-картки, ви можете звернутися до компетентного органу і встановити там новий PIN-код ID-картки. + + + Request a new card PIN to be able to use the eID function again. LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK - Надішліть безкоштовно запит на новий PIN-код картки, щоб знову мати змогу користуватися функцією eID. + Надішліть запит на новий PIN-код картки, щоб знову мати змогу користуватися функцією eID. + + + You can request activation of the eID function. + LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + Ви можете надіслати запит на активацію функції eID. + + + You can use the PIN Reset Service to request a new card PIN. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Ви можете скористатися службою скидання PIN-коду, щоб надіслати запит на новий PIN-код картки. + + + If you do not know either your Transport PIN or your card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + Якщо ви не знаєте ні транспортний PIN-код, ні PIN-код картки, ви можете надіслати запит на новий PIN-код, скориставшись службою скидання PIN-коду. + + + If you have forgotten your ID card PIN, you can request a new PIN using the PIN Reset Service. + LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + Якщо ви забули PIN-код ID картки, ви можете надіслати запит на новий PIN-код, скориставшись службою скидання PIN-коду. @@ -5807,6 +6222,11 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u LABEL ALL_PLATFORMS Натисніть, щоб створити пару + + was + LABEL ALL_PLATFORMS Describes the former name of the device and is shown as: "New_Name (was Old_Name)" + був + governikus::RemoteServiceModel @@ -5823,15 +6243,6 @@ To proceed use your ID card by selecting the NFC interface. If you want to set u The NFC radio standard is required for communication with the ID card. -Unfortunately NFC is not available on your device. - INFO ALL_PLATFORMS The device does not offer NFC. - Для зв’язку з ID-карткою потрібен радіостандарт NFC. - -На жаль, NFC недоступний на вашому пристрої. - - - The NFC radio standard is required for communication with the ID card. - Please enable NFC to use your smartphone as a card reader (SaC). INFO ALL_PLATFORMS NFC is available but not active. Для зв’язку з ID-карткою потрібен радіостандарт NFC. @@ -5839,9 +6250,19 @@ Please enable NFC to use your smartphone as a card reader (SaC). Увімкніть NFC, щоб використовувати свій смартфон як пристрій читання карток (SaC). - Pairing with %1 successful. - LABEL ALL_PLATFORMS - Створено пару з %1. + This device cannot be used to read your ID card. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + + + + To pair a smartphone go to <b>Settings</b> and <b>Manage Pairings</b>. + ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + @@ -5867,17 +6288,19 @@ Please enable NFC to use your smartphone as a card reader (SaC). dd.MM.yyyy LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString - dd.MM.yyyy + дд.ММ.рррр xx.MM.yyyy - LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day - xx.MM.yyyy + LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day +---------- +LABEL ALL_PLATFORMS Additional date format with unknown day + xx.ММ.рррр xx.xx.yyyy LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day and month - xx.xx.yyyy + xx.xx.рррр Family name @@ -5945,72 +6368,72 @@ Please enable NFC to use your smartphone as a card reader (SaC). The online check for the Smart-eID support on your device failed. Please note that this process requires an internet connection. ERROR ANDROID IOS The check for Smart-eID support failed without any specific reason. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої. Зверніть увагу, що для цього процесу потрібне підключення до Інтернету. The online check for the Smart-eID support on your device failed because the server is currently facing too many requests. Please try again later. ERROR ANDROID IOS The check for Smart-eID support failed because the server is overloaded. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої, оскільки на сервері наразі надто багато запитів. Повторіть спробу пізніше. The online check for the Smart-eID support on your device failed because the server is currently under maintenance. Please try again later. ERROR ANDROID IOS The check for Smart-eID support failed because the server is being maintained. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої, оскільки сервер перебуває наразі на технічному обслуговуванні. Повторіть спробу пізніше. The Smart-eID data and provisioning could not be successfully deleted from your device. Please note that this process requires an internet connection. ERROR ANDROID IOS Deletion of the Smart-eID failed without a specific reason. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою. Зверніть увагу, що для цього процесу потрібне підключення до Інтернету. The Smart-eID data and provisioning could not be successfully deleted from your device because the server is currently facing too many requests. Please try again later. ERROR ANDROID IOS Deletion of the Smart-eID failed because the server is overloaded. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою, оскільки на сервері наразі надто багато запитів. Повторіть спробу пізніше. The Smart-eID data and provisioning could not be successfully deleted from your device because the server is currently under maintenance. Please try again later. ERROR ANDROID IOS Deletion of the Smart-eID failed because the server is being maintained. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою, оскільки сервер перебуває наразі на технічному обслуговуванні. Повторіть спробу пізніше. The Smart-eID data and provisioning could not be successfully deleted from your device. In order to access the necessary device storage, active NFC functionality is required. Please activate NFC and restart the process. ERROR ANDROID IOS Deletion of the Smart-eID failed because NFC is not activated. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою. Щоб отримати доступ до необхідної пам’яті пристрою, потрібна активна функція NFC. Увімкніть NFC і перезапустіть процес. The online check for the Smart-eID support on your device failed. In order to access the necessary device storage, active NFC functionality is required. Please activate NFC and try again. ERROR ANDROID IOS The check for Smart-eID support failed because the NFC functionality is not activated. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої. Щоб отримати доступ до необхідної пам’яті пристрою, потрібна активна функція NFC. Увімкніть NFC і спробуйте ще раз. The online check for the Smart-eID support on your device failed. The Google Play Integrity Check failed. ERROR ANDROID IOS The check for Smart-eID support failed because Google Play Integrity Check failed. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої. Не вдалося виконати перевірку благонадійності Google Play. The online check for the Smart-eID support on your device failed. An authentication issue occurred (e.g. a resource was accessed without authorization or an unauthorized app tried to access a security component). ERROR ANDROID IOS The check for Smart-eID support failed because an authorization issue occurred. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої. Виникла проблема з автентифікацією (наприклад, доступ до ресурсу було отримано без дозволу або неавторизований додаток намагався отримати доступ до компонента безпеки). The Smart-eID data and provisioning could not be successfully deleted from your device. The Google Play Integrity Check failed. ERROR ANDROID IOS Deletion of the Smart-eID failed because the Google Play Integrity Check failed. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою. Не вдалося виконати перевірку благонадійності Google Play. The Smart-eID data and provisioning could not be successfully deleted from your device. An authentication issue occurred (e.g. a resource was accessed without authorization or an unauthorized app tried to access a security component). ERROR ANDROID IOS Deletion of the Smart-eID failed because an authorization issue occurred. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою. Виникла проблема з автентифікацією (наприклад, доступ до ресурсу було отримано без дозволу або неавторизований додаток намагався отримати доступ до компонента безпеки). The online check for the Smart-eID support on your device failed. Please ensure that you have an internet connection and your antivirus software and firewall are not blocking the connection. ERROR ANDROID IOS The check for Smart-eID support failed because a network connection error occurred. - + Не вдалося виконати онлайн-перевірку підтримки Smart-eID на вашому пристрої. Переконайтеся, що у вас є підключення до Інтернету, а антивірусне програмне забезпечення та брандмауер не блокують з’єднання. The Smart-eID data and provisioning could not be successfully deleted from your device. Please ensure that you have an internet connection and your antivirus software and firewall are not blocking the connection. ERROR ANDROID IOS Deletion of the Smart-eID failed because a network connection error occurred. - + Не вдалося видалити дані й налаштування Smart-eID з вашого пристрою. Переконайтеся, що у вас є підключення до Інтернету, а антивірусне програмне забезпечення та брандмауер не блокують з’єднання. @@ -6036,15 +6459,10 @@ Please enable NFC to use your smartphone as a card reader (SaC). governikus::StateConnectCard - - The used card reader does not meet the technical requirements (Extended Length not supported). - INFO IOS - Використовуваний пристрій читання карток не відповідає технічним вимогам (Extended Length не підтримується). - The used ID card type is not accepted by the server. INFO IOS - + Сервер не приймає тип ID-картки, що використовується. @@ -6052,7 +6470,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). Cleaning up old Smart-eID LABEL ANDROID IOS - Очищення старого Smart-eID + Очищення старого Smart-eID @@ -6139,7 +6557,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). Installing Smart-eID LABEL ANDROID IOS - Установлення Smart-eID + Установлення Smart-eID @@ -6169,11 +6587,11 @@ Please enable NFC to use your smartphone as a card reader (SaC). Checking Smart-eID status LABEL ANDROID IOS - Перевірка статусу Smart-eID + Перевірка статусу Smart-eID - governikus::SurveyModel + governikus::Survey Vendor Продавець @@ -6204,7 +6622,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). %1 Version - Версія %1 + %1 Версія NFC Tag Type @@ -6230,21 +6648,21 @@ Please enable NFC to use your smartphone as a card reader (SaC). - governikus::UIPlugInProxy + governikus::UiPluginProxy Reverse proxy plugin is enabled Плагін зворотного проксі ввімкнено - governikus::UIPlugInQml + governikus::UiPluginQml Information Інформація - governikus::UIPlugInWebService + governikus::UiPluginWebService An unknown program uses the required port (%1). Please exit the other program and try again! ERROR ALL_PLATFORMS An unknown programme is using the local port on which the AA2 listens. @@ -6267,7 +6685,7 @@ Please enable NFC to use your smartphone as a card reader (SaC). Reverse-Proxy of %1 is started and this instance cannot rebind port. Please ask your administrator! - Запущено зворотний проксі додатка %1, і цей екземпляр не може перепризначити порт. Зверніться до свого адміністратора! + Запущено зворотний проксі програми %1, і цей екземпляр не може перепризначити порт. Зверніться до свого адміністратора! Cannot start authentication @@ -6320,9 +6738,9 @@ Please enable NFC to use your smartphone as a card reader (SaC). Повідомити зараз - The connection to the browser was lost. No forwarding was executed. Please try to call the URL again manually: %1 + The connection to the browser was lost while redirecting to the provider (%1). No automatic redirection could be performed. ERROR ALL_PLATFORMS The connection to the browser was lost/timed out.. - З’єднання з браузером було втрачено. Перенаправлення не виконано. Спробуйте викликати URL ще раз вручну: %1 + З'єднання з браузером було втрачено під час переспрямування до провайдера (%1). Не вдалося виконати автоматичне переспрямування. @@ -6338,109 +6756,32 @@ Please enable NFC to use your smartphone as a card reader (SaC). The used Smart-eID is not accepted by the server. Please restart the remote service on your connected smartphone and try again with a physical ID card. INFO ALL_PLATFORMS - + Сервер не приймає Smart-eID, що використовується. Перезапустіть віддалений сервіс на підключеному смартфоні та спробуйте ще раз із фізичною ID-карткою. The used Smart-eID is not accepted by the server. Please stop the remote service and use another Smart-eID or contact the service provider. INFO ALL_PLATFORMS - + Сервер не приймає Smart-eID, що використовується. Зупиніть віддалений сервіс та скористайтеся іншим Smart-eID або зверніться до постачальника послуг. The used ID card is not accepted by the server. Please remove the ID card from your device or card reader and use a Smart-eID or contact the service provider. INFO ALL_PLATFORMS - + Сервер не приймає ID-картку, що використовується. Вийміть ID-картку із пристрою чи пристрою читання карток і скористайтеся Smart-eID або зверніться до постачальника послуг. Renew your Smart-eID and set a new PIN in the Smart-eID menu. LABEL ANDROID IOS The hint text that is shwon right above the redirect button that appears when a user tried to usa an unusable Smart-eID - + Поновіть свій Smart-eID і встановіть новий PIN-код у меню Smart-eID. Go to Smart-eID menu LABEL ANDROID IOS The text on the redirect button that appears when the user tried to use an unusable Smart-eID - - - - - main - - Another application uses %1 - INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. - Інша програма використовує %1 - - - The user interface of the %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is closed for the first time. - Інтерфейс користувача %1 закрито. - - - The program remains available via the icon in the system tray. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. - Програма залишається доступною через піктограму в системному лотку. Натисніть піктограму %1, щоб знову відкрити інтерфейс користувача. - - - Do not show this dialog again. - LABEL DESKTOP - Більше не показувати це діалогове вікно. - - - This will cancel the current operation and hide the UI of %1. You can restart the operation at any time. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and a workflow is still active. - Це скасує поточну операцію та приховає інтерфейс користувача %1. Ви можете перезапустити операцію в будь-який час. - - - Abort operation - INFO DESKTOP Header of the popup that is shown when the AA2 is closed and a workflow is still active - Перервати операцію - - - Failed to retrieve update information. - INFO DESKTOP Message that the update data is invalid and can't be used. - Не вдалося отримати інформацію про оновлення. - - - An update is available (version %1). - INFO DESKTOP An update was found which matches the current platform, the new version number is shown in the message. - Доступне оновлення (версія %1). - - - Developer Mode: Enabled! - LABEL DESKTOP - Режим розробника: Увімкнено! - - - Disable - LABEL DESKTOP Global button to disable developer mode. - Вимкнути - - - Detached log viewer - Відключений засіб перегляду журналів - - - To close the app, quickly press the back button twice. - INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). - Щоб закрити програму, двічі швидко натисніть кнопку «Назад». - - - The program remains available via the icon in the menu bar. Click on the %1 icon to reopen the user interface. - INFO DESKTOP Content of the popup that is shown when the AA2 is closed and the close/minimize info was not disabled. macOS specific if autostart is enabled. - Програма залишається доступною через піктограму на панелі меню. Натисніть піктограму %1, щоб знову відкрити інтерфейс користувача. - - - The %1 will be shut down and an authentication will no longer be possible. You will have to restart the %1 to identify yourself towards providers. - INFO DESKTOP Text of the popup that is shown when the AA2 is quit for the first time. - + Перейти до меню Smart-eID - The %1 is closed. - INFO DESKTOP Header of the popup that is shown when the AA2 is quit for the first time. - - - - This will cancel the current operation and shut the %1 down. You will have to restart the %1 to restart the operation. - INFO DESKTOP Content of the popup that is shown when the AA2 is shut down and a workflow is still active. - + Set a new PIN + LABEL ALL_PLATFORMS Hint title to assist the user on how to set a new PIN + Установити новий PIN-код diff --git a/resources/updatable-files/reader/img_ACS_ACR1281U_mit_ausweis.png b/resources/updatable-files/reader/img_ACS_ACR1281U_mit_ausweis.png deleted file mode 100644 index ff2e55b60..000000000 Binary files a/resources/updatable-files/reader/img_ACS_ACR1281U_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_ACS_ACR1581U-C1.png b/resources/updatable-files/reader/img_ACS_ACR1581U-C1.png new file mode 100644 index 000000000..9125a5879 Binary files /dev/null and b/resources/updatable-files/reader/img_ACS_ACR1581U-C1.png differ diff --git a/resources/updatable-files/reader/img_Cherry_ST_1275_mit_ausweis.png b/resources/updatable-files/reader/img_Cherry_ST_1275_mit_ausweis.png deleted file mode 100644 index 2ed89949f..000000000 Binary files a/resources/updatable-files/reader/img_Cherry_ST_1275_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Cherry_TC_1200_mit_ausweis.png b/resources/updatable-files/reader/img_Cherry_TC_1200_mit_ausweis.png deleted file mode 100644 index 67736d28e..000000000 Binary files a/resources/updatable-files/reader/img_Cherry_TC_1200_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Cherry_TC_1300_mit_ausweis.png b/resources/updatable-files/reader/img_Cherry_TC_1300_mit_ausweis.png deleted file mode 100644 index dec65ecb9..000000000 Binary files a/resources/updatable-files/reader/img_Cherry_TC_1300_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Cherry_secure_board_mit_ausweis.png b/resources/updatable-files/reader/img_Cherry_secure_board_mit_ausweis.png deleted file mode 100644 index e83dbe318..000000000 Binary files a/resources/updatable-files/reader/img_Cherry_secure_board_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_FEIG_myAXXES_basic_mit_ausweis.png b/resources/updatable-files/reader/img_FEIG_myAXXES_basic_mit_ausweis.png deleted file mode 100644 index b7a608cea..000000000 Binary files a/resources/updatable-files/reader/img_FEIG_myAXXES_basic_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Gemalto_Prox_DU_mit_ausweis.png b/resources/updatable-files/reader/img_Gemalto_Prox_DU_mit_ausweis.png deleted file mode 100644 index cdcbc0981..000000000 Binary files a/resources/updatable-files/reader/img_Gemalto_Prox_DU_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Gemalto_Prox_SU_mit_ausweis.png b/resources/updatable-files/reader/img_Gemalto_Prox_SU_mit_ausweis.png deleted file mode 100644 index 9d13a00ae..000000000 Binary files a/resources/updatable-files/reader/img_Gemalto_Prox_SU_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_HID_Global_OMNIKEY_5321_V2_mit_ausweis.png b/resources/updatable-files/reader/img_HID_Global_OMNIKEY_5321_V2_mit_ausweis.png deleted file mode 100644 index 9004b5f26..000000000 Binary files a/resources/updatable-files/reader/img_HID_Global_OMNIKEY_5321_V2_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_HID_Omnikey_542x_mit_ausweis.png b/resources/updatable-files/reader/img_HID_Omnikey_542x_mit_ausweis.png deleted file mode 100644 index 651f06134..000000000 Binary files a/resources/updatable-files/reader/img_HID_Omnikey_542x_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_HID_Omnikey_Mobile_Reader_502X_CL_mit_ausweis.png b/resources/updatable-files/reader/img_HID_Omnikey_Mobile_Reader_502X_CL_mit_ausweis.png deleted file mode 100644 index 9ea5929c5..000000000 Binary files a/resources/updatable-files/reader/img_HID_Omnikey_Mobile_Reader_502X_CL_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_4701_F_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_4701_F_mit_ausweis.png deleted file mode 100644 index 6fd89fd55..000000000 Binary files a/resources/updatable-files/reader/img_Identive_4701_F_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_Cloud_4700_F_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_Cloud_4700_F_mit_ausweis.png deleted file mode 100644 index 6fd89fd55..000000000 Binary files a/resources/updatable-files/reader/img_Identive_Cloud_4700_F_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_SCL011_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_SCL011_mit_ausweis.png deleted file mode 100644 index 55c4911f1..000000000 Binary files a/resources/updatable-files/reader/img_Identive_SCL011_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_SCL3711_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_SCL3711_mit_ausweis.png deleted file mode 100644 index d08338654..000000000 Binary files a/resources/updatable-files/reader/img_Identive_SCL3711_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_SDI011_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_SDI011_mit_ausweis.png deleted file mode 100644 index 03f28ab59..000000000 Binary files a/resources/updatable-files/reader/img_Identive_SDI011_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Identive_XXXX_F_mit_ausweis.png b/resources/updatable-files/reader/img_Identive_XXXX_F_mit_ausweis.png deleted file mode 100644 index 6d21fda02..000000000 Binary files a/resources/updatable-files/reader/img_Identive_XXXX_F_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_KOBIL_ID_Token_mit_ausweis.png b/resources/updatable-files/reader/img_KOBIL_ID_Token_mit_ausweis.png deleted file mode 100644 index 55110d6aa..000000000 Binary files a/resources/updatable-files/reader/img_KOBIL_ID_Token_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_PersoSim_mit_ausweis.png b/resources/updatable-files/reader/img_PersoSim_mit_ausweis.png deleted file mode 100644 index c0713a6ee..000000000 Binary files a/resources/updatable-files/reader/img_PersoSim_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_basis_mit_ausweis.png b/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_basis_mit_ausweis.png deleted file mode 100644 index abb555431..000000000 Binary files a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_basis_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_komfort_mit_ausweis.png b/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_komfort_mit_ausweis.png deleted file mode 100644 index 7c6949a5f..000000000 Binary files a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_komfort_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_standard_mit_ausweis.png b/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_standard_mit_ausweis.png deleted file mode 100644 index 19d690d6c..000000000 Binary files a/resources/updatable-files/reader/img_Reiner_SCT_cyberjack_RFID_standard_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_RemoteReader_mit_ausweis.png b/resources/updatable-files/reader/img_RemoteReader_mit_ausweis.png deleted file mode 100644 index 4cffc7c73..000000000 Binary files a/resources/updatable-files/reader/img_RemoteReader_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Signotec_Omega_Pad_mit_ausweis.png b/resources/updatable-files/reader/img_Signotec_Omega_Pad_mit_ausweis.png deleted file mode 100644 index 2163b7ce8..000000000 Binary files a/resources/updatable-files/reader/img_Signotec_Omega_Pad_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_Simulator_mit_ausweis.png b/resources/updatable-files/reader/img_Simulator_mit_ausweis.png deleted file mode 100644 index 1bacd3f82..000000000 Binary files a/resources/updatable-files/reader/img_Simulator_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/reader/img_cyberjack_wave_mit_ausweis.png b/resources/updatable-files/reader/img_cyberjack_wave_mit_ausweis.png deleted file mode 100644 index 12f6c740a..000000000 Binary files a/resources/updatable-files/reader/img_cyberjack_wave_mit_ausweis.png and /dev/null differ diff --git a/resources/updatable-files/supported-providers.json b/resources/updatable-files/supported-providers.json index 4a1a59b1c..9ff9d58d8 100644 --- a/resources/updatable-files/supported-providers.json +++ b/resources/updatable-files/supported-providers.json @@ -139,7 +139,7 @@ "homepage": "https://www.bitkasten.de", "phone": "+49 911 6099 8688", "email": "nachricht@bitkasten.de", - "postalAddress": "bitkasten AG
Wallensteinstr. 63
90431 Nürnberg", + "postalAddress": "bitkasten GmbH
Wallensteinstr. 63
90431 Nürnberg", "image": "bitkasten_image.png", "icon": "bitkasten_icon.png", "category": "other", @@ -147,6 +147,44 @@ "https://mein.bitkasten.de" ] }, + { + "shortName": { + "": "Adoption Digital" + }, + "longName": { + "": "Adoption Digital" + }, + "longDescription": { + "": "Der Online-Dienst 'Adoption Digital' ist ein digitaler Dienst mit dem Ziel den Bürger:innen, die ein Kind adoptieren möchten, eine vereinfachte Möglichkeit anzubieten einen Antrag auf Adoption zu stellen. Mit Hilfe des Online-Dienstes können Antragstellende die nötigen Formulare bequem von zu Hause aus online ausfüllen. Neben eines Kontaktformulars zur ersten Kontaktaufnahme mit der entsprechenden Adoptionsvermittlungsstelle, bietet der Online-Dienst auch Formulare für die weitere Antragstellung. Interessierte Bürger:innen können das entsprechende Bewerbungsformular zur Fremdkind-, Stiefkind- oder Verwandtenkindadoption ebenfalls im Online-Dienst ausfüllen. Geforderte Nachweise können direkt hochgeladen und dem Formular angehängt werden oder zu einem späteren Zeitpunkt digital nachgereicht werden. Der Online-Dienst erspart nicht nur Antragstellenden, sondern auch den Adoptionsvermittlungsstellen und Behörden Zeit und Aufwand. Für Bürger:innen, die sich zunächst informieren möchten, stellt der Online-Dienst erste wichtige Informationen über eine Adoption und dessen Prozess zur Verfügung." + }, + "address": "https://www.adoption-und-pflegekinderwesen.de", + "homepage": "https://www.adoption-und-pflegekinderwesen.de", + "email": "info@betriebskoordination.bremen.de", + "postalAddress": "Der Senator für Finanzen
Am Tabakquartier 56
28197 Bremen", + "image": "AdoptionDigital_image.png", + "icon": "AdoptionDigital_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." + }, + { + "shortName": { + "": "Pflegekinderwesen Digital" + }, + "longName": { + "": "Pflegekinderwesen Digital" + }, + "longDescription": { + "": " Der Online Dienst 'Pflegekinderwesen Digital' ist ein digitaler Dienst mit dem Ziel den Bürger:innen, die ein Kind in Pflege nehmen möchten oder finanzielle Leistungen für ein Pflegekind beantragen möchten, eine vereinfachte Möglichkeit anzubieten diese Anträge zu stellen. Mit Hilfe des Online Dienstes können Antragstellende die nötigen Formulare bequem von zu Hause aus online ausfüllen. Neben eines Kontaktformulars zur ersten Kontaktaufnahme mit der entsprechenden Pflegestelle bietet der Online Dienst auch Formulare für die weitere Antragstellung. Interessierte Bürger:innen können das Bewerbungsformular für Pflegeeltern ebenso im Online Dienst ausfüllen. Für Eltern, die bereits ein Kind in Pflege genommen haben, gibt es weitere Formulare zur Beantragung von finanziellen Leistungen wie beispielsweise die Beitragsübernahme der Unfallversicherung, eine Bezuschussung der Altersabsicherung und Leistungen gemäß Paragraf 33 und 39 SGB VIII. Geforderte Nachweise können direkt hochgeladen und dem Formular angehängt werden oder zu einem späteren Zeitpunkt digital nachgereicht werden. Außerdem haben Antragstellende die Möglichkeit einen formlosen Antrag zu stellen. Der Online Dienst erspart nicht nur Antragstellenden, sondern auch den Pflegestellen und Behörden Zeit und Aufwand. Für Bürger:innen, die sich zunächst informieren möchten, stellt der Online Dienst erste wichtige Informationen über die Aufnahme eines Pflegekindes und dessen Prozess zur Verfügung." + }, + "address": "https://www.adoption-und-pflegekinderwesen.de", + "homepage": "https://www.adoption-und-pflegekinderwesen.de", + "email": "info@betriebskoordination.bremen.de", + "postalAddress": "Der Senator für Finanzen
Am Tabakquartier 56
28197 Bremen", + "image": "PflegekinderwesenDigital_image.png", + "icon": "PflegekinderwesenDigital_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." + }, { "shortName": { "": "Akteneinsicht in Stasi-Unterlagen" @@ -332,13 +370,13 @@ "longName": { "": "Stadt Braunschweig - Internetbasierte Fahrzeugzulassung" }, - "address": "https://stadt-braunschweig.govconnect.de", + "address": "https://service.braunschweig.de", "homepage": "https://braunschweig.de", "phone": "+49 531 4701", "email": "stadt@braunschweig.de", "postalAddress": "Stadt Braunschweig
Platz der Deutschen Einheit 1
38100 Braunschweig", "category": "citizen", - "subjectUrlInfo": "Using service from Niedersächsisches Ministerium für Inneres und Sport (https://e-id.niedersachsen.de)." + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." }, { "shortName": { @@ -360,6 +398,28 @@ "https://formular.arbeitsagentur.de" ] }, + { + "shortName": { + "": "Bundesanzeiger Verlag GmbH" + }, + "longName": { + "": "Bundesanzeiger Verlag GmbH" + }, + "longDescription": { + "": "Für die Übermittlung von Rechnungslegungsunterlagen von den im Handels- oder Genossenschaftsregister eingetragenen Unternehmen an das Unternehmensregister muss nach den Vorgaben der URV im Rahmen einer Registrierung eine einmalige, elektronische Identitätsprüfung des Nutzers anhand bestimmter elektronischer Identifizierungsmittel, u.a. mit der Online-Ausweisfunktion des Personalausweises, erfolgen." + }, + "address": "https://ident.bundesanzeiger-verlag.de", + "homepage": "https://www.bundesanzeiger-verlag.de", + "phone": "+49 221 97668 275", + "email": "service@bundesanzeiger.de", + "postalAddress": "Bundesanzeiger Verlag GmbH
Amsterdamer Straße 192
50735 Köln", + "image": "BundesanzeigerVerlag_image.jpg", + "icon": "BundesanzeigerVerlag_icon.svg", + "category": "other", + "subjectUrls": [ + "https://ident.bundesanzeiger-verlag.de" + ] + }, { "eidSupport": false, "shortName": { @@ -399,6 +459,26 @@ "https://servicekonto.bremen.de" ] }, + { + "shortName": { + "": "Bürgerservice Online Stadt Memmingen" + }, + "longName": { + "": "Online Bürgerservice der Stadt Memmingen" + }, + "longDescription": { + "": "Hier finden Sie eine Übersicht der Verwaltungs-Dienstleistungen, die Sie online erledigen können. Unser Bürgerservice Online ist Ihr Zugang zu den Onlineverfahren und dem Virtuellen Rathaus der Stadtverwaltung Memmingen mit den jeweiligen Ansprechpartnern und weiteren Informationen, wie z. B. die für die Behördendienstleistung notwendigen Papiere und ggf. Kosten innerhalb der Stadtverwaltung." + }, + "address": "https://www.memmingen.de/buergerservice/virtuelles-rathaus/buergerservice-online.html", + "homepage": "https://www.memmingen.de", + "phone": "+49 8331 8500", + "email": "digitalisierung@memmingen.de", + "postalAddress": "Stadtverwaltung Memmingen
Marktplatz 1
87700 Memmingen", + "image": "StadtMemmingen_image.jpg", + "icon": "StadtMemmingen_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from Bürgerservice-Portale der bayerischen Kommunen (https://bayernid.freistaat.bayern)." + }, { "shortName": { "": "Bürgerdienste der Stadt Münster" @@ -409,7 +489,7 @@ "longDescription": { "": "Die Stadt Münster bietet auf ihrer Webseite eine Reihe von Online-Diensten an. Dort können Sie mit der Online-Ausweisfunktion unter anderem:
  • eine Personenstandsurkunde bestellen,
  • Ihr Wunschkennzeichen beantragen,
  • geografische Karten bestellen,
  • Elektroschrott zur Abholung anmelden,
  • eine Erklärung zum Elterneinkommen für die Festsetzung des Elternbeitrags für die Kindertagesbetreuung abgeben,
  • eine Sondernutzungserlaubnis für private Baumaßnahmen an öffentlichen Straßen beantragen,
  • eine Großanlage mit zentraler Trinkwassererwärmung anzeigen,
  • einen Fahrradfund melden,
  • ein Reitkennzeichen beantragen,
  • Mietspiegel-Broschüren bestellen.
" }, - "address": "https://www.stadt-muenster.de/online-dienste", + "address": "https://www.stadt-muenster.de/service/online-services", "homepage": "https://www.stadt-muenster.de", "phone": "+49 251 4 92 0", "email": "stadtverwaltung@stadt-muenster.de", @@ -486,7 +566,7 @@ "longDescription": { "": "In unserem Bürgerservice-Portal können Sie Anträge an die Kreisverwaltung Herford online erfassen und direkt zur weiteren Bearbeitung an die zuständigen Stellen übermitteln." }, - "address": "https://www.kreis-herford.de/i-KFZ-Stufe 4", + "address": "https://www.kreis-herford.de/i-KFZ-Stufe%204", "homepage": "https://www.kreis-herford.de", "phone": "+49 5223 988 500", "email": "portal@kreis-herford.de", @@ -540,15 +620,15 @@ { "eidSupport": false, "shortName": { - "": "Bürgerservice-Portal Stadt Lage" + "": "Onlinedienste Stadt Lage" }, "longName": { - "": "Bürgerservice-Portal Stadt Lage" + "": "Onlinedienste Stadt Lage" }, "longDescription": { - "": "Das Bürgerservice-Portal bietet die Möglichkeit, Anträge an die Verwaltung der Stadt Lage online zu erfassen und elektronisch zur weiteren Bearbeitung weiterzuleiten." + "": "Die Onlinedienste der Stadt Lage bieten die Möglichkeit, Anträge an die Verwaltung der Stadt Lage online zu erfassen und elektronisch zur weiteren Bearbeitung weiterzuleiten." }, - "address": "https://www.buergerserviceportal.nrw/krz/lage", + "address": "https://onlinedienste-owl.de/Lage", "homepage": "https://www.lage.de", "phone": "+49 5232 601300", "email": "Buergerbuero@lage.de", @@ -743,6 +823,25 @@ "https://www.elster.de" ] }, + { + "shortName": { + "": "eWA" + }, + "longName": { + "": "Elektronische Wohnsitzanmeldung" + }, + "longDescription": { + "": "Sind Sie gerade umgezogen und möchten Ihren Wohnsitz anmelden? Das ist jetzt online und gebührenfrei möglich! Mit der elektronischen Wohnsitzanmeldung können Sie Ihrer Meldebehörde Ihre neue Wohnanschrift einfach online mitteilen. Sie erhalten eine digitale Meldebestätigung. Auch die Aktualisierung Ihres Personalausweises, Reisepasses oder Ihrer eID-Karte erfolgt über den Online-Dienst. Am einfachsten geht es mit Ihrem Smartphone.
Die elektronische Wohnsitzanmeldung ist ein bundesweiter Service der Freien und Hansestadt Hamburg, der stetig erweitert wird. Unter www.wohnsitzanmeldung.de können Sie prüfen, ob Ihre Kommune schon dabei ist." + }, + "address": "https://wohnsitzanmeldung.de", + "homepage": "https://wohnsitzanmeldung.de", + "email": "ewa@sk.hamburg.de", + "postalAddress": "Freie und Hansestadt Hamburg Senatskanzlei - Amt für IT und Digitalisierung
Caffamacherreihe 1-3
20354 Hamburg", + "image": "eWa_image.png", + "icon": "eWa_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from Gemeinsam-Online (https://idp.serviceportal.gemeinsamonline.de)" + }, { "eidSupport": false, "shortName": { @@ -883,7 +982,7 @@ "longDescription": { "": "Mit i-Kfz können Sie Ihr Auto per Internet von zu Hause aus zulassen. Derzeit sind online folgende Dienstleistungen möglich:
  • Neuzulassung
  • Umschreibung
  • Wiederzulassung
  • Adressänderung
  • Außerbetriebsetzung
" }, - "address": "https://ikfz.ikfz-sachsen.de/ikfz3/?LICENSEIDENTIFIER=nordsachsen_kreis", + "address": "https://www.landkreis-nordsachsen.de/was-erledige-ich-wo/dezernat/sachgebiet-kfz-zulassungsbehoerde", "homepage": "https://www.landkreis-nordsachsen.de", "phone": "+49 3421 758 5143", "email": "ikfz@lra-nordsachsen.de", @@ -1034,6 +1133,24 @@ "category": "citizen", "subjectUrlInfo": "Using service from Bürgerservice-Portal Krz (https://www.buergerserviceportal.nrw)." }, + { + "shortName": { + "": "Organspende-Register" + }, + "longName": { + "": "Abgabe einer Erklärung im Organspende-Register" + }, + "longDescription": { + "": "Im Register für Erklärungen zur Organ und Gewebespende (Organspende-Register) können Bürgerinnen und Bürger ihre Entscheidung für oder gegen eine Organ- und Gewebespende festhalten. Dies erleichtert es Ärztinnen und Ärzten, die Spendebereitschaft potenzieller Organspenderinnen und -spender schnell und verlässlich zu klären. Der Eintrag ist freiwillig, kostenlos und kann jederzeit geändert oder gelöscht werden.
Zur Abgabe der Erklärung im Organspende-Register ist die Bestätigung der eigenen Identität erforderlich. Über die AusweisApp können Sie sich digital identifizieren. Hierfür benötigen Sie lediglich Ihren Online-Ausweis, die dazugehörige PIN, ein geeignetes Smartphone oder Tablet sowie die installierte AusweisApp.
Weitere Informationen zum Organspende-Register erhalten Sie hier: https://www.organspende-info.de/organspende-register/." + }, + "address": "https://organspende-register.de", + "homepage": "https://www.bfarm.de", + "email": "poststelle@bfarm.de", + "postalAddress": "Kurt-Georg-Kiesinger-Allee 3
53175 Bonn", + "icon": "OrganspendeRegister_icon.svg", + "category": "other", + "subjectUrlInfo": "https://eid.organspende-register.de" + }, { "shortName": { "": "Serviceportal Solingen" @@ -1091,7 +1208,7 @@ "category": "citizen", "image": "Hameln-Pyrmont_image.png", "icon": "Hameln-Pyrmont_icon.png", - "subjectUrlInfo": "Using service from Servicekonto Niedersachsen (https://idp.servicekonto.niedersachsen.de)." + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." }, { "shortName": { @@ -1287,45 +1404,6 @@ "https://e-id.niedersachsen.de" ] }, - { - "internalId": "pinResetService", - "shortName": { - "": "Neue PIN für den Online-Ausweis bestellen" - }, - "longName": { - "": "Neue PIN für den Online-Ausweis bestellen" - }, - "longDescription": { - "": "Wenn Sie Ihre PIN für den Online-Ausweis vergessen haben, Sie Ihren PIN-Brief mit der Transport-PIN nicht mehr haben oder Ihre PIN blockiert ist, können Sie hier einen PIN-Rücksetzbrief bestellen.

Sie erhalten diesen Brief per Post an Ihre deutsche Meldeadresse. Er enthält einen Aktivierungscode und eine neue PIN für Ihren Online-Ausweis, sodass Sie diesen im Anschluss wieder nutzen können." - }, - "address": "https://www.pin-ruecksetzbrief-bestellen.de", - "homepage": "https://www.pin-ruecksetzbrief-bestellen.de/support", - "phone": "+49 30 18 681 23333", - "postalAddress": "Bundesministerium des Innern und für Heimat
Alt-Moabit 140
10557 Berlin", - "icon": "BMI_PIN_Reset_icon.svg", - "category": "citizen", - "subjectUrls": [ - "https://www.pin-ruecksetzbrief-bestellen.de" - ] - }, - { - "shortName": { - "": "Online-Ausweis nachträglich aktivieren" - }, - "longName": { - "": "Online-Ausweis nachträglich aktivieren" - }, - "longDescription": { - "": "Wenn Ihre Online-Ausweisfunktion nicht aktiviert ist, können Sie diese nachträglich durch Bestellung eines PIN-Rücksetzbriefes aktivieren. Sie erhalten den Brief per Post an Ihre deutsche Meldeadresse. Der Brief enthält einen Aktivierungscode und eine neue PIN für Ihren Online-Ausweis, sodass Sie diesen im Anschluss nutzen können." - }, - "address": "https://www.pin-ruecksetzbrief-bestellen.de", - "homepage": "https://www.pin-ruecksetzbrief-bestellen.de/support", - "phone": "+49 30 18 681 23333", - "postalAddress": "Bundesministerium des Innern und für Heimat
Alt-Moabit 140
10557 Berlin", - "icon": "BMI_Aktivierung_icon.svg", - "category": "citizen", - "subjectUrlInfo": "Using service from Neue PIN für den Online-Ausweis bestellen (https://www.pin-ruecksetzbrief-bestellen.de)." - }, { "shortName": { "": "Siegburg Online" @@ -1376,8 +1454,8 @@ "longDescription": { "": "Wir stellen Online-Dienstleistungen aus Bad Oeynhausen, dem Kreis Minden-Lübbecke, dem Land NRW und den Bundesbehörden zur Verfügung.

Sie können unseren Service ohne Anmeldung oder mit einer Anmeldung über das Servicekonto.NRW nutzen. Für die Nutzung von ePayment ist eine Anmeldung mit dem Servicekonto Voraussetzung." }, - "address": "https://portal.kommunale.it/bad-oeynhausen/login", - "homepage": "https://portal.kommunale.it/bad-oeynhausen/services", + "address": "https://www.badoeynhausen.de/rathaus-service-politik", + "homepage": "https://www.badoeynhausen.de", "phone": "+49 5731 14 0", "email": "egov@badoeynhausen.de", "postalAddress": "Stadt Bad Oeynhausen
Der Bürgermeister
Ostkorso 8
32545 Bad Oeynhausen", @@ -1417,7 +1495,7 @@ "": "In unserem Service-Portal können Sie Anträge an die Kreisverwaltung Soest online erfassen und direkt zur weiteren Bearbeitung an die zuständigen Stellen übermitteln." }, "address": "https://serviceportal.kreis-soest.de", - "homepage": "https://www.kreis-soest.de/start", + "homepage": "https://www.kreis-soest.de", "phone": "+49 2921 30 0", "email": "service-portal@kreis-soest.de", "postalAddress": "Kreisverwaltung Soest
Hoher Weg 1-3
59494 Soest", @@ -1445,6 +1523,25 @@ "category": "citizen", "subjectUrlInfo": "Using service from Servicekonto Nordrhein-Westfalen (https://servicekonto.nrw)." }, + { + "shortName": { + "": "Onlinedienste der Stadt Neuötting" + }, + "longName": { + "": "Onlinedienste der Stadt Neuötting" + }, + "longDescription": { + "": "Im Online-Portal der Stadt Neuötting können Sie immer mehr digitale Verwaltungsleistungen in Verbindung mit der Bayern-ID nutzen." + }, + "address": "https://www.neuoetting.de/dienste-informationen/online-formulare", + "homepage": "https://www.neuoetting.de", + "phone": "+49 8671 9980 0", + "email": "rathaus@neuoetting.de", + "postalAddress": "Stadt Neuötting
Ludwigstraße 62
84524 Neuötting", + "icon": "Neuoetting_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from Bürgerservice-Portale der bayerischen Kommunen (https://id.bayernportal.de)." + }, { "shortName": { "": "Rhein-Neckar-Kreis - iKFZ" @@ -1614,8 +1711,8 @@ "longDescription": { "": "Mithilfe der internetbasierten Fahrzeugzulassung können Sie Ihr Fahrzeug ganz einfach anmelden, Adresse ändern und abmelden.
Nähere Details zum Verfahren entnehmen Sie der Startseite des iKFZ-Portals." }, - "address": "https://region-hannover.govconnect.de", - "homepage": "https://region-hannover.govconnect.de", + "address": "https://region-hannover-ikfz4.govconnect.de/i4/ikfz4/?LICENSEIDENTIFIER=hannover_region", + "homepage": "https://www.hannover.de/Leben-in-der-Region-Hannover/Mobilit%C3%A4t/Kraftfahrzeug-Stra%C3%9Fe/KFZ-Zulassung-in-Stadt-und-Region/Kfz-Zulassungen-in-der-Region-Hannover/i-KFZ-Zulassungen,-Wiederzulassungen-und-Au%C3%9Ferbetriebsetzungen-online", "phone": "+49 511 616 17444", "email": "TeamKfz@Region-Hannover.de", "postalAddress": "Region Hannover
Fachbereich Öffentliche Sicherheit
Team Kfz-Zulassungsangelegenheiten
Hildesheimer Straße 20
30169 Hannover", @@ -1736,6 +1833,26 @@ "icon": "Grabow_icon.png", "subjectUrlInfo": "Using service from Serviceportal Mecklenburg-Vorpommern (https://login.mv-serviceportal.de)." }, + { + "shortName": { + "": "ServicePortal der Stadt Mönchengladbach" + }, + "longName": { + "": "ServicePortal der Stadt Mönchengladbach" + }, + "longDescription": { + "": "Im ServicePortal der Stadt Mönchengladbach können eine Vielzahl an digitalen Antragsformularen mit der BundID genutzt werden. Ein schriftlicher Antrag oder ein Behördengang kann damit entfallen. Folgende Leistungen können u. a. online beantragt werden:
  • Meldebescheinigung
  • Melderegisterauskunft
  • Führungszeugnis
  • Bewohnerparkausweis
  • KFZ-Angelegenheiten (z. B. Zulassung, Abmeldung, Wunschkennzeichen)
  • den 'berühmt-berüchtigten' Passierschein A38 (Gamification-Ansatz, bundesweit nutzbar)

Das Angebot wird laufend erweitert." + }, + "address": "https://service.moenchengladbach.de", + "homepage": "https://www.moenchengladbach.de", + "phone": "+49 2161 25 0", + "email": "post@moenchengladbach.de", + "postalAddress": "Stadt Mönchengladbach
41050 Mönchengladbach", + "image": "ServiceportalMoenchengladbach_image.png", + "icon": "ServiceportalMoenchengladbach_icon.png", + "category": "citizen", + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." + }, { "shortName": { "": "Servicekonto Sachsen" @@ -1836,15 +1953,18 @@ "": "MV-Serviceportal" }, "longName": { - "": "Serviceportal Mecklenburg-Vorpommern" + "": "Mecklenburg-Vorpommern-Serviceportal" }, "longDescription": { - "": "Das MV-Serviceportal ist die zentrale Informationsplattform der öffentlichen Verwaltung von Mecklenburg-Vorpommern für Bürgerinnen und Bürger, Unternehmen und Verwaltungen." + "": "MV-Serviceportal: Suchen. Finden. Antrag stellen.
Das MV-SERVICEPORTAL ist die zentrale Informationsplattform der öffentlichen Verwaltung von Mecklenburg-Vorpommern für Bürgerinnen und Bürger, Unternehmen und Verwaltungen. Hier können Sie sich informieren, in Kontakt mit den zuständigen Stellen der Verwaltung treten und viele Behördengänge einfach online erledigen." }, "address": "https://login.mv-serviceportal.de", - "homepage": "https://login.mv-serviceportal.de", - "email": "support@ego-mv.de", - "postalAddress": "Ministerium für Inneres, Bau und Digitalisierung Mecklenburg-Vorpommern
Arsenal am Pfaffenteich
Alexandrinenstraße 1
19053 Schwerin", + "homepage": "https://www.dvz-mv.de", + "phone": "+49 115", + "email": "mv-serviceportal@dvz-mv.de", + "postalAddress": "DVZ Datenverarbeitungszentrum Mecklenburg-Vorpommern GmbH
Lübecker Straße 283
19059 Schwerin", + "image": "MV-ServicePortal_image.png", + "icon": "MV-ServicePortal_icon.png", "category": "citizen", "subjectUrls": [ "https://login.mv-serviceportal.de" @@ -1898,8 +2018,8 @@ "longDescription": { "": "Der Landkreis Ludwigslust-Parchim bietet auf seinem Serviceportal eine Vielzahl von Online-Diensten (inkl. Bezahlvorgang bei gebührenpflichtigen Leistungen) an." }, - "address": "https://service.kreis-lup.de", - "homepage": "https://www.kreis-lup.de", + "address": "https://service.kreis-lup.de/dienstleistungen", + "homepage": "https://service.kreis-lup.de", "phone": "+49 3871 722 0", "email": "info@kreis-lup.de", "postalAddress": "Landkreis Ludwigslust-Parchim
Postfach 16 02 20
19092 Schwerin", @@ -2024,6 +2144,28 @@ "https://service.skidentity.de" ] }, + { + "shortName": { + "": "Girokonto" + }, + "longName": { + "": "Sparkassen-Girokonto" + }, + "longDescription": { + "": "Online-Eröffnung einer Sparkassen-Girokontos bei der Kreissparkasse Esslingen-Nürtingen mit Ihrem elektronischen Personalausweis in weniger als 3 Minuten." + }, + "address": "https://www.ksk-es.de/de/home/privatkunden/girokonto/girokonto-online/online-ausweisfunktion.html", + "homepage": "https://www.ksk-es.de", + "phone": "+49 711 398 5000", + "email": "kundenservice@ksk-es.de", + "postalAddress": "Kreissparkasse Esslingen-Nürtingen
Bahnhofstr. 8
73728 Esslingen", + "image": "KSK-Esslingen-Nuertingen_image.png", + "icon": "KSK-Esslingen-Nuertingen_icon.png", + "category": "finance", + "subjectUrls": [ + "https://www.ksk-es.de" + ] + }, { "shortName": { "": "Stadt Kassel" @@ -2182,7 +2324,7 @@ "": "Die Stadt Remscheid bietet auf ihrem Serviceportal eine Vielzahl von Online-Diensten (inkl. Bezahlvorgang bei gebührenpflichtigen Leistungen) an." }, "address": "https://serviceportal.remscheid.de", - "homepage": "https://www.remscheid.de", + "homepage": "https://serviceportal.remscheid.de", "phone": "+49 2191 16 00", "email": "Serviceportal@remscheid.de", "postalAddress": "Stadt Remscheid
Theodor-Heuss-Platz 1
42853 Remscheid", @@ -2224,6 +2366,21 @@ "postalAddress": "Der Senator für Finanzen
Projektteam Unterhaltsvorschuss
Rudolf-Hilferding-Platz 1
28195 Bremen", "category": "citizen", "icon": "UVO_icon.svg", + "subjectUrlInfo": "Using service from Gemeinsam-Online (https://idp.serviceportal.gemeinsamonline.de)." + }, + { + "shortName": { + "": "Gemeinsam-Online" + }, + "longName": { + "": "Gemeinsam-Online" + }, + "address": "https://serviceportal.gemeinsamonline.de", + "homepage": "https://serviceportal.gemeinsamonline.de", + "longDescription": { + "": " Das Serviceportal Gemeinsam-Online stellt verschiedene digitale Dienste bereit." + }, + "category": "citizen", "subjectUrls": [ "https://idp.serviceportal.gemeinsamonline.de" ] @@ -2483,23 +2640,6 @@ "category": "citizen", "subjectUrlInfo": "Using service from Bürgerservice-Portale der bayerischen Kommunen (https://bayernid.freistaat.bayern)." }, - { - "shortName": { - "": "Servicekonto Niedersachsen" - }, - "longName": { - "": "Servicekonto Niedersachsen" - }, - "address": "https://servicekonto.niedersachsen.de", - "homepage": "https://servicekonto.niedersachsen.de", - "longDescription": { - "": "Das Servicekonto ist Ihr persönlicher Online-Zugang zu den Leistungen der Behörden. Damit können Sie in Zukunft eine Vielzahl von Verwaltungsleistungen von zu Hause digital erledigen. Dies gilt insbesondere für Niedersachsen, das Konto können Sie aber auch deutschlandweit nutzen.

Egal welche Verwaltungsleistung Sie gerade benötigen, Sie werden sich dazu mit Ihrem Servicekonto anmelden und den zugehörigen Antrag rechtssicher bei der Behörde einreichen können. Außerdem werden Ihnen auf Wunsch Informationen und Bescheide zu Ihren Anträgen in Zukunft schnell und digital in Ihr Servicekonto-Postfach zugestellt.

Das Servicekonto ist ein Angebot der niedersächsischen Landesverwaltung an alle Nutzerinnen und Nutzer niedersächsischer Verwaltungsleistungen." - }, - "category": "citizen", - "subjectUrls": [ - "https://idp.servicekonto.niedersachsen.de" - ] - }, { "shortName": { "": "Serviceportal Schaumburg" @@ -2518,7 +2658,27 @@ "icon": "Schaumburg_icon.svg", "image": "Schaumburg_image.svg", "category": "citizen", - "subjectUrlInfo": "Using service from Servicekonto Niedersachsen (https://idp.servicekonto.niedersachsen.de)." + "subjectUrlInfo": "Using service from bundID (https://id.bund.de)." + }, + { + "shortName": { + "": "Stadt Freiburg im Breisgau - Bürgerservice" + }, + "longName": { + "": "Stadt Freiburg im Breisgau - Bürgerservice" + }, + "phone": "+49 761 201 0", + "address": "https://www.freiburg.de/pb/site/Freiburg/node/205252?QUERYSTRING=online%20dienste", + "homepage": "https://www.freiburg.de", + "email": "buergerservice@stadt.freiburg.de", + "longDescription": { + "": "Viele Dienstleistungen können Sie bereits jetzt online erledigen. Über das landesweite Portal Service-bw, über bundesweite Portale oder direkt bei der Stadt Freiburg i. Br.. Bei verschiedenen Dienstleistungen wie beispielsweise der KFZ-Zulassung, Meldebescheinigung, Abmeldung ins Ausland oder Abmeldung zahlen Sie bei einer online-Abwicklung weniger Gebühren als bei einem Besuch vor Ort." + }, + "postalAddress": "Stadt Freiburg im Breisgau
Fehrenbachallee 12
79106 Freiburg", + "icon": "Freiburg_icon.png", + "image": "Freiburg_image.png", + "category": "citizen", + "subjectUrlInfo": "Using service from Bürgerportal Baden-Württemberg (https://eid.service-bw.de)." } ] } diff --git a/resources/updatable-files/supported-readers.json b/resources/updatable-files/supported-readers.json index b0ca340c5..27ac36fe0 100644 --- a/resources/updatable-files/supported-readers.json +++ b/resources/updatable-files/supported-readers.json @@ -142,15 +142,21 @@ "DE": "Windows", "EN": "Windows", "os": "win" - }, + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + }, + { + "Platforms": [ { "DE": "macOS", "EN": "macOS", "os": "mac" } ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -218,7 +224,7 @@ "os": "win" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=Windows&productGroup=77304735&product=77304820&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-windows" }, { "Platforms": [ @@ -226,7 +232,7 @@ "os": "mac" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304820&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-mac" }, { "Platforms": [ @@ -234,7 +240,7 @@ "os": "unknown" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=Linux&productGroup=77304735&product=77304820&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-linux" } ], "Information": [ @@ -244,15 +250,21 @@ "DE": "Windows", "EN": "Windows", "os": "win" - }, + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + }, + { + "Platforms": [ { "DE": "macOS", "EN": "macOS", "os": "mac" } ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -273,15 +285,25 @@ "os": "win" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=Windows&productGroup=77304735&product=77304856&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-windows" }, { "Platforms": [ { - "os": "mac" + "os": "mac", + "max": "13" + } + ], + "URL": "https://www.reiner-sct.com/treiber-mac" + }, + { + "Platforms": [ + { + "os": "mac", + "min": "14" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304856&q=driver#choice5" + "URL": "https://help.reiner-sct.com/de/support/solutions/articles/101000502874" }, { "Platforms": [ @@ -289,22 +311,35 @@ "os": "unknown" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=Linux&productGroup=77304735&product=77304856&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-linux" } ], "Information": [ { "Platforms": [ { - "DE": "macOS", - "EN": "macOS", - "os": "mac" - }, + "DE": "bis Windows 10", + "EN": "up to Windows 10", + "os": "win", + "max": "10.0.19999" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + }, + { + "Platforms": [ { - "DE": "bis Windows 8.1", - "EN": "up to Windows 8.1", + "DE": "ab Windows 11", + "EN": "from Windows 11", "os": "win", - "max": "6.3" + "min": "10.0.20000" + }, + { + "DE": "bis macOS 13", + "EN": "up to macOS 13", + "os": "mac", + "max": "13" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber.", @@ -313,14 +348,14 @@ { "Platforms": [ { - "DE": "ab Windows 10", - "EN": "from Windows 10", - "os": "win", - "min": "10" + "DE": "ab macOS 14", + "EN": "from macOS 14", + "os": "mac", + "min": "14" } ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -331,7 +366,7 @@ "0x0505" ], "Name": "REINER SCT cyberJack wave", - "Pattern": "REINER SCT cyberJack wave( USB)?( \\d{1,1})?$", + "Pattern": "REINER SCT cyberJack wave", "Icon": "img_cyberjack_wave.png", "IconWithNPA": "img_cyberjack_wave_mit_ausweis.png", "Drivers": [ @@ -341,7 +376,7 @@ "os": "win" } ], - "URL": "https://help.reiner-sct.com/de/support/solutions/articles/101000475765" + "URL": "https://www.reiner-sct.com/treiber-windows" }, { "Platforms": [ @@ -349,7 +384,7 @@ "os": "mac" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304828&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-mac" }, { "Platforms": [ @@ -357,7 +392,7 @@ "os": "unknown" } ], - "URL": "https://www.reiner-sct.com/support/support-anfrage/?os=Linux&productGroup=77304735&product=77304828&q=driver#choice5" + "URL": "https://www.reiner-sct.com/treiber-linux" } ], "Information": [ @@ -386,7 +421,7 @@ "0x301D" ], "Name": "KOBIL IDToken", - "Pattern": "^KOBIL (Systems )?IDToken( \\d{1,1})?$", + "Pattern": "^KOBIL (Systems )?IDToken", "Icon": "img_KOBIL_ID_Token.png", "IconWithNPA": "img_KOBIL_ID_Token_mit_ausweis.png", "Drivers": [ @@ -397,11 +432,7 @@ }, { "os": "mac", - "max": "10.14" - }, - { - "os": "mac", - "min": "11" + "max": "13" }, { "os": "unknown" @@ -425,20 +456,26 @@ { "Platforms": [ { - "DE": "bis macOS 10.14 (Mojave)", - "EN": "up to macOS 10.14 (Mojave)", - "os": "mac", - "max": "10.14" - }, - { - "DE": "ab macOS 11 (Big Sur)", - "EN": "from macOS 11 (Big Sur)", + "DE": "bis macOS 13", + "EN": "up to macOS 13", "os": "mac", - "min": "11" + "max": "13" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber.", "EN": "The card reader is compatible with the installed system driver." + }, + { + "Platforms": [ + { + "DE": "ab macOS 14", + "EN": "from macOS 14", + "os": "mac", + "min": "14" + } + ], + "DE": "Der Kartenleser wird nicht mehr unterstützt, leider bietet der Hersteller keine aktuellen Treiber an.", + "EN": "The card reader is no longer supported, unfortunately the manufacturer does not offer up-to-date drivers." } ], "Internal information": "Der Hersteller stellt keinen Treiber mehr zur Verfügung." @@ -447,7 +484,8 @@ "VendorId": "0x04E6", "ProductId": "0x512B", "ProductIds": [ - "0x512B" + "0x512B", + "0x512C" ], "Name": "Identiv SDI011 Dual Interface Smart Card Reader", "Pattern": "^(SCM Microsystems Inc. )?SDI011G? ((Contactless Reader( 0)?)|((USB Smart Card|Contactless) Reader\\([12]\\)))$", @@ -470,17 +508,6 @@ } ], "Information": [ - { - "Platforms": [ - { - "DE": "macOS", - "EN": "macOS", - "os": "mac" - } - ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." - }, { "Platforms": [ { @@ -504,6 +531,17 @@ ], "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Bitte beachten Sie nach der Treiberinstallation die Windows-Informationen zur Einstellung der Gerätesicherheit.", "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. After the driver installation, please observe the Windows information notification regarding your device security settings." + }, + { + "Platforms": [ + { + "DE": "macOS", + "EN": "macOS", + "os": "mac" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -545,8 +583,8 @@ { "Platforms": [ { - "DE": "MacOS", - "EN": "MacOS", + "DE": "macOS", + "EN": "macOS", "os": "mac" } ], @@ -563,7 +601,7 @@ "0x5790" ], "Name": "Identiv 3700 F", - "Pattern": "^Identiv (uTrust|cloud|CLOUD) 3700 F (Contactless|CL) Reader( 0)?$", + "Pattern": "^Identiv[e]? (uTrust|cloud|CLOUD) 3700 F (Contactless|CL) Reader( 0)?$", "Icon": "img_Identive_XXXX_F.png", "IconWithNPA": "img_Identive_XXXX_F_mit_ausweis.png", "Drivers": [ @@ -579,7 +617,7 @@ "os": "unknown" } ], - "URL": "https://support.identiv.com/3700f/" + "URL": "https://support.identiv.com/3700f" } ], "Information": [ @@ -589,15 +627,34 @@ "DE": "Windows", "EN": "Windows", "os": "win" - }, + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website." + }, + { + "Platforms": [ { - "DE": "macOS", - "EN": "macOS", - "os": "mac" + "DE": "bis macOS 13", + "EN": "up to macOS 13", + "os": "mac", + "max": "13" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden.", "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website." + }, + { + "Platforms": [ + { + "DE": "ab macOS 14", + "EN": "from macOS 14", + "os": "mac", + "min": "14" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -746,7 +803,7 @@ "os": "mac" } ], - "DE": "Der Kartenleser wird nicht mehr unterstützt, leider ist der vom Hersteller angebotene Treiber veraltert und funktioniert nicht.", + "DE": "Der Kartenleser wird nicht mehr unterstützt, leider ist der vom Hersteller angebotene Treiber veraltet und funktioniert nicht.", "EN": "The card reader is no longer supported, the driver offered by the manufacturer is unfortunately outdated and does not work." } ] @@ -873,7 +930,7 @@ "os": "mac" } ], - "URL": "https://www.acs.com.hk/en/driver/151/acr1281u-npa-contactless-reader/" + "URL": "https://www.acs.com.hk/en/driver/151/acr1281u-npa-contactless-reader" } ], "Information": [ @@ -885,19 +942,93 @@ "os": "win" } ], - "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Falls Sie jedoch den Treiber von der Webseite des Herstellers installieren möchten, ist anschließend ein Neustart erforderlich.", - "EN": "The card reader operates with the driver automatically installed by the system. In case you prefer to install the driver from the manufacturer's webseite, a reboot is required." + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website." }, { "Platforms": [ { - "DE": "macOS", - "EN": "macOS", + "DE": "bis macOS 13", + "EN": "up to macOS 13", + "os": "mac", + "max": "13" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." + }, + { + "Platforms": [ + { + "DE": "ab macOS 14", + "EN": "from macOS 14", + "os": "mac", + "min": "14" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden. Nach der Installation ist ein Neustart erforderlich.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website. A reboot is required after the installation of the driver." + } + ] + }, + { + "VendorId": "0x072F", + "ProductId": "0x2224", + "ProductIds": [ + "0x2224" + ], + "Name": "ACS ACR1281U-C1", + "Pattern": "ACS ACR1281 1S Dual Reader (PICC 0|\\(1\\))", + "Icon": "img_ACS_ACR1281U.png", + "IconWithNPA": "img_ACS_ACR1281U_mit_ausweis.png", + "Drivers": [ + { + "Platforms": [ + { + "os": "win" + }, + { "os": "mac" } ], + "URL": "https://www.acs.com.hk/en/driver/159/acr1281u-c1-dualboost-ii-usb-dual-interface-reader" + } + ], + "Information": [ + { + "Platforms": [ + { + "DE": "Windows", + "EN": "Windows", + "os": "win" + } + ], "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + }, + { + "Platforms": [ + { + "DE": "bis macOS 12", + "EN": "up to macOS 12", + "os": "mac", + "max": "12" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." + }, + { + "Platforms": [ + { + "DE": "ab macOS 13", + "EN": "from macOS 13", + "os": "mac", + "min": "13" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden. Nach der Installation ist ein Neustart erforderlich.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website. A reboot is required after the installation of the driver." } ] }, @@ -1011,16 +1142,16 @@ }, { "Platforms": [ - { - "DE": "macOS", - "EN": "macOS", - "os": "mac" - }, { "DE": "ab Windows 11", "EN": "from Windows 11", "os": "win", "min": "10.0.20000" + }, + { + "DE": "macOS", + "EN": "macOS", + "os": "mac" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber.", @@ -1254,7 +1385,7 @@ "os": "win" } ], - "URL": "https://www.feig.de/login/" + "URL": "https://www.feig.de/login" } ], "Information": [ @@ -1296,31 +1427,32 @@ { "Platforms": [ { - "os": "win" - }, - { - "os": "mac" + "os": "win", + "max": "10.0.19999" }, { "os": "unknown" } ], "URL": "https://supportportal.gemalto.com/csm/?id=kb_article_view&sysparm_article=KB0016422" + }, + { + "Platforms": [ + { + "os": "mac" + } + ], + "URL": "https://supportportal.gemalto.com/csm?sys_kb_id=fd704ab21bd53d1019913035464bcb30&id=kb_article_view&sysparm_rank=1&sysparm_tsqueryId=6590372b1bed3d1019913035464bcb0e&sysparm_article=KB0027738" } ], "Information": [ { "Platforms": [ { - "DE": "Windows", - "EN": "Windows", - "os": "win" - }, - { - "DE": "bis macOS 10.15 (Catalina)", - "EN": "up to macOS 10.15 (Catalina)", - "os": "mac", - "max": "10.15" + "DE": "bis Windows 10", + "EN": "up to Windows 10", + "os": "win", + "max": "10.0.19999" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Es ist kein Treiber vom Hersteller vorhanden.", @@ -1329,14 +1461,38 @@ { "Platforms": [ { - "DE": "ab macOS 11 (Big Sur)", - "EN": "from macOS 11 (Big Sur)", + "DE": "ab Windows 11", + "EN": "from Windows 11", + "os": "win", + "min": "10.0.20000" + } + ], + "DE": "Der Kartenleser wird nicht mehr unterstützt, leider bietet der Hersteller keine aktuellen Treiber an.", + "EN": "The card reader is no longer supported, unfortunately the manufacturer does not offer up-to-date drivers." + }, + { + "Platforms": [ + { + "DE": "bis macOS 12", + "EN": "up to macOS 12", + "os": "mac", + "max": "12" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich. Trotz des Herstellertreibers ist es wichtig zu beachten, dass der Kartenleser nur funktioniert, solang er vor dem Start des Computers angeschlossen ist und nicht vom Gerät entfernt wird. Sollte er entfernt werden, müssen Sie Ihr Gerät neu starten.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver. Despite the manufacturer's driver, it is important to note that the card reader only works as long as it is connected before starting the computer and is not removed from the device. If it is removed, you will need to restart your device." + }, + { + "Platforms": [ + { + "DE": "ab macOS 13", + "EN": "from macOS 13", "os": "mac", - "min": "11" + "min": "13" } ], - "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber, ein Neustart ist erforderlich. Es ist kein Treiber vom Hersteller vorhanden.", - "EN": "The card reader operates with the driver automatically installed by the system, a reboot is required. There is no driver from the manufacturer." + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden. Nach der Installation ist ein Neustart erforderlich.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website. A reboot is required after the installation of the driver." } ] }, @@ -1355,25 +1511,20 @@ "Platforms": [ { "os": "win" - } - ], - "URL": "https://supportportal.gemalto.com/csm/?id=kb_article_view&sysparm_article=KB0016422" - }, - { - "Platforms": [ + }, { - "os": "mac" + "os": "unknown" } ], - "URL": "https://supportportal.gemalto.com/csm/?id=kb_article_view&sysparm_article=KB0016424" + "URL": "https://supportportal.gemalto.com/csm" }, { "Platforms": [ { - "os": "unknown" + "os": "mac" } ], - "URL": "https://supportportal.gemalto.com/csm/?id=kb_article_view&sysparm_article=KB0016423" + "URL": "https://supportportal.gemalto.com/csm?sys_kb_id=fd704ab21bd53d1019913035464bcb30&id=kb_article_view&sysparm_rank=1&sysparm_tsqueryId=6590372b1bed3d1019913035464bcb0e&sysparm_article=KB0027738" } ], "Information": [ @@ -1383,12 +1534,6 @@ "DE": "Windows", "EN": "Windows", "os": "win" - }, - { - "DE": "bis macOS 10.15 (Catalina)", - "EN": "up to macOS 10.15 (Catalina)", - "os": "mac", - "max": "10.15" } ], "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Es ist kein Treiber vom Hersteller vorhanden.", @@ -1397,14 +1542,39 @@ { "Platforms": [ { - "DE": "ab macOS 11 (Big Sur)", - "EN": "from macOS 11 (Big Sur)", + "DE": "bis macOS 12", + "EN": "up to macOS 12", + "os": "mac", + "max": "12" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." + }, + { + "Platforms": [ + { + "DE": "macOS 13", + "EN": "macOS 13", + "os": "mac", + "min": "13", + "max": "13" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden. Nach der Installation ist ein Neustart erforderlich.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website. A reboot is required after the installation of the driver." + }, + { + "Platforms": [ + { + "DE": "ab macOS 14", + "EN": "from macOS 14", "os": "mac", - "min": "11" + "min": "14" } ], - "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber, ein Neustart ist erforderlich. Es ist kein Treiber vom Hersteller vorhanden.", - "EN": "The card reader operates with the driver automatically installed by the system, a reboot is required. There is no driver from the manufacturer." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -1431,25 +1601,44 @@ "os": "unknown" } ], - "URL": "https://cherry.de/download/de/download.php?product_id=307" + "URL": "https://cherry.de/service/downloads#21865" } ], "Information": [ { "Platforms": [ { - "DE": "Windows", - "EN": "Windows", - "os": "win" - }, + "DE": "bis Windows 10", + "EN": "up to Windows 10", + "os": "win", + "max": "10.0.19999" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + }, + { + "Platforms": [ + { + "DE": "ab Windows 11", + "EN": "from Windows 11", + "os": "win", + "min": "10.0.20000" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website." + }, + { + "Platforms": [ { "DE": "macOS", "EN": "macOS", "os": "mac" } ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." } ] }, @@ -1460,7 +1649,7 @@ "0x0092" ], "Name": "Cherry TC-1300", - "Pattern": "(Cherry TC 1300|Cherry Smartcard Terminal TC 13xx-CL 0|Cherry SC Reader \\(046A:0092\\))", + "Pattern": "(Cherry Smartcard Terminal TC 13xx-CL 0|Cherry SC Reader \\(046A:0092\\))", "Icon": "img_Cherry_TC_1300.png", "IconWithNPA": "img_Cherry_TC_1300_mit_ausweis.png", "Drivers": [ @@ -1476,16 +1665,17 @@ "os": "unknown" } ], - "URL": "https://cherry.de/download/de/download.php?product_id=306" + "URL": "https://www.cherry.de/service/downloads#21864" } ], "Information": [ { "Platforms": [ { - "DE": "Windows", - "EN": "Windows", - "os": "win" + "DE": "bis Windows 10", + "EN": "up to Windows 10", + "os": "win", + "max": "10.0.19999" }, { "DE": "macOS", @@ -1493,8 +1683,20 @@ "os": "mac" } ], - "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", - "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite. Nach der Installation ist ein Neustart erforderlich.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system. A reboot is required after the installation of the driver." + }, + { + "Platforms": [ + { + "DE": "ab Windows 11", + "EN": "from Windows 11", + "os": "win", + "min": "10.0.20000" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website." } ] }, @@ -1514,28 +1716,38 @@ { "os": "win" }, - { - "os": "mac" - }, { "os": "unknown" } ], - "URL": "https://cherry.de/download/de/download.php?product_id=170" + "URL": "https://www.cherry.de/service/downloads#21987" } ], "Information": [ { "Platforms": [ { - "DE": "Windows", - "EN": "Windows", - "os": "win" + "DE": "bis Windows 10", + "EN": "up to Windows 10", + "os": "win", + "max": "10.0.19999" } ], "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." }, + { + "Platforms": [ + { + "DE": "ab Windows 11", + "EN": "from Windows 11", + "os": "win", + "min": "10.0.20000" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber. Alternativ können Sie den Treiber von der Webseite des Herstellers verwenden. Bitte beachten Sie nach Anschließen des Kartenlesers die Windows-Informationen zur Einstellung der Gerätesicherheit.", + "EN": "The card reader operates with the driver automatically installed by the system. Alternatively you have the option to install a driver from the manufacturer's website. After connecting the card reader, please observe the Windows information notification regarding your device security settings." + }, { "Platforms": [ { @@ -1544,8 +1756,8 @@ "os": "mac" } ], - "DE": "Es ist kein Treiber vom Hersteller vorhanden.", - "EN": "There is no driver from the manufacturer." + "DE": "Der Kartenleser wird nicht mehr unterstützt, leider bietet der Hersteller keine aktuellen Treiber an.", + "EN": "The card reader is no longer supported, unfortunately the manufacturer does not offer up-to-date drivers." } ], "Internal information": "Unter Windows funktioniert nur NFC A. Reader wird nicht als unterstützt markiert, da er nicht zertifiziert ist." @@ -1639,6 +1851,64 @@ "EN": "The card reader operates with the driver automatically installed by the system. There is no driver from the manufacturer." } ] + }, + { + "VendorId": "0x072F", + "ProductId": "0x2301", + "ProductIds": [ + "0x2301" + ], + "Name": "ACS ACR1581U-C1", + "Pattern": "ACS ACR1581 1S Dual Reader (PICC|\\(1\\))( 0)?", + "Icon": "img_ACS_ACR1581U-C1.png", + "IconWithNPA": "img_ACS_ACR1581U-C1_mit_ausweis.png", + "Drivers": [ + { + "Platforms": [ + { + "os": "win" + }, + { + "os": "mac" + }, + { + "os": "unknown" + } + ], + "URL": "https://www.acs.com.hk/en/products/583/acr1581u-dualboost-iii-usb-dual-interface-reader" + } + ], + "Information": [ + { + "Platforms": [ + { + "DE": "Windows", + "EN": "Windows", + "os": "win" + }, + { + "DE": "ab macOS 14", + "EN": "from macOS 14", + "os": "mac", + "min": "14" + } + ], + "DE": "Der Kartenleser funktioniert mit dem systemseitig installierten Treiber.", + "EN": "The card reader is compatible with the installed system driver." + }, + { + "Platforms": [ + { + "DE": "bis macOS 13", + "EN": "up to macOS 13", + "os": "mac", + "max": "13" + } + ], + "DE": "Es ist notwendig, die Treiber vom Hersteller zu installieren. Dazu folgen Sie bitte dem jeweiligen Link für Ihr Betriebssystem zur Herstellerseite.", + "EN": "It is necessary to install the drivers from the manufacturer. Please follow the relevant link for your operating system." + } + ] } ] } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7230d6507..1099af403 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,12 +24,10 @@ add_subdirectory(workflows) add_subdirectory(ui) add_subdirectory(core) add_subdirectory(init) -add_subdirectory(whitelist_client) if(IOS) if(NOT INTEGRATED_SDK) - list(APPEND IOS_RESOURCES ${RESOURCES_DIR}/qml) list(APPEND IOS_RESOURCES ${RESOURCES_DIR}/packaging/ios/de.lproj) list(APPEND IOS_RESOURCES ${RESOURCES_DIR}/packaging/ios/launchscreen.storyboard) @@ -54,8 +52,7 @@ elseif(MAC) set(MACOS_APPICON_PATH "") endif() - list(APPEND MAC_RESOURCES ${RESOURCES_DIR}/images/macos/${MACOS_APPICON_PATH}AusweisApp.icns) - list(APPEND MAC_RESOURCES ${PACKAGING_DIR}/macos/container-migration.plist) + list(APPEND MAC_RESOURCES "${RESOURCES_DIR}/images/macos/${MACOS_APPICON_PATH}${PROJECT_NAME}.icns") list(APPEND MAC_RESOURCES ${RCC}) set_source_files_properties(${RCC} PROPERTIES GENERATED TRUE) endif() @@ -63,10 +60,6 @@ endif() if(APPLE) set(CMAKE_XCODE_GENERATE_SCHEME ON) set(CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER ON) - - if(MAC AND DEFINED CMAKE_PREFIX_PATH) - set(CMAKE_XCODE_SCHEME_ENVIRONMENT "DYLD_LIBRARY_PATH=${CMAKE_PREFIX_PATH}/lib;DYLD_FRAMEWORK_PATH=${CMAKE_PREFIX_PATH}/lib") - endif() endif() set(MAIN_FILE main.cpp) @@ -77,7 +70,15 @@ if(IOS) add_executable(AusweisAppBinary MACOSX_BUNDLE ${MAIN_FILE} ${IOS_RESOURCES}) endif() elseif(ANDROID OR (INTEGRATED_SDK AND NOT CONTAINER_SDK)) - add_library(AusweisAppBinary SHARED ${MAIN_FILE}) + if(INTEGRATED_SDK) + add_library(AusweisAppBinary SHARED ${MAIN_FILE}) + else() + qt_add_executable(AusweisAppBinary ${MAIN_FILE}) + set_target_properties(AusweisAppBinary PROPERTIES QT_ANDROID_PACKAGE_SOURCE_DIR "${ANDROID_PACKAGE_SRC_DIR}") + set_target_properties(AusweisAppBinary PROPERTIES QT_ANDROID_MIN_SDK_VERSION ${CMAKE_SYSTEM_VERSION}) + set_target_properties(AusweisAppBinary PROPERTIES QT_ANDROID_TARGET_SDK_VERSION ${ANDROID_TARGET_SDK_VERSION}) + set_target_properties(AusweisAppBinary PROPERTIES QT_QML_ROOT_PATH $/${CMAKE_SYSTEM_NAME}) + endif() elseif(MAC) add_executable(AusweisAppBinary MACOSX_BUNDLE ${MAIN_FILE} ${MAC_RESOURCES}) else() @@ -89,7 +90,7 @@ if(TARGET AusweisAppRcc) endif() target_link_libraries(AusweisAppBinary PRIVATE AusweisAppInit) -if(ANDROID) +if(ANDROID AND INTEGRATED_SDK) set_target_properties(AusweisAppBinary PROPERTIES OUTPUT_NAME "${PROJECT_NAME}_${CMAKE_ANDROID_ARCH_ABI}") elseif(IOS AND INTEGRATED_SDK) set_target_properties(AusweisAppBinary PROPERTIES OUTPUT_NAME "${PROJECT_NAME}2") @@ -106,7 +107,6 @@ ADD_SHADERS_TO_TARGET(AusweisAppBinary) if(APPLE) set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}) set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION}) - set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION}) set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}) set(MACOSX_BUNDLE_GUI_IDENTIFIER "${BUNDLE_IDENTIFIER}") set(MACOSX_BUNDLE_COPYRIGHT "${COPYRIGHT_TEXT}") @@ -148,7 +148,6 @@ if(IOS) if(TARGET ${Qt}::Qml) target_link_libraries(AusweisAppBinary PRIVATE ${Qt}::Gui ${Qt}::Svg ${Qt}::Qml ${Qt}::Quick ${Qt}::QuickControls2 ${Qt}::QuickTemplates2) target_link_libraries(AusweisAppBinary PRIVATE -lqsvg${qt_suffix} -lqjpeg${qt_suffix}) - target_link_libraries(AusweisAppBinary PRIVATE AusweisAppQmlPlugins) endif() set_target_properties(AusweisAppBinary PROPERTIES RESOURCE "${IOS_RESOURCES}") @@ -194,6 +193,17 @@ if(MAC) add_executable(${AUTOSTART_HELPER_FULL_NAME} MACOSX_BUNDLE ${AUTOSTART_HELPER_SOURCES}) target_link_libraries(${AUTOSTART_HELPER_FULL_NAME} ${OSX_APPKIT}) set_target_properties(${AUTOSTART_HELPER_FULL_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PACKAGING_DIR}/macos/autostart_helper/Info.plist.in) + + if(USE_DISTRIBUTION_PROFILE) + configure_file(${PACKAGING_DIR}/macos/entitlements.distribution.plist.in ${CMAKE_BINARY_DIR}/entitlements.plist @ONLY) + set_target_properties(AusweisAppBinary PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_BINARY_DIR}/entitlements.plist") + + set_target_properties(AusweisAppBinary PROPERTIES XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "G7EQCJU4BR") + set_target_properties(AusweisAppBinary PROPERTIES XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "macOS Release (Distribution)") + set_target_properties(AusweisAppBinary PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "3rd Party Mac Developer Application: Governikus GmbH & Co. KG (G7EQCJU4BR)") + else() + configure_file(${PACKAGING_DIR}/macos/entitlements.development.plist ${CMAKE_BINARY_DIR}/entitlements.plist COPYONLY) + endif() endif() if(WIN32) diff --git a/src/android/AusweisApp2LocalIfdService.java b/src/android/AusweisApp2LocalIfdService.java index 9243f22ae..5ddf50823 100644 --- a/src/android/AusweisApp2LocalIfdService.java +++ b/src/android/AusweisApp2LocalIfdService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; @@ -24,7 +24,7 @@ public final class AusweisApp2LocalIfdService extends QtService private final IBinder mBinder = new AusweisApp2LocalIfdServiceBinder(); - // Native method provided by UIPlugInLocalIfd + // Native method provided by UiPluginLocalIfd public static native boolean notifyStartWorkflow(String pPsk); public static native void notifyAbortWorkflow(); public static native boolean verifyServiceToken(String token); diff --git a/src/android/AusweisApp2LocalIfdServiceConnection.java b/src/android/AusweisApp2LocalIfdServiceConnection.java index d9ff76caf..5c6c7b4a7 100644 --- a/src/android/AusweisApp2LocalIfdServiceConnection.java +++ b/src/android/AusweisApp2LocalIfdServiceConnection.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/android/AusweisApp2Service.java b/src/android/AusweisApp2Service.java index 122b6a95f..09f4ec82a 100644 --- a/src/android/AusweisApp2Service.java +++ b/src/android/AusweisApp2Service.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/android/BootstrapHelper.java b/src/android/BootstrapHelper.java index 0b1f64580..8d11c8ec0 100644 --- a/src/android/BootstrapHelper.java +++ b/src/android/BootstrapHelper.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/android/LogHandler.java b/src/android/LogHandler.java index d28ee2da8..c63cc1149 100644 --- a/src/android/LogHandler.java +++ b/src/android/LogHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/android/MainActivity.java b/src/android/MainActivity.java index 8091bfff3..502902a23 100644 --- a/src/android/MainActivity.java +++ b/src/android/MainActivity.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; @@ -9,12 +9,10 @@ import java.util.Locale; import android.accessibilityservice.AccessibilityServiceInfo; -import android.annotation.SuppressLint; -import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Color; import android.net.Uri; @@ -30,7 +28,6 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; -import org.qtproject.qt.android.QtActivityDelegate; import org.qtproject.qt.android.QtNative; import org.qtproject.qt.android.bindings.QtActivity; @@ -43,59 +40,13 @@ public class MainActivity extends QtActivity private final MarginLayoutParams windowInsets = new MarginLayoutParams(0, 0); - private NfcForegroundDispatcher mNfcForegroundDispatcher; private NfcReaderMode mNfcReaderMode; private boolean mIsResumed; - // Native methods provided by UIPlugInQml + // Native methods provided by UiPluginQml public static native void notifySafeAreaMarginsChanged(); public static native void notifyConfigurationChanged(); - private class NfcForegroundDispatcher - { - private final IntentFilter[] mFilters; - private final String[][] mTechLists; - private final PendingIntent mPendingIntent; - - @SuppressLint("UnspecifiedImmutableFlag") - NfcForegroundDispatcher() - { - mFilters = new IntentFilter[] { - new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED) - }; - mTechLists = new String[][] { - new String[] { - IsoDep.class.getName() - } - }; - - mPendingIntent = PendingIntent.getActivity(MainActivity.this, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE); - } - - - void enable() - { - NfcAdapter adapter = NfcAdapter.getDefaultAdapter(MainActivity.this); - if (adapter != null) - { - adapter.enableForegroundDispatch(MainActivity.this, mPendingIntent, mFilters, mTechLists); - } - } - - - void disable() - { - NfcAdapter adapter = NfcAdapter.getDefaultAdapter(MainActivity.this); - if (adapter != null) - { - adapter.disableForegroundDispatch(MainActivity.this); - } - } - - - } - - private class NfcReaderMode { private final int mFlags; @@ -173,15 +124,6 @@ public static String fetchStoredReferrer() } - public MainActivity() - { - QT_ANDROID_THEMES = new String[] { - "AppTheme" - }; - QT_ANDROID_DEFAULT_THEME = "AppTheme"; - } - - public static boolean isStartedByAuth() { if (cIntent == null || cIntent.getData() == null) @@ -215,7 +157,6 @@ public void onCreate(Bundle savedInstanceState) cIntent = getIntent(); - mNfcForegroundDispatcher = new NfcForegroundDispatcher(); mNfcReaderMode = new NfcReaderMode(); // Handle systemWindowInsets @@ -233,10 +174,6 @@ public void onCreate(Bundle savedInstanceState) return insets; }); - // Set Qt flags first so we can overwrite with our own values. - setSystemUiVisibility(QtActivityDelegate.SYSTEM_UI_VISIBILITY_TRANSLUCENT); - window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - // Make statusbar and navigation bar transparent if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) // API 29, Android 10 { @@ -271,7 +208,6 @@ public void onResume() super.onResume(); mIsResumed = true; - mNfcForegroundDispatcher.enable(); setReaderModeNative(true); } @@ -280,7 +216,6 @@ public void onResume() public void onPause() { setReaderModeNative(false); - mNfcForegroundDispatcher.disable(); mIsResumed = false; super.onPause(); @@ -295,7 +230,7 @@ protected void onDestroy() } - // used by NfcReaderManagerPlugIn + // used by NfcReaderManagerPlugin public void setReaderMode(boolean pEnabled) { if (pEnabled) @@ -309,7 +244,7 @@ public void setReaderMode(boolean pEnabled) } - // used by NfcReaderManagerPlugIn + // used by NfcReaderManagerPlugin public void resetNfcReaderMode() { if (mIsResumed && mNfcReaderMode.isEnabled()) @@ -334,15 +269,6 @@ public void keepScreenOn(boolean pActivate) } - // required by UIPlugInQml::getPlatformSelectors() - public boolean isTablet() - { - final Context context = getBaseContext(); - // https://developer.android.com/training/multiscreen/screensizes.html#TaskUseSWQuali - return context.getResources().getConfiguration().smallestScreenWidthDp >= 600; - } - - public boolean isScreenReaderRunning() { AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE); @@ -377,6 +303,13 @@ public boolean openUrl(String pUrl, String pReferrer) } + public boolean isChromeOS() + { + PackageManager packageManager = getPackageManager(); + return packageManager.hasSystemFeature("org.chromium.arc") || packageManager.hasSystemFeature("org.chromium.arc.device_management"); + } + + @Override public void onConfigurationChanged(Configuration newConfig) { diff --git a/src/android/UpdateReceiver.java b/src/android/UpdateReceiver.java index cc7868077..7d1f15681 100644 --- a/src/android/UpdateReceiver.java +++ b/src/android/UpdateReceiver.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/autostart_helper/main.mm b/src/autostart_helper/main.mm index d03ab13af..234d5d273 100644 --- a/src/autostart_helper/main.mm +++ b/src/autostart_helper/main.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include diff --git a/src/card/CMakeLists.txt b/src/card/CMakeLists.txt index 671b632ce..4ee5e9684 100644 --- a/src/card/CMakeLists.txt +++ b/src/card/CMakeLists.txt @@ -3,7 +3,7 @@ # (APDU). # # It provides an interface that can be implemented by plugins like -# PCSC or Android-NFC called ReaderManagerPlugIn. +# PCSC or Android-NFC called ReaderManagerPlugin. # Also it provides a ReaderManager that can be used as a generic # control interface. It handles access and commands to specific # reader, cards and commands to the identity card. diff --git a/src/card/base/CMakeLists.txt b/src/card/base/CMakeLists.txt index 1e2f16743..608bdb477 100644 --- a/src/card/base/CMakeLists.txt +++ b/src/card/base/CMakeLists.txt @@ -9,3 +9,5 @@ endif() if(TARGET ${Qt}::Test) target_link_libraries(AusweisAppCard PRIVATE debug ${Qt}::Test) endif() + +qt_extract_metatypes(AusweisAppCard) # QTBUG-123574 diff --git a/src/card/base/Card.cpp b/src/card/base/Card.cpp index f3682c1e7..92cfd7fb5 100644 --- a/src/card/base/Card.cpp +++ b/src/card/base/Card.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Card.h" @@ -25,13 +25,18 @@ void Card::setProgressMessage(const QString& pMessage, int pProgress) } -EstablishPaceChannelOutput Card::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds) +void Card::setErrorMessage(const QString& pMessage) +{ + Q_UNUSED(pMessage) +} + + +EstablishPaceChannelOutput Card::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) { Q_UNUSED(pPasswordId) Q_UNUSED(pPreferredPinLength) Q_UNUSED(pChat) Q_UNUSED(pCertificateDescription) - Q_UNUSED(pTimeoutSeconds) qCWarning(card) << "Establishment of PACE channel not supported"; return EstablishPaceChannelOutput(CardReturnCode::COMMAND_FAILED); } @@ -74,6 +79,14 @@ QString Card::generateProgressMessage(const QString& pMessage, int pProgress) } +QString Card::generateErrorMessage(const QString& pMessage) +{ + return Env::getSingleton()->isUsedAsSDK() && !pMessage.isNull() + ? Env::getSingleton()->getMessages().getSessionFailed() + : pMessage; +} + + EstablishPaceChannelOutput Card::prepareIdentification(const QByteArray& pChat) { Q_UNUSED(pChat) diff --git a/src/card/base/Card.h b/src/card/base/Card.h index cd65bdf49..37d45a439 100644 --- a/src/card/base/Card.h +++ b/src/card/base/Card.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -48,6 +48,8 @@ class Card Q_OBJECT public: + static constexpr int DEFAULT_PINPAD_TIMEOUT = 90; + Card(); ~Card() override = default; @@ -71,6 +73,7 @@ class Card * where interacting with a card leads to a dialog where the message needs to be updated. */ virtual void setProgressMessage(const QString& pMessage, int pProgress = -1); + virtual void setErrorMessage(const QString& pMessage); /*! * Performs a transmit to the smart card. @@ -82,7 +85,7 @@ class Card /*! * Establishes a PACE channel, i.e. the corresponding reader is no basic reader. */ - virtual EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds = 60); + virtual EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription); /*! * Destroys an existing PACE channel, i.e. the corresponding reader is no basic reader. @@ -98,6 +101,7 @@ class Card * Combines the message and progressvalue depending on the environment. */ static QString generateProgressMessage(const QString& pMessage, int pProgress = -1); + static QString generateErrorMessage(const QString& pMessage); virtual EstablishPaceChannelOutput prepareIdentification(const QByteArray& pChat); diff --git a/src/card/base/CardConnection.cpp b/src/card/base/CardConnection.cpp index 983bda2f7..3ced3fa7b 100644 --- a/src/card/base/CardConnection.cpp +++ b/src/card/base/CardConnection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardConnection.h" @@ -64,12 +64,26 @@ void CardConnection::setProgressMessage(const QString& pMessage, int pProgress) } +void CardConnection::setErrorMessage(const QString& pMessage) +{ + QMetaObject::invokeMethod(mCardConnectionWorker.data(), [this, pMessage] { + mCardConnectionWorker->setErrorMessage(pMessage); + }, Qt::BlockingQueuedConnection); +} + + UpdateRetryCounterCommand* CardConnection::createUpdateRetryCounterCommand() { return new UpdateRetryCounterCommand(mCardConnectionWorker); } +ResetRetryCounterCommand* CardConnection::createResetRetryCounterCommand() +{ + return new ResetRetryCounterCommand(mCardConnectionWorker); +} + + EstablishPaceChannelCommand* CardConnection::createEstablishPaceChannelCommand(PacePasswordId pPacePasswordId, const QByteArray& pPacePassword, const QByteArray& pEffectiveChat, const QByteArray& pCertificateDescription) { return new EstablishPaceChannelCommand(mCardConnectionWorker, pPacePasswordId, pPacePassword, pEffectiveChat, pCertificateDescription); @@ -82,9 +96,9 @@ SetEidPinCommand* CardConnection::createSetEidPinCommand(const QByteArray& pNewP } -DestroyPaceChannelCommand* CardConnection::createDestroyPaceChannelCommand() +DestroyPaceChannelCommand* CardConnection::createDestroyPaceChannelCommand(const QString& pSlotHandle) { - return new DestroyPaceChannelCommand(mCardConnectionWorker); + return new DestroyPaceChannelCommand(mCardConnectionWorker, pSlotHandle); } @@ -111,7 +125,7 @@ void CardConnection::onReaderInfoChanged(const ReaderInfo& pReaderInfo) } -TransmitCommand* CardConnection::createTransmitCommand(const QVector& pInputApduInfos, const QString& pSlotHandle) +TransmitCommand* CardConnection::createTransmitCommand(const QList& pInputApduInfos, const QString& pSlotHandle) { return new TransmitCommand(mCardConnectionWorker, pInputApduInfos, pSlotHandle); } diff --git a/src/card/base/CardConnection.h b/src/card/base/CardConnection.h index 4f7f4c632..1d81f4aa6 100644 --- a/src/card/base/CardConnection.h +++ b/src/card/base/CardConnection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,6 +21,7 @@ #include "command/DidAuthenticateEAC1Command.h" #include "command/DidAuthenticateEAC2Command.h" +#include "command/ResetRetryCounterCommand.h" #include "command/TransmitCommand.h" #include "command/UpdateRetryCounterCommand.h" @@ -51,12 +52,13 @@ class CardConnection bool mPaceCanSuccessful; bool mPacePinSuccessful; - TransmitCommand* createTransmitCommand(const QVector& pInputApduInfos, const QString& pSlotHandle); + TransmitCommand* createTransmitCommand(const QList& pInputApduInfos, const QString& pSlotHandle); UpdateRetryCounterCommand* createUpdateRetryCounterCommand(); + ResetRetryCounterCommand* createResetRetryCounterCommand(); EstablishPaceChannelCommand* createEstablishPaceChannelCommand(PacePasswordId pPacePasswordId, const QByteArray& pPacePassword, const QByteArray& pEffectiveChat, const QByteArray& pCertificateDescription); SetEidPinCommand* createSetEidPinCommand(const QByteArray& pNewPin, quint8 pTimeoutSeconds); - DestroyPaceChannelCommand* createDestroyPaceChannelCommand(); + DestroyPaceChannelCommand* createDestroyPaceChannelCommand(const QString& pSlotHandle); DidAuthenticateEAC1Command* createDidAuthenticateEAC1Command(); DidAuthenticateEAC2Command* createDidAuthenticateEAC2Command(const CVCertificateChain& pCvcChain, @@ -70,7 +72,7 @@ class CardConnection { pCommand->moveToThread(mCardConnectionWorker->thread()); - QMetaObject::Connection resultConnection = connect(pCommand, &BaseCardCommand::commandDone, pReceiver, pFunc, Qt::UniqueConnection); + QMetaObject::Connection resultConnection = connect(pCommand, &BaseCardCommand::commandDone, pReceiver, pFunc); if (resultConnection) { @@ -112,6 +114,7 @@ class CardConnection void setKeepAlive(bool pEnabled); void setProgressMessage(const QString& pMessage, int pProgress = -1); + void setErrorMessage(const QString& pMessage); template QMetaObject::Connection callDidAuthenticateEAC1Command(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc) @@ -164,7 +167,7 @@ class CardConnection template QMetaObject::Connection callSetEidPinCommand(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc, const QByteArray& pNewPin, - quint8 pTimeoutSeconds = 60) + quint8 pTimeoutSeconds = Card::DEFAULT_PINPAD_TIMEOUT) { auto command = createSetEidPinCommand(pNewPin, pTimeoutSeconds); return call(command, pReceiver, pFunc); @@ -172,16 +175,17 @@ class CardConnection template - QMetaObject::Connection callDestroyPaceChannelCommand(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc) + QMetaObject::Connection callDestroyPaceChannelCommand(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc, + const QString& pSlotHandle = QString()) { - auto command = createDestroyPaceChannelCommand(); + auto command = createDestroyPaceChannelCommand(pSlotHandle); return call(command, pReceiver, pFunc); } template QMetaObject::Connection callTransmitCommand(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc, - const QVector& pInputApduInfos, const QString& pSlotHandle = QString()) + const QList& pInputApduInfos, const QString& pSlotHandle = QString()) { auto command = createTransmitCommand(pInputApduInfos, pSlotHandle); return call(command, pReceiver, pFunc); @@ -195,6 +199,14 @@ class CardConnection return call(command, pReceiver, pFunc); } + + template + QMetaObject::Connection callResetRetryCounterCommand(const typename QtPrivate::FunctionPointer::Object* pReceiver, T pFunc) + { + auto command = createResetRetryCounterCommand(); + return call(command, pReceiver, pFunc); + } + Q_SIGNALS: void fireReaderInfoChanged(const ReaderInfo& pReaderInfo); }; diff --git a/src/card/base/CardConnectionWorker.cpp b/src/card/base/CardConnectionWorker.cpp index 8f7a6ecd0..4bd274c16 100644 --- a/src/card/base/CardConnectionWorker.cpp +++ b/src/card/base/CardConnectionWorker.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardConnectionWorker.h" #include "apdu/CommandApdu.h" #include "apdu/FileCommand.h" +#include "apdu/PacePinStatus.h" #include "pace/PaceHandler.h" #include @@ -73,6 +74,41 @@ void CardConnectionWorker::setPukInoperative() } +bool CardConnectionWorker::selectApplicationRoot(const FileRef& pApplication) +{ + qCDebug(card) << "Try to select application:" << pApplication; + ResponseApduResult select = transmit(FileCommand(pApplication)); + switch (select.mResponseApdu.getStatusCode()) + { + case StatusCode::SUCCESS: + case StatusCode::ACCESS_DENIED: + // According to ICAO Doc 9303 "Machine Readable Travel Documents", Eighth Edition + // 2021, 4.3.2 "Inspection Process" an unsecured SelectApplication command will + // return 0x6982 when the card supporting only PACE without Basic Access Control. + // While productive cards have Basic Access Control the test cards do not have it. + break; + + case StatusCode::UNSUPPORTED_INS: + // PersoSim currently does not know its own application identifier. + break; + + default: + qCWarning(card) << "Cannot select application:" << select.mResponseApdu.getStatusCode(); + return false; + } + + qCDebug(card) << "Try to select master file"; + ResponseApduResult result = transmit(FileCommand(FileRef::masterFile())); + if (result.mResponseApdu.getStatusCode() != StatusCode::SUCCESS) + { + qCWarning(card) << "Cannot select master file:" << result.mResponseApdu.getStatusCode(); + return false; + } + + return true; +} + + CardReturnCode CardConnectionWorker::updateRetryCounter() { if (!mReader || !mReader->getCard()) @@ -105,6 +141,12 @@ void CardConnectionWorker::onKeepAliveTimeout() return; } + if (mReader->getReaderInfo().getCardInfo().getCardType() != CardType::SMART_EID) + { + qCDebug(card) << "No Smart-eID - Skipping keep alive"; + return; + } + FileCommand command(FileRef::efCardAccess()); const auto& result = transmit(command); if (result.mReturnCode == CardReturnCode::OK) @@ -238,6 +280,16 @@ void CardConnectionWorker::setProgressMessage(const QString& pMessage, int pProg } +void CardConnectionWorker::setErrorMessage(const QString& pMessage) +{ + const auto card = mReader ? mReader->getCard() : nullptr; + if (card) + { + card->setErrorMessage(pMessage); + } +} + + EstablishPaceChannelOutput CardConnectionWorker::establishPaceChannel(PacePasswordId pPasswordId, const QByteArray& pPasswordValue, const QByteArray& pChat, @@ -288,7 +340,19 @@ EstablishPaceChannelOutput CardConnectionWorker::establishPaceChannel(PacePasswo break; case PacePasswordId::PACE_PIN: - invalidPasswordId = CardReturnCode::INVALID_PIN; + switch (PacePinStatus::getRetryCounter(output.getStatusCodeMseSetAt())) + { + case 2: + invalidPasswordId = CardReturnCode::INVALID_PIN_2; + break; + + case 1: + invalidPasswordId = CardReturnCode::INVALID_PIN_3; + break; + + default: + invalidPasswordId = CardReturnCode::INVALID_PIN; + } break; case PacePasswordId::PACE_PUK: diff --git a/src/card/base/CardConnectionWorker.h b/src/card/base/CardConnectionWorker.h index 2e9fe7c47..428696b8b 100644 --- a/src/card/base/CardConnectionWorker.h +++ b/src/card/base/CardConnectionWorker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -74,6 +74,8 @@ class CardConnectionWorker void setPukInoperative(); + [[nodiscard]] bool selectApplicationRoot(const FileRef& pApplication); + virtual CardReturnCode updateRetryCounter(); virtual CardReturnCode readFile(const FileRef& pFileRef, QByteArray& pFileContent, int pLe = CommandApdu::SHORT_MAX_LE); @@ -102,6 +104,7 @@ class CardConnectionWorker * where interacting with a card leads to a dialog where the message needs to be updated. */ virtual void setProgressMessage(const QString& pMessage, int pProgress = -1); + virtual void setErrorMessage(const QString& pMessage); virtual ResponseApduResult setEidPin(const QByteArray& pNewPin, quint8 pTimeoutSeconds); diff --git a/src/card/base/CardInfo.cpp b/src/card/base/CardInfo.cpp index e58dfd258..2fa0d84b8 100644 --- a/src/card/base/CardInfo.cpp +++ b/src/card/base/CardInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,8 +24,9 @@ using namespace governikus; const int CardInfo::UNDEFINED_RETRY_COUNTER = -1; -CardInfo::CardInfo(CardType pCardType, const QSharedPointer& pEfCardAccess, int pRetryCounter, bool pPinDeactivated, bool pPukInoperative, bool pPinInitial) +CardInfo::CardInfo(CardType pCardType, const FileRef& pApplication, const QSharedPointer& pEfCardAccess, int pRetryCounter, bool pPinDeactivated, bool pPukInoperative, bool pPinInitial) : mCardType(pCardType) + , mApplication(pApplication) , mEfCardAccess(pEfCardAccess) , mRetryCounter(pRetryCounter) , mPinDeactivated(pPinDeactivated) @@ -127,6 +128,18 @@ void CardInfo::setTagType(CardInfo::TagType pTagType) } +const FileRef& CardInfo::getApplication() const +{ + return mApplication; +} + + +void CardInfo::setApplication(const FileRef& pApplication) +{ + mApplication = pApplication; +} + + MobileEidType CardInfo::getMobileEidType() const { if (!mEfCardAccess || !mEfCardAccess->getMobileEIDTypeInfo()) diff --git a/src/card/base/CardInfo.h b/src/card/base/CardInfo.h index da8eceee5..e7032fcd4 100644 --- a/src/card/base/CardInfo.h +++ b/src/card/base/CardInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,9 +8,11 @@ #pragma once +#include "FileRef.h" #include "SmartCardDefinitions.h" #include "asn1/SecurityInfos.h" +#include #include namespace governikus @@ -36,6 +38,7 @@ class CardInfo private: CardType mCardType; + FileRef mApplication; QSharedPointer mEfCardAccess; int mRetryCounter; bool mPinDeactivated; @@ -45,7 +48,7 @@ class CardInfo static const int UNDEFINED_RETRY_COUNTER; public: - CardInfo(CardType pCardType, const QSharedPointer& = QSharedPointer(), + CardInfo(CardType pCardType, const FileRef& pApplication = FileRef(), const QSharedPointer& = QSharedPointer(), int pRetryCounter = UNDEFINED_RETRY_COUNTER, bool pPinDeactivated = false, bool pPukInoperative = false, bool pPinInitial = false); void setCardType(CardType pCardType); @@ -61,6 +64,9 @@ class CardInfo [[nodiscard]] TagType getTagType() const; void setTagType(TagType pTagType); + [[nodiscard]] const FileRef& getApplication() const; + void setApplication(const FileRef& pApplication); + [[nodiscard]] bool isRetryCounterDetermined() const; /*! diff --git a/src/card/base/CardInfoFactory.cpp b/src/card/base/CardInfoFactory.cpp index c8e45a359..f472e530c 100644 --- a/src/card/base/CardInfoFactory.cpp +++ b/src/card/base/CardInfoFactory.cpp @@ -1,10 +1,9 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardInfoFactory.h" -#include "apdu/FileCommand.h" #include "asn1/ApplicationTemplates.h" #include "asn1/PaceInfo.h" @@ -27,7 +26,9 @@ CardInfo CardInfoFactory::create(const QSharedPointer& pCa return CardInfo(CardType::UNKNOWN); } - if (!CardInfoFactory::detectCard(pCardConnectionWorker)) + const auto application = CardInfoFactory::detectCard(pCardConnectionWorker); + + if (application == FileRef()) { qCWarning(card) << "Not a German EID card"; return CardInfo(CardType::UNKNOWN); @@ -40,43 +41,25 @@ CardInfo CardInfoFactory::create(const QSharedPointer& pCa return CardInfo(CardType::UNKNOWN); } - const CardInfo cardInfo(efCardAccess->getMobileEIDTypeInfo() ? CardType::SMART_EID : CardType::EID_CARD, efCardAccess); + const CardInfo cardInfo(efCardAccess->getMobileEIDTypeInfo() ? CardType::SMART_EID : CardType::EID_CARD, application, efCardAccess); qCDebug(card) << "Card detected:" << cardInfo; return cardInfo; } -bool CardInfoFactory::selectApplication(const QSharedPointer& pCardConnectionWorker, const FileRef& pFileRef) +bool CardInfoFactory::detectEid(const QSharedPointer& pCardConnectionWorker, const FileRef& pRef) { - qCDebug(card) << "Try to select application:" << pFileRef; - - FileCommand command(pFileRef); - ResponseApduResult select = pCardConnectionWorker->transmit(command); - if (select.mResponseApdu.getStatusCode() != StatusCode::SUCCESS) + if (!pCardConnectionWorker->selectApplicationRoot(pRef)) { - qCWarning(card) << "Cannot select application identifier:" << select.mResponseApdu.getStatusCode(); return false; } - return true; -} - - -bool CardInfoFactory::detectEid(const QSharedPointer& pCardConnectionWorker, const FileRef& pRef) -{ - // 1. Select the application id - selectApplication(pCardConnectionWorker, pRef); - - // 2. Select the master file - FileCommand command(FileRef::masterFile()); - ResponseApduResult result = pCardConnectionWorker->transmit(command); - if (result.mResponseApdu.getStatusCode() != StatusCode::SUCCESS) + if (pRef == FileRef::appPassport()) { - qCWarning(card) << "Cannot select MF:" << result.mResponseApdu.getStatusCode(); + qCDebug(card) << "Passport found"; return false; } - // 3. Read EF.DIR QByteArray rawEfDir; if (pCardConnectionWorker->readFile(FileRef::efDir(), rawEfDir) != CardReturnCode::OK) { @@ -101,23 +84,17 @@ bool CardInfoFactory::detectEid(const QSharedPointer& pCar } -bool CardInfoFactory::detectCard(const QSharedPointer& pCardConnectionWorker) +FileRef CardInfoFactory::detectCard(const QSharedPointer& pCardConnectionWorker) { - for (const auto& appId : {FileRef::appEId(), FileRef::appPersosim()}) + for (const auto& appId : {FileRef::appEId(), FileRef::appPersosim(), FileRef::appPassport()}) { - const auto eidAvailable = detectEid(pCardConnectionWorker, appId); - if (eidAvailable) + if (detectEid(pCardConnectionWorker, appId)) { - return true; + return appId; } } - if (selectApplication(pCardConnectionWorker, FileRef::appPassport())) - { - qCDebug(card) << "Passport found"; - } - - return false; + return FileRef(); } diff --git a/src/card/base/CardInfoFactory.h b/src/card/base/CardInfoFactory.h index 338763f27..74433fb8a 100644 --- a/src/card/base/CardInfoFactory.h +++ b/src/card/base/CardInfoFactory.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -30,12 +30,10 @@ class CardInfoFactory final static CardInfo create(const QSharedPointer& pCardConnectionWorker); private: - static bool selectApplication(const QSharedPointer& pCardConnectionWorker, const FileRef& pFileRef); - /*! * Checks, if the smart card is a german eID card (i.e. a NPA or an EAT) or a passport. */ - static bool detectCard(const QSharedPointer& pCardConnectionWorker); + static FileRef detectCard(const QSharedPointer& pCardConnectionWorker); static bool detectEid(const QSharedPointer& pCardConnectionWorker, const FileRef& pRef); /*! diff --git a/src/card/base/FileRef.cpp b/src/card/base/FileRef.cpp index 4de0c5462..6624a7648 100644 --- a/src/card/base/FileRef.cpp +++ b/src/card/base/FileRef.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "FileRef.h" diff --git a/src/card/base/FileRef.h b/src/card/base/FileRef.h index 85df433e5..339c6aa9e 100644 --- a/src/card/base/FileRef.h +++ b/src/card/base/FileRef.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -53,6 +53,14 @@ class FileRef }; +inline bool operator==(const FileRef& pFileRefA, const FileRef& pFileRefB) +{ + return pFileRefA.getType() == pFileRefB.getType() + && pFileRefA.getIdentifier() == pFileRefB.getIdentifier() + && pFileRefA.getShortIdentifier() == pFileRefB.getShortIdentifier(); +} + + inline QDebug operator<<(QDebug pDbg, const FileRef& pFileRef) { QDebugStateSaver saver(pDbg); diff --git a/src/card/base/InputAPDUInfo.cpp b/src/card/base/InputAPDUInfo.cpp index b0b90e939..8e68bb3d9 100644 --- a/src/card/base/InputAPDUInfo.cpp +++ b/src/card/base/InputAPDUInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "InputAPDUInfo.h" diff --git a/src/card/base/InputAPDUInfo.h b/src/card/base/InputAPDUInfo.h index 19b824c30..a305cfd5f 100644 --- a/src/card/base/InputAPDUInfo.h +++ b/src/card/base/InputAPDUInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/Reader.cpp b/src/card/base/Reader.cpp index 46029e7db..7331a7166 100644 --- a/src/card/base/Reader.cpp +++ b/src/card/base/Reader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Reader.h" @@ -7,8 +7,8 @@ #include "CardConnectionWorker.h" #include "CardInfoFactory.h" #include "apdu/CommandApdu.h" -#include "apdu/CommandData.h" #include "apdu/PacePinStatus.h" +#include "asn1/ASN1Struct.h" #include "asn1/PaceInfo.h" #include @@ -21,9 +21,9 @@ Q_DECLARE_LOGGING_CATEGORY(card) Q_DECLARE_LOGGING_CATEGORY(support) -Reader::Reader(ReaderManagerPlugInType pPlugInType, const QString& pReaderName) +Reader::Reader(ReaderManagerPluginType pPluginType, const QString& pReaderName) : QObject() - , mReaderInfo(pReaderName, pPlugInType) + , mReaderInfo(pReaderName, pPluginType) , mTimerId(0) { } @@ -64,6 +64,8 @@ void Reader::fetchCardInfo() { const auto& cardConnection = createCardConnectionWorker(); + printGetReaderInfo(); + setInfoCardInfo(CardInfoFactory::create(cardConnection)); if (cardConnection && cardConnection->updateRetryCounter() != CardReturnCode::OK) @@ -101,8 +103,9 @@ void Reader::insertCard(const QVariant& pData) return; } - qCDebug(card) << "Card inserted"; mReaderInfo.insertCard(); + + qCInfo(card) << "Card inserted:" << mReaderInfo.getCardInfo(); Q_EMIT fireCardInserted(mReaderInfo); } @@ -121,6 +124,7 @@ void Reader::shelveCard() if (wasShelved) { + qCInfo(card) << "Card removed"; Q_EMIT fireCardRemoved(mReaderInfo); return; } @@ -210,12 +214,12 @@ Reader::RetryCounterResult Reader::getRetryCounter(QSharedPointergetPaceInfos().at(0); - CommandData cmdData; - cmdData.append(CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE, paceInfo->getOid()); - cmdData.append(CommandData::PUBLIC_KEY_REFERENCE, PacePasswordId::PACE_PIN); + ASN1Struct cmdData; + cmdData.append(ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE, paceInfo->getOid()); + cmdData.append(ASN1Struct::PUBLIC_KEY_REFERENCE, PacePasswordId::PACE_PIN); if (paceInfo->hasParameterId()) { - cmdData.append(CommandData::PRIVATE_KEY_REFERENCE, paceInfo->getParameterId()); + cmdData.append(ASN1Struct::PRIVATE_KEY_REFERENCE, paceInfo->getParameterId()); } CommandApdu cmdApdu(Ins::MSE_SET, CommandApdu::PACE, CommandApdu::AUTHENTICATION_TEMPLATE, cmdData); diff --git a/src/card/base/Reader.h b/src/card/base/Reader.h index 5d85ff23f..2e0cc8828 100644 --- a/src/card/base/Reader.h +++ b/src/card/base/Reader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -48,9 +48,15 @@ class Reader RetryCounterResult getRetryCounter(QSharedPointer pCardConnectionWorker); public: - Reader(ReaderManagerPlugInType pPlugInType, const QString& pReaderName); + Reader(ReaderManagerPluginType pPluginType, const QString& pReaderName); ~Reader() override = default; + + virtual void printGetReaderInfo() const + { + } + + /*! * Periodically called to perform an update of the readers and cards state. */ diff --git a/src/card/base/ReaderFilter.cpp b/src/card/base/ReaderFilter.cpp index ecfe5f69c..3c6af97f6 100644 --- a/src/card/base/ReaderFilter.cpp +++ b/src/card/base/ReaderFilter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderFilter.h" @@ -17,7 +17,7 @@ ReaderFilter::ReaderFilter() } -ReaderFilter::ReaderFilter(const QVector& pPluginTypes) +ReaderFilter::ReaderFilter(const QList& pPluginTypes) : mFilterType(PluginTypeFilter) , mPluginTypes(pPluginTypes) { @@ -31,17 +31,17 @@ ReaderFilter::ReaderFilter(const ReaderFilter::FilterType pFilterType) } -QVector ReaderFilter::apply(const QVector& pInputList) const +QList ReaderFilter::apply(const QList& pInputList) const { - QVector filtered = pInputList; + QList filtered = pInputList; if (mFilterType & PluginTypeFilter) { - QMutableVectorIterator iter(filtered); + QMutableListIterator iter(filtered); while (iter.hasNext()) { const ReaderInfo entry = iter.next(); - if (!mPluginTypes.contains(entry.getPlugInType())) + if (!mPluginTypes.contains(entry.getPluginType())) { iter.remove(); } @@ -50,9 +50,9 @@ QVector ReaderFilter::apply(const QVector& pInputList) c if (mFilterType & UniqueReaderTypes) { - QVector alreadyContained; + QList alreadyContained; - QMutableVectorIterator iter(filtered); + QMutableListIterator iter(filtered); while (iter.hasNext()) { const ReaderConfigurationInfo configurationInfo = iter.next().getReaderConfigurationInfo(); diff --git a/src/card/base/ReaderFilter.h b/src/card/base/ReaderFilter.h index 53ad3e972..17fa6ef50 100644 --- a/src/card/base/ReaderFilter.h +++ b/src/card/base/ReaderFilter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,10 +9,10 @@ #pragma once #include "ReaderInfo.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include -#include +#include namespace governikus { @@ -30,14 +30,14 @@ class ReaderFilter private: const ReaderFilter::FilterTypes mFilterType; - const QVector mPluginTypes; + const QList mPluginTypes; public: ReaderFilter(); ReaderFilter(const ReaderFilter::FilterType pFilterType); - explicit ReaderFilter(const QVector& pPluginTypes); + explicit ReaderFilter(const QList& pPluginTypes); - [[nodiscard]] QVector apply(const QVector& pInputList) const; + [[nodiscard]] QList apply(const QList& pInputList) const; }; } // namespace governikus diff --git a/src/card/base/ReaderInfo.cpp b/src/card/base/ReaderInfo.cpp index 11cef4b02..da1939634 100644 --- a/src/card/base/ReaderInfo.cpp +++ b/src/card/base/ReaderInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderInfo.h" @@ -17,9 +17,9 @@ INIT_FUNCTION([] { }) ReaderInfo::ReaderInfo(const QString& pName, - ReaderManagerPlugInType pPlugInType, + ReaderManagerPluginType pPluginType, const CardInfo& pCardInfo) - : mPlugInType(pPlugInType) + : mPluginType(pPluginType) , mName(pName) , mBasicReader(true) , mCardInfo(pCardInfo) @@ -27,7 +27,7 @@ ReaderInfo::ReaderInfo(const QString& pName, , mShelvedCard(CardType::NONE) { #ifdef Q_OS_ANDROID - if (pPlugInType == ReaderManagerPlugInType::NFC) + if (pPluginType == ReaderManagerPluginType::NFC) { mMaxApduLength = -1; } diff --git a/src/card/base/ReaderInfo.h b/src/card/base/ReaderInfo.h index aec197870..2658458fe 100644 --- a/src/card/base/ReaderInfo.h +++ b/src/card/base/ReaderInfo.h @@ -1,12 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "CardInfo.h" #include "ReaderConfigurationInfo.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include "SmartCardDefinitions.h" #include @@ -19,7 +19,7 @@ class ReaderInfo friend class Reader; private: - ReaderManagerPlugInType mPlugInType; + ReaderManagerPluginType mPluginType; QString mName; bool mBasicReader; CardInfo mCardInfo; @@ -28,27 +28,27 @@ class ReaderInfo public: explicit ReaderInfo(const QString& pName = QString(), - ReaderManagerPlugInType pPlugInType = ReaderManagerPlugInType::UNKNOWN, + ReaderManagerPluginType pPluginType = ReaderManagerPluginType::UNKNOWN, const CardInfo& pCardInfo = CardInfo(CardType::NONE)); [[nodiscard]] ReaderConfigurationInfo getReaderConfigurationInfo() const; - [[nodiscard]] ReaderManagerPlugInType getPlugInType() const + [[nodiscard]] ReaderManagerPluginType getPluginType() const { - return mPlugInType; + return mPluginType; } [[nodiscard]] bool isValid() const { - return mPlugInType != ReaderManagerPlugInType::UNKNOWN; + return mPluginType != ReaderManagerPluginType::UNKNOWN; } void invalidate() { - mPlugInType = ReaderManagerPlugInType::UNKNOWN; + mPluginType = ReaderManagerPluginType::UNKNOWN; mCardInfo = CardInfo(CardType::NONE); } @@ -85,7 +85,7 @@ class ReaderInfo [[nodiscard]] bool hasEid() const { - return QVector({CardType::EID_CARD, CardType::SMART_EID}).contains(mCardInfo.getCardType()); + return QList({CardType::EID_CARD, CardType::SMART_EID}).contains(mCardInfo.getCardType()); } diff --git a/src/card/base/ReaderManager.cpp b/src/card/base/ReaderManager.cpp index 250cd8de1..a9a1c4a1b 100644 --- a/src/card/base/ReaderManager.cpp +++ b/src/card/base/ReaderManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderManager.h" @@ -10,7 +10,7 @@ using namespace governikus; -QVector> ReaderManager::cMainThreadInit; +QList> ReaderManager::cMainThreadInit; Q_DECLARE_LOGGING_CATEGORY(card) @@ -101,7 +101,7 @@ void ReaderManager::init() } -void ReaderManager::reset(ReaderManagerPlugInType pType) +void ReaderManager::reset(ReaderManagerPluginType pType) { const QMutexLocker mutexLocker(&mMutex); @@ -167,13 +167,13 @@ void ReaderManager::shutdown() mThread.quit(); mThread.wait(5000); mReaderInfoCache.clear(); - mPlugInInfoCache.clear(); + mPluginInfoCache.clear(); qCDebug(card).noquote() << mThread.objectName() << "stopped:" << !mThread.isRunning(); } } -void ReaderManager::startScan(ReaderManagerPlugInType pType, bool pAutoConnect) +void ReaderManager::startScan(ReaderManagerPluginType pType, bool pAutoConnect) { const QMutexLocker mutexLocker(&mMutex); @@ -192,14 +192,14 @@ void ReaderManager::startScan(ReaderManagerPlugInType pType, bool pAutoConnect) void ReaderManager::startScanAll(bool pAutoConnect) { - for (const auto& entry : std::as_const(mPlugInInfoCache)) + for (const auto& entry : std::as_const(mPluginInfoCache)) { - startScan(entry.getPlugInType(), pAutoConnect); + startScan(entry.getPluginType(), pAutoConnect); } } -void ReaderManager::stopScan(ReaderManagerPlugInType pType, const QString& pError) +void ReaderManager::stopScan(ReaderManagerPluginType pType, const QString& pError) { const QMutexLocker mutexLocker(&mMutex); @@ -216,20 +216,31 @@ void ReaderManager::stopScan(ReaderManagerPlugInType pType, const QString& pErro } +bool ReaderManager::isInitialScanFinished() const +{ + const QMutexLocker mutexLocker(&mMutex); + return std::all_of(mPluginInfoCache.cbegin(), mPluginInfoCache.cend(), [] (const ReaderManagerPluginInfo& pInfo){ + const auto& state = pInfo.getInitialScanState(); + return state == ReaderManagerPluginInfo::InitialScan::SUCCEEDED + || state == ReaderManagerPluginInfo::InitialScan::FAILED; + }); +} + + void ReaderManager::stopScanAll(const QString& pError) { - for (const auto& entry : std::as_const(mPlugInInfoCache)) + for (const auto& entry : std::as_const(mPluginInfoCache)) { - stopScan(entry.getPlugInType(), pError); + stopScan(entry.getPluginType(), pError); } } -ReaderManagerPlugInInfo ReaderManager::getPlugInInfo(ReaderManagerPlugInType pType) const +ReaderManagerPluginInfo ReaderManager::getPluginInfo(ReaderManagerPluginType pType) const { const QMutexLocker mutexLocker(&mMutex); - return mPlugInInfoCache.value(pType, ReaderManagerPlugInInfo(pType)); + return mPluginInfoCache.value(pType, ReaderManagerPluginInfo(pType)); } @@ -251,16 +262,27 @@ void ReaderManager::doRemoveCacheEntry(const ReaderInfo& pInfo) } -void ReaderManager::doUpdatePluginCache(const ReaderManagerPlugInInfo& pInfo) +void ReaderManager::doUpdatePluginCache(const ReaderManagerPluginInfo& pInfo) { - const QMutexLocker mutexLocker(&mMutex); + ReaderManagerPluginInfo cachedValue; - qCDebug(card).noquote() << "Update cache entry:" << pInfo.getPlugInType(); - mPlugInInfoCache.insert(pInfo.getPlugInType(), pInfo); + { + const QMutexLocker mutexLocker(&mMutex); + + qCDebug(card).noquote() << "Update cache entry:" << pInfo.getPluginType(); + cachedValue = mPluginInfoCache.value(pInfo.getPluginType()); + mPluginInfoCache.insert(pInfo.getPluginType(), pInfo); + } + + if (cachedValue.getInitialScanState() != pInfo.getInitialScanState() && isInitialScanFinished()) + { + qCDebug(card) << "Initial scan finished"; + Q_EMIT fireInitialScanFinished(); + } } -QVector ReaderManager::getReaderInfos(const ReaderFilter& pFilter) const +QList ReaderManager::getReaderInfos(const ReaderFilter& pFilter) const { Q_ASSERT(mThread.isRunning() || mThread.isFinished()); const QMutexLocker mutexLocker(&mMutex); diff --git a/src/card/base/ReaderManager.h b/src/card/base/ReaderManager.h index ff41a4fa5..fc967f778 100644 --- a/src/card/base/ReaderManager.h +++ b/src/card/base/ReaderManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -16,7 +16,6 @@ #include - namespace governikus { @@ -28,13 +27,13 @@ class ReaderManager friend class Env; private: - static QVector> cMainThreadInit; + static QList> cMainThreadInit; mutable QMutex mMutex; QThread mThread; QPointer mWorker; QMap mReaderInfoCache; - QMap mPlugInInfoCache; + QMap mPluginInfoCache; protected: ReaderManager(); @@ -52,7 +51,7 @@ class ReaderManager /*! * Resets the plugins matching the given type. */ - void reset(ReaderManagerPlugInType pType); + void reset(ReaderManagerPluginType pType); /*! * Insert a "virtual" card if plugin supports it. @@ -72,7 +71,7 @@ class ReaderManager /*! * Starts a scan for devices if registered plugin don't scan anytime. */ - void startScan(ReaderManagerPlugInType pType, bool pAutoConnect = true); + void startScan(ReaderManagerPluginType pType, bool pAutoConnect = true); /*! * Stops scan for all device types. @@ -84,10 +83,12 @@ class ReaderManager * Be aware that some plugins don't finish the whole scan if you * abort it with stopScan! */ - void stopScan(ReaderManagerPlugInType pType, const QString& pError = QString()); + void stopScan(ReaderManagerPluginType pType, const QString& pError = QString()); + + bool isInitialScanFinished() const; - ReaderManagerPlugInInfo getPlugInInfo(ReaderManagerPlugInType pType) const; - virtual QVector getReaderInfos(const ReaderFilter& pFilter = ReaderFilter()) const; + virtual ReaderManagerPluginInfo getPluginInfo(ReaderManagerPluginType pType) const; + virtual QList getReaderInfos(const ReaderFilter& pFilter = ReaderFilter()) const; ReaderInfo getReaderInfo(const QString& pReaderName) const; void updateReaderInfo(const QString& pReaderName); @@ -178,7 +179,7 @@ class ReaderManager QMetaObject::Connection callCreateCardConnectionCommand(const QString& pReaderName, const typename QtPrivate::FunctionPointer::Object* pReceiver, T pSlot) { auto* command = new CreateCardConnectionCommand(pReaderName, mWorker); - QMetaObject::Connection connection = connect(command, &CreateCardConnectionCommand::fireCommandDone, pReceiver, pSlot, Qt::UniqueConnection); + QMetaObject::Connection connection = connect(command, &CreateCardConnectionCommand::fireCommandDone, pReceiver, pSlot); if (connection) { command->run(); @@ -193,8 +194,8 @@ class ReaderManager } Q_SIGNALS: - void firePluginAdded(const ReaderManagerPlugInInfo& pInfo); - void fireStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void firePluginAdded(const ReaderManagerPluginInfo& pInfo); + void fireStatusChanged(const ReaderManagerPluginInfo& pInfo); void fireReaderAdded(const ReaderInfo& pInfo); void fireReaderRemoved(const ReaderInfo& pInfo); void fireReaderPropertiesUpdated(const ReaderInfo& pInfo); @@ -202,11 +203,12 @@ class ReaderManager void fireCardRemoved(const ReaderInfo& pInfo); void fireCardInfoChanged(const ReaderInfo& pInfo); void fireInitialized(); + void fireInitialScanFinished(); private Q_SLOTS: void doUpdateCacheEntry(const ReaderInfo& pInfo); void doRemoveCacheEntry(const ReaderInfo& pInfo); - void doUpdatePluginCache(const ReaderManagerPlugInInfo& pInfo); + void doUpdatePluginCache(const ReaderManagerPluginInfo& pInfo); public Q_SLOTS: /*! diff --git a/src/card/base/ReaderManagerPlugIn.cpp b/src/card/base/ReaderManagerPlugIn.cpp deleted file mode 100644 index 8b77773ba..000000000 --- a/src/card/base/ReaderManagerPlugIn.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "ReaderManagerPlugIn.h" - - -using namespace governikus; - - -ReaderManagerPlugIn::ReaderManagerPlugIn(ReaderManagerPlugInType pPlugInType, - bool pAvailable, - bool pPlugInEnabled) - : mInfo(pPlugInType, pPlugInEnabled, pAvailable) -{ -} - - -void ReaderManagerPlugIn::shelve() const -{ - const auto& readers = getReaders(); - for (const auto& reader : readers) - { - if (reader->getReaderInfo().wasShelved()) - { - reader->shelveCard(); - } - } -} - - -void ReaderManagerPlugIn::startScan(bool /*pAutoConnect*/) -{ - if (!mInfo.isScanRunning()) - { - mInfo.setScanRunning(true); - Q_EMIT fireStatusChanged(mInfo); - } -} - - -void ReaderManagerPlugIn::stopScan(const QString& pError) -{ - Q_UNUSED(pError) - - if (mInfo.isScanRunning()) - { - mInfo.setScanRunning(false); - Q_EMIT fireStatusChanged(mInfo); - } -} diff --git a/src/card/base/ReaderManagerPlugInInfo.cpp b/src/card/base/ReaderManagerPlugInInfo.cpp deleted file mode 100644 index f8884cf8c..000000000 --- a/src/card/base/ReaderManagerPlugInInfo.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "ReaderManagerPlugInInfo.h" - -#include "Initializer.h" - -using namespace governikus; - -INIT_FUNCTION([] { - qRegisterMetaType("ReaderManagerPlugInInfo"); - }) - - -ReaderManagerPlugInInfo::ReaderManagerPlugInInfo(ReaderManagerPlugInType pType, bool pEnabled, bool pAvailable) - : mType(pType) - , mValues() - , mEnabled(pEnabled) - , mAvailable(pAvailable) - , mScanRunning(false) -{ -} - - -#include "moc_ReaderManagerPlugInInfo.cpp" diff --git a/src/card/base/ReaderManagerPlugin.cpp b/src/card/base/ReaderManagerPlugin.cpp new file mode 100644 index 000000000..c7d535d4e --- /dev/null +++ b/src/card/base/ReaderManagerPlugin.cpp @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "ReaderManagerPlugin.h" + + +using namespace governikus; + + +ReaderManagerPlugin::ReaderManagerPlugin(ReaderManagerPluginType pPluginType, + bool pAvailable, + bool pPluginEnabled) + : mInfo(pPluginType, pPluginEnabled, pAvailable) +{ +} + + +void ReaderManagerPlugin::shelve() const +{ + const auto& readers = getReaders(); + for (const auto& reader : readers) + { + if (reader->getReaderInfo().wasShelved()) + { + reader->shelveCard(); + } + } +} + + +void ReaderManagerPlugin::startScan(bool /*pAutoConnect*/) +{ + if (!mInfo.isScanRunning()) + { + mInfo.setScanRunning(true); + Q_EMIT fireStatusChanged(mInfo); + } +} + + +void ReaderManagerPlugin::stopScan(const QString& pError) +{ + Q_UNUSED(pError) + + if (mInfo.isScanRunning()) + { + mInfo.setScanRunning(false); + Q_EMIT fireStatusChanged(mInfo); + } +} + + +void ReaderManagerPlugin::setInitialScanState(ReaderManagerPluginInfo::InitialScan pState) +{ + if (mInfo.getInitialScanState() != pState) + { + mInfo.setInitialScanState(pState); + Q_EMIT fireStatusChanged(mInfo); + } +} diff --git a/src/card/base/ReaderManagerPlugIn.h b/src/card/base/ReaderManagerPlugin.h similarity index 62% rename from src/card/base/ReaderManagerPlugIn.h rename to src/card/base/ReaderManagerPlugin.h index 966a2ee4f..a391fa903 100644 --- a/src/card/base/ReaderManagerPlugIn.h +++ b/src/card/base/ReaderManagerPlugin.h @@ -1,17 +1,17 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief PlugIn to control different kinds of reader managers that will be used in \ref ReaderManager. - * If you implement a class of this PlugIn you need to register it in \ref ReaderManager, otherwise it won't be used. + * \brief Plugin to control different kinds of reader managers that will be used in \ref ReaderManager. + * If you implement a class of this Plugin you need to register it in \ref ReaderManager, otherwise it won't be used. */ #pragma once #include "Reader.h" #include "ReaderInfo.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include #include @@ -19,17 +19,17 @@ namespace governikus { -class ReaderManagerPlugIn +class ReaderManagerPlugin : public QObject { Q_OBJECT - friend class MockReaderManagerPlugIn; + friend class MockReaderManagerPlugin; private: - ReaderManagerPlugInInfo mInfo; + ReaderManagerPluginInfo mInfo; protected: - void setPlugInEnabled(bool pEnabled) + void setPluginEnabled(bool pEnabled) { if (mInfo.isEnabled() != pEnabled) { @@ -39,25 +39,25 @@ class ReaderManagerPlugIn } - void setPlugInAvailable(bool pAvailable) + void setPluginAvailable(bool pAvailable) { mInfo.setAvailable(pAvailable); Q_EMIT fireStatusChanged(mInfo); } - void setPlugInValue(ReaderManagerPlugInInfo::Key pKey, const QVariant& pValue) + void setPluginValue(ReaderManagerPluginInfo::Key pKey, const QVariant& pValue) { mInfo.setValue(pKey, pValue); } public: - ReaderManagerPlugIn(ReaderManagerPlugInType pPlugInType, + ReaderManagerPlugin(ReaderManagerPluginType pPluginType, bool pAvailable = false, - bool pPlugInEnabled = false); - ~ReaderManagerPlugIn() override = default; + bool pPluginEnabled = false); + ~ReaderManagerPlugin() override = default; - [[nodiscard]] const ReaderManagerPlugInInfo& getInfo() const + [[nodiscard]] const ReaderManagerPluginInfo& getInfo() const { return mInfo; } @@ -96,9 +96,10 @@ class ReaderManagerPlugIn virtual void startScan(bool pAutoConnect); virtual void stopScan(const QString& pError = QString()); + void setInitialScanState(ReaderManagerPluginInfo::InitialScan pState); Q_SIGNALS: - void fireStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void fireStatusChanged(const ReaderManagerPluginInfo& pInfo); void fireReaderAdded(const ReaderInfo& pInfo); void fireReaderRemoved(const ReaderInfo& pInfo); void fireCardInserted(const ReaderInfo& pInfo); @@ -109,4 +110,4 @@ class ReaderManagerPlugIn } // namespace governikus -Q_DECLARE_INTERFACE(governikus::ReaderManagerPlugIn, "governikus.ReaderManagerPlugIn") +Q_DECLARE_INTERFACE(governikus::ReaderManagerPlugin, "governikus.ReaderManagerPlugin") diff --git a/src/card/base/ReaderManagerPluginInfo.cpp b/src/card/base/ReaderManagerPluginInfo.cpp new file mode 100644 index 000000000..053d6947c --- /dev/null +++ b/src/card/base/ReaderManagerPluginInfo.cpp @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "ReaderManagerPluginInfo.h" + +#include "Initializer.h" + +using namespace governikus; + +INIT_FUNCTION([] { + qRegisterMetaType("ReaderManagerPluginInfo"); + }) + + +ReaderManagerPluginInfo::ReaderManagerPluginInfo(ReaderManagerPluginType pType, bool pEnabled, bool pAvailable) + : mType(pType) + , mValues() + , mEnabled(pEnabled) + , mAvailable(pAvailable) + , mScanRunning(false) + , mInitialScan(InitialScan::UNKNOWN) +{ +} + + +#include "moc_ReaderManagerPluginInfo.cpp" diff --git a/src/card/base/ReaderManagerPlugInInfo.h b/src/card/base/ReaderManagerPluginInfo.h similarity index 70% rename from src/card/base/ReaderManagerPlugInInfo.h rename to src/card/base/ReaderManagerPluginInfo.h index 54cebc3a1..44625b09f 100644 --- a/src/card/base/ReaderManagerPlugInInfo.h +++ b/src/card/base/ReaderManagerPluginInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,7 +17,7 @@ namespace governikus { -defineEnumType(ReaderManagerPlugInType +defineEnumTypeQmlExposed(ReaderManagerPluginType , UNKNOWN , MOCK , PCSC @@ -29,7 +29,7 @@ defineEnumType(ReaderManagerPlugInType ) -class ReaderManagerPlugInInfo +class ReaderManagerPluginInfo { public: enum class Key @@ -37,12 +37,19 @@ class ReaderManagerPlugInInfo PCSC_LITE_VERSION, LOCAL_IFD_STATE }; + enum class InitialScan + { + SUCCEEDED, + FAILED, + UNKNOWN + }; + public: - ReaderManagerPlugInInfo(ReaderManagerPlugInType pType = ReaderManagerPlugInType::UNKNOWN, + ReaderManagerPluginInfo(ReaderManagerPluginType pType = ReaderManagerPluginType::UNKNOWN, bool pEnabled = false, bool pAvailable = false); - [[nodiscard]] const ReaderManagerPlugInType& getPlugInType() const + [[nodiscard]] const ReaderManagerPluginType& getPluginType() const { return mType; } @@ -107,13 +114,25 @@ class ReaderManagerPlugInInfo mScanRunning = pScanRunning; } + + [[nodiscard]] InitialScan getInitialScanState() const + { + return mInitialScan; + } + + + void setInitialScanState(InitialScan pInitialScan) + { + mInitialScan = pInitialScan; + } + private: - ReaderManagerPlugInType mType; + ReaderManagerPluginType mType; QMap mValues; bool mEnabled; bool mAvailable; bool mScanRunning; - + InitialScan mInitialScan; }; diff --git a/src/card/base/ReaderManagerWorker.cpp b/src/card/base/ReaderManagerWorker.cpp index 285f31b6a..283e0ee5a 100644 --- a/src/card/base/ReaderManagerWorker.cpp +++ b/src/card/base/ReaderManagerWorker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderManagerWorker.h" @@ -24,7 +24,7 @@ INIT_FUNCTION([] { ReaderManagerWorker::ReaderManagerWorker() : QObject() - , mPlugIns() + , mPlugins() { } @@ -39,7 +39,7 @@ ReaderManagerWorker::~ReaderManagerWorker() void ReaderManagerWorker::shutdown() { qCDebug(card) << "Shutdown ReaderManagerWorker"; - for (auto& plugin : std::as_const(mPlugIns)) + for (auto& plugin : std::as_const(mPlugins)) { plugin->stopScan(); @@ -50,7 +50,7 @@ void ReaderManagerWorker::shutdown() // https://bugreports.qt.io/browse/QTBUG-17458 plugin->deleteLater(); } - mPlugIns.clear(); + mPlugins.clear(); } @@ -67,29 +67,29 @@ void ReaderManagerWorker::onThreadStarted() Q_ASSERT(QObject::thread() == QThread::currentThread()); qCDebug(card) << "Thread started"; - registerPlugIns(); + registerPlugins(); Q_EMIT fireInitialized(); } -void ReaderManagerWorker::registerPlugIns() +void ReaderManagerWorker::registerPlugins() { qCDebug(card) << "Try to register plugins"; const auto& plugins = QPluginLoader::staticPlugins(); for (const auto& plugin : plugins) { - if (isPlugIn(plugin.metaData())) + if (isPlugin(plugin.metaData())) { qCDebug(card) << "Register and initialize plugin:" << plugin.metaData(); - ReaderManagerPlugIn* pluginInstance = qobject_cast(plugin.instance()); + ReaderManagerPlugin* pluginInstance = qobject_cast(plugin.instance()); if (pluginInstance == nullptr) { qCWarning(card) << "Cannot cast to plugin instance:" << plugin.instance(); } else { - registerPlugIn(pluginInstance); + registerPlugin(pluginInstance); pluginInstance->init(); Q_EMIT firePluginAdded(pluginInstance->getInfo()); @@ -99,34 +99,34 @@ void ReaderManagerWorker::registerPlugIns() } -bool ReaderManagerWorker::isPlugIn(const QJsonObject& pJson) +bool ReaderManagerWorker::isPlugin(const QJsonObject& pJson) { - return pJson.value(QLatin1String("IID")).toString() == QLatin1String("governikus.ReaderManagerPlugIn"); + return pJson.value(QLatin1String("IID")).toString() == QLatin1String("governikus.ReaderManagerPlugin"); } -void ReaderManagerWorker::registerPlugIn(ReaderManagerPlugIn* pPlugIn) +void ReaderManagerWorker::registerPlugin(ReaderManagerPlugin* pPlugin) { - Q_ASSERT(pPlugIn != nullptr); - Q_ASSERT(!mPlugIns.contains(pPlugIn)); - - mPlugIns << pPlugIn; - - connect(pPlugIn, &ReaderManagerPlugIn::fireReaderAdded, this, &ReaderManagerWorker::fireReaderAdded); - connect(pPlugIn, &ReaderManagerPlugIn::fireReaderRemoved, this, &ReaderManagerWorker::onReaderRemoved); - connect(pPlugIn, &ReaderManagerPlugIn::fireReaderPropertiesUpdated, this, &ReaderManagerWorker::fireReaderPropertiesUpdated); - connect(pPlugIn, &ReaderManagerPlugIn::fireStatusChanged, this, &ReaderManagerWorker::fireStatusChanged); - connect(pPlugIn, &ReaderManagerPlugIn::fireCardInserted, this, &ReaderManagerWorker::fireCardInserted); - connect(pPlugIn, &ReaderManagerPlugIn::fireCardRemoved, this, &ReaderManagerWorker::fireCardRemoved); - connect(pPlugIn, &ReaderManagerPlugIn::fireCardInfoChanged, this, &ReaderManagerWorker::fireCardInfoChanged); + Q_ASSERT(pPlugin != nullptr); + Q_ASSERT(!mPlugins.contains(pPlugin)); + + mPlugins << pPlugin; + + connect(pPlugin, &ReaderManagerPlugin::fireReaderAdded, this, &ReaderManagerWorker::fireReaderAdded); + connect(pPlugin, &ReaderManagerPlugin::fireReaderRemoved, this, &ReaderManagerWorker::onReaderRemoved); + connect(pPlugin, &ReaderManagerPlugin::fireReaderPropertiesUpdated, this, &ReaderManagerWorker::fireReaderPropertiesUpdated); + connect(pPlugin, &ReaderManagerPlugin::fireStatusChanged, this, &ReaderManagerWorker::fireStatusChanged); + connect(pPlugin, &ReaderManagerPlugin::fireCardInserted, this, &ReaderManagerWorker::fireCardInserted); + connect(pPlugin, &ReaderManagerPlugin::fireCardRemoved, this, &ReaderManagerWorker::fireCardRemoved); + connect(pPlugin, &ReaderManagerPlugin::fireCardInfoChanged, this, &ReaderManagerWorker::fireCardInfoChanged); } -void ReaderManagerWorker::callOnPlugIn(ReaderManagerPlugInType pType, const std::function& pFunc, const char* pLog) +void ReaderManagerWorker::callOnPlugin(ReaderManagerPluginType pType, const std::function& pFunc, const char* pLog) { - for (auto& plugin : std::as_const(mPlugIns)) + for (auto& plugin : std::as_const(mPlugins)) { - if (plugin->getInfo().getPlugInType() == pType) + if (plugin->getInfo().getPluginType() == pType) { qCDebug(card).nospace() << pLog << ": " << plugin->metaObject()->className(); pFunc(plugin); @@ -135,12 +135,12 @@ void ReaderManagerWorker::callOnPlugIn(ReaderManagerPlugInType pType, const std: } -void ReaderManagerWorker::reset(ReaderManagerPlugInType pType) +void ReaderManagerWorker::reset(ReaderManagerPluginType pType) { Q_ASSERT(QObject::thread() == QThread::currentThread()); - callOnPlugIn(pType, [](ReaderManagerPlugIn* pPlugIn){ - pPlugIn->reset(); + callOnPlugin(pType, [](ReaderManagerPlugin* pPlugin){ + pPlugin->reset(); }, "Reset plugin"); } @@ -149,8 +149,8 @@ void ReaderManagerWorker::insert(const ReaderInfo& pReaderInfo, const QVariant& { Q_ASSERT(QObject::thread() == QThread::currentThread()); - callOnPlugIn(pReaderInfo.getPlugInType(), [pReaderInfo, pData](ReaderManagerPlugIn* pPlugIn){ - pPlugIn->insert(pReaderInfo.getName(), pData); + callOnPlugin(pReaderInfo.getPluginType(), [pReaderInfo, pData](ReaderManagerPlugin* pPlugin){ + pPlugin->insert(pReaderInfo.getName(), pData); }, "Insert"); } @@ -159,49 +159,50 @@ void ReaderManagerWorker::shelve() { Q_ASSERT(QObject::thread() == QThread::currentThread()); - for (const auto& plugIn : std::as_const(mPlugIns)) + for (const auto& plugin : std::as_const(mPlugins)) { - callOnPlugIn(plugIn->getInfo().getPlugInType(), [](ReaderManagerPlugIn* pPlugIn){ - pPlugIn->shelve(); + callOnPlugin(plugin->getInfo().getPluginType(), [](ReaderManagerPlugin* pPlugin){ + pPlugin->shelve(); }, "Shelve"); } } -void ReaderManagerWorker::startScan(ReaderManagerPlugInType pType, bool pAutoConnect) +void ReaderManagerWorker::startScan(ReaderManagerPluginType pType, bool pAutoConnect) { Q_ASSERT(QObject::thread() == QThread::currentThread()); - callOnPlugIn(pType, [pAutoConnect](ReaderManagerPlugIn* pPlugIn){ - if (!pPlugIn->getInfo().isScanRunning()) + callOnPlugin(pType, [pAutoConnect](ReaderManagerPlugin* pPlugin){ + if (!pPlugin->getInfo().isScanRunning()) { - pPlugIn->startScan(pAutoConnect); + pPlugin->startScan(pAutoConnect); } }, "Start scan on plugin"); } -void ReaderManagerWorker::stopScan(ReaderManagerPlugInType pType, const QString& pError) +void ReaderManagerWorker::stopScan(ReaderManagerPluginType pType, const QString& pError) { Q_ASSERT(QObject::thread() == QThread::currentThread()); - callOnPlugIn(pType, [pError](ReaderManagerPlugIn* pPlugIn){ - if (pPlugIn->getInfo().isScanRunning()) + callOnPlugin(pType, [pError](ReaderManagerPlugin* pPlugin){ + if (pPlugin->getInfo().isScanRunning()) { - pPlugIn->stopScan(pError); + pPlugin->stopScan(pError); + pPlugin->setInitialScanState(ReaderManagerPluginInfo::InitialScan::UNKNOWN); } }, "Stop scan on plugin"); } -QVector ReaderManagerWorker::getReaderInfos() const +QList ReaderManagerWorker::getReaderInfos() const { Q_ASSERT(QObject::thread() == QThread::currentThread()); - QVector list; - for (const auto& plugIn : std::as_const(mPlugIns)) + QList list; + for (const auto& plugin : std::as_const(mPlugins)) { - const auto& readerList = plugIn->getReaders(); + const auto& readerList = plugin->getReaders(); for (const Reader* const reader : readerList) { list += reader->getReaderInfo(); @@ -229,7 +230,7 @@ Reader* ReaderManagerWorker::getReader(const QString& pReaderName) const { Q_ASSERT(QObject::thread() == QThread::currentThread()); - for (auto& plugin : std::as_const(mPlugIns)) + for (auto& plugin : std::as_const(mPlugins)) { const auto& readerList = plugin->getReaders(); for (Reader* reader : readerList) @@ -246,7 +247,7 @@ Reader* ReaderManagerWorker::getReader(const QString& pReaderName) const } -void ReaderManagerWorker::createCardConnectionWorker(const QString& pReaderName) +void ReaderManagerWorker::createCardConnectionWorker(const QString& pReaderName, const std::function(const QSharedPointer&)>& pInitWorker) { Q_ASSERT(QObject::thread() == QThread::currentThread()); @@ -254,6 +255,10 @@ void ReaderManagerWorker::createCardConnectionWorker(const QString& pReaderName) if (auto reader = getReader(pReaderName)) { worker = reader->createCardConnectionWorker(); + if (pInitWorker) + { + worker = pInitWorker(worker); + } } Q_EMIT fireCardConnectionWorkerCreated(worker); } diff --git a/src/card/base/ReaderManagerWorker.h b/src/card/base/ReaderManagerWorker.h index 9bedc08a0..1c4800579 100644 --- a/src/card/base/ReaderManagerWorker.h +++ b/src/card/base/ReaderManagerWorker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,8 +10,8 @@ #include "CardConnectionWorker.h" #include "ReaderInfo.h" -#include "ReaderManagerPlugIn.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPlugin.h" +#include "ReaderManagerPluginInfo.h" #include @@ -23,12 +23,12 @@ class ReaderManagerWorker Q_OBJECT private: - QVector mPlugIns; + QList mPlugins; - void callOnPlugIn(ReaderManagerPlugInType pType, const std::function& pFunc, const char* pLog); - void registerPlugIns(); - [[nodiscard]] static bool isPlugIn(const QJsonObject& pJson); - void registerPlugIn(ReaderManagerPlugIn* pPlugIn); + void callOnPlugin(ReaderManagerPluginType pType, const std::function& pFunc, const char* pLog); + void registerPlugins(); + [[nodiscard]] static bool isPlugin(const QJsonObject& pJson); + void registerPlugin(ReaderManagerPlugin* pPlugin); [[nodiscard]] Reader* getReader(const QString& pReaderName) const; public: @@ -37,19 +37,19 @@ class ReaderManagerWorker Q_INVOKABLE void shutdown(); - Q_INVOKABLE void reset(ReaderManagerPlugInType pType); + Q_INVOKABLE void reset(ReaderManagerPluginType pType); Q_INVOKABLE void insert(const ReaderInfo& pReaderInfo, const QVariant& pData); Q_INVOKABLE void shelve(); - Q_INVOKABLE void startScan(ReaderManagerPlugInType pType, bool pAutoConnect); - Q_INVOKABLE void stopScan(ReaderManagerPlugInType pType, const QString& pError); + Q_INVOKABLE void startScan(ReaderManagerPluginType pType, bool pAutoConnect); + Q_INVOKABLE void stopScan(ReaderManagerPluginType pType, const QString& pError); - [[nodiscard]] Q_INVOKABLE QVector getReaderInfos() const; + [[nodiscard]] Q_INVOKABLE QList getReaderInfos() const; Q_INVOKABLE void updateReaderInfo(const QString& pReaderName); - Q_INVOKABLE void createCardConnectionWorker(const QString& pReaderName); + void createCardConnectionWorker(const QString& pReaderName, const std::function(const QSharedPointer&)>& pInitWorker); Q_SIGNALS: - void firePluginAdded(const ReaderManagerPlugInInfo& pInfo); - void fireStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void firePluginAdded(const ReaderManagerPluginInfo& pInfo); + void fireStatusChanged(const ReaderManagerPluginInfo& pInfo); void fireReaderAdded(const ReaderInfo& pInfo); void fireReaderRemoved(const ReaderInfo& pInfo); void fireReaderPropertiesUpdated(const ReaderInfo& pInfo); diff --git a/src/card/base/SecurityProtocol.cpp b/src/card/base/SecurityProtocol.cpp index 256bd58bb..413050325 100644 --- a/src/card/base/SecurityProtocol.cpp +++ b/src/card/base/SecurityProtocol.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ @@ -8,6 +8,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -72,6 +73,12 @@ const QMap> SecurityProtocol: }; +void SecurityProtocol::logCritical(const QLatin1String& pTopic) const +{ + qCCritical(card) << pTopic << "OID:" << mOid; +} + + SecurityProtocol::SecurityProtocol(const Oid& pOid) : mOid(pOid) , mProtocol(ProtocolType::UNDEFINED) @@ -81,17 +88,17 @@ SecurityProtocol::SecurityProtocol(const Oid& pOid) , mSignature(SignatureType::UNDEFINED) , mHashAlgorithm(std::nullopt) { - const QByteArray rawOid = mOid.getData(); - if (rawOid.size() < 8 || !rawOid.startsWith(Oid(KnownOid::BSI_DE_PROTOCOLS_SMARTCARD).getData())) + const QByteArray rawOid(mOid); + if (rawOid.size() < 8 || !rawOid.startsWith(QByteArray(Oid(KnownOid::BSI_DE_PROTOCOLS_SMARTCARD)))) { - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); return; } mProtocol = cProtocol.value(rawOid.at(7), ProtocolType::UNDEFINED); if (mProtocol == ProtocolType::UNDEFINED) { - qCCritical(card) << "Unsupported OID:" << mOid; + logCritical("Unsupported"_L1); return; } @@ -110,7 +117,7 @@ SecurityProtocol::SecurityProtocol(const Oid& pOid) mSignature = cSignature.value(keyAgreement, SignatureType::UNDEFINED); if (mSignature == SignatureType::UNDEFINED) { - qCCritical(card) << "Unsupported OID:" << mOid; + logCritical("Unsupported"_L1); return; } if (mSignature == SignatureType::RSA) @@ -123,7 +130,7 @@ SecurityProtocol::SecurityProtocol(const Oid& pOid) mHashAlgorithm = hashBase->value(algorithm, std::nullopt); if (!mHashAlgorithm.has_value()) { - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); } return; @@ -131,7 +138,7 @@ SecurityProtocol::SecurityProtocol(const Oid& pOid) mMapping = cMapping.value(keyAgreement, MappingType::UNDEFINED); if (mMapping == MappingType::UNDEFINED) { - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); return; } Q_FALLTHROUGH(); @@ -140,19 +147,19 @@ SecurityProtocol::SecurityProtocol(const Oid& pOid) mKeyAgreement = cKeyAgreement.value(keyAgreement, KeyAgreementType::UNDEFINED); if (mKeyAgreement == KeyAgreementType::UNDEFINED) { - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); return; } mCipher = cCipher.value(algorithm, CipherType::UNDEFINED); if (mCipher == CipherType::UNDEFINED) { - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); return; } break; default: - qCCritical(card) << "Unknown OID:" << mOid; + logCritical("Unknown"_L1); } } diff --git a/src/card/base/SecurityProtocol.h b/src/card/base/SecurityProtocol.h index 3948c1b83..94df36fc0 100644 --- a/src/card/base/SecurityProtocol.h +++ b/src/card/base/SecurityProtocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -44,6 +44,8 @@ class SecurityProtocol SignatureType mSignature; std::optional mHashAlgorithm; + void logCritical(const QLatin1String& pTopic) const; + public: explicit SecurityProtocol(const Oid& pOid); diff --git a/src/card/base/SmartCardDefinitions.cpp b/src/card/base/SmartCardDefinitions.cpp index b44c81fb0..9c127b841 100644 --- a/src/card/base/SmartCardDefinitions.cpp +++ b/src/card/base/SmartCardDefinitions.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartCardDefinitions.h" diff --git a/src/card/base/SmartCardDefinitions.h b/src/card/base/SmartCardDefinitions.h index 09817bc7a..53a7fbc16 100644 --- a/src/card/base/SmartCardDefinitions.h +++ b/src/card/base/SmartCardDefinitions.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/base/apdu/CommandApdu.cpp b/src/card/base/apdu/CommandApdu.cpp index 24b3e56dd..b2deed692 100644 --- a/src/card/base/apdu/CommandApdu.cpp +++ b/src/card/base/apdu/CommandApdu.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CommandApdu.h" @@ -249,6 +249,19 @@ bool CommandApdu::isExtendedLength() const } +QByteArray CommandApdu::generateLengthField(int pLength) const +{ + QByteArray field; + if (isExtendedLength()) + { + field += static_cast(pLength >> 8 & 0xFF); + } + field += static_cast(pLength & 0xFF); + + return field; +} + + CommandApdu::operator QByteArray() const { if (mData.size() > EXTENDED_MAX_LC || mLe > EXTENDED_MAX_LE) @@ -259,33 +272,20 @@ CommandApdu::operator QByteArray() const QByteArray cmd = getHeaderBytes(); // According to ISO-7816-4, 5.2 Syntax - if (mData.size() > 0) + if (isExtendedLength()) { - if (CommandApdu::isExtendedLength(mData, mLe)) - { - cmd += '\0'; - cmd += static_cast(mData.size() >> 8 & 0xFF); - cmd += static_cast(mData.size() & 0xFF); - } - else - { - cmd += static_cast(mData.size() & 0xFF); - } + cmd += '\0'; + } + if (mData.size() > 0) + { + cmd += generateLengthField(static_cast(mData.size())); cmd += mData; } if (mLe > 0) { - if (CommandApdu::isExtendedLength(mData, mLe)) - { - if (mData.isEmpty()) - { - cmd += '\0'; - } - cmd += static_cast(mLe >> 8 & 0xFF); - } - cmd += static_cast(mLe & 0xFF); + cmd += generateLengthField(mLe); } return cmd; diff --git a/src/card/base/apdu/CommandApdu.h b/src/card/base/apdu/CommandApdu.h index 7f4d69a6a..707fef3e6 100644 --- a/src/card/base/apdu/CommandApdu.h +++ b/src/card/base/apdu/CommandApdu.h @@ -1,10 +1,11 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "EnumHelper.h" +#include "LogPrivacy.h" #include #include @@ -50,7 +51,7 @@ class CommandApdu UNBLOCK = 0x03, PIN = 0x03, CHIP_AUTHENTICATION = 0x41, - VERIFICATION = 0x81, + TERMINAL_AUTHENTICATION = 0x81, AUTHENTICATION_TEMPLATE = 0xA4, DIGITAL_SIGNATURE_TEMPLATE = 0xB6, SELF_DESCRIPTIVE = 0xBE, @@ -87,15 +88,14 @@ class CommandApdu [[nodiscard]] int getLe() const; [[nodiscard]] bool isExtendedLength() const; + [[nodiscard]] QByteArray generateLengthField(int pLength) const; operator QByteArray() const; }; inline QDebug operator<<(QDebug pDbg, const CommandApdu& pCommandApdu) { - QDebugStateSaver saver(pDbg); - pDbg << QByteArray(pCommandApdu).toHex(); - return pDbg; + return privacy::logApdu(pDbg, pCommandApdu); } diff --git a/src/card/base/apdu/FileCommand.cpp b/src/card/base/apdu/FileCommand.cpp index 9f7c80ce3..acde2ae06 100644 --- a/src/card/base/apdu/FileCommand.cpp +++ b/src/card/base/apdu/FileCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "FileCommand.h" diff --git a/src/card/base/apdu/FileCommand.h b/src/card/base/apdu/FileCommand.h index 98f7381e2..cc39438b1 100644 --- a/src/card/base/apdu/FileCommand.h +++ b/src/card/base/apdu/FileCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/base/apdu/GeneralAuthenticateResponse.cpp b/src/card/base/apdu/GeneralAuthenticateResponse.cpp index f3387601d..4308f5e9b 100644 --- a/src/card/base/apdu/GeneralAuthenticateResponse.cpp +++ b/src/card/base/apdu/GeneralAuthenticateResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "GeneralAuthenticateResponse.h" diff --git a/src/card/base/apdu/GeneralAuthenticateResponse.h b/src/card/base/apdu/GeneralAuthenticateResponse.h index e8c6955f3..50742ed48 100644 --- a/src/card/base/apdu/GeneralAuthenticateResponse.h +++ b/src/card/base/apdu/GeneralAuthenticateResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/apdu/PacePinStatus.cpp b/src/card/base/apdu/PacePinStatus.cpp index 167be6f54..796d5cad2 100644 --- a/src/card/base/apdu/PacePinStatus.cpp +++ b/src/card/base/apdu/PacePinStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "PacePinStatus.h" diff --git a/src/card/base/apdu/PacePinStatus.h b/src/card/base/apdu/PacePinStatus.h index 6c24cc867..3d933e19f 100644 --- a/src/card/base/apdu/PacePinStatus.h +++ b/src/card/base/apdu/PacePinStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/base/apdu/ResponseApdu.cpp b/src/card/base/apdu/ResponseApdu.cpp index 70de2e5a2..44d7e53f3 100644 --- a/src/card/base/apdu/ResponseApdu.cpp +++ b/src/card/base/apdu/ResponseApdu.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ResponseApdu.h" diff --git a/src/card/base/apdu/ResponseApdu.h b/src/card/base/apdu/ResponseApdu.h index 3314bff50..0d73dfbb8 100644 --- a/src/card/base/apdu/ResponseApdu.h +++ b/src/card/base/apdu/ResponseApdu.h @@ -1,11 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "CardReturnCode.h" #include "EnumHelper.h" +#include "LogPrivacy.h" namespace governikus @@ -36,6 +37,7 @@ defineTypedEnumType(StatusCode, quint16, NO_CURRENT_DIRECTORY_SELECTED = 0x6986, DATAFIELD_EXPECTED = 0x6987, INVALID_SM_OBJECTS = 0x6988, + SW_APPLET_SELECT_FAILED = 0x6999, COMMAND_NOT_ALLOWED = 0x69F0, INVALID_DATAFIELD = 0x6A80, ALGORITHM_ID = 0x6A81, @@ -102,9 +104,7 @@ class ResponseApdu final inline QDebug operator<<(QDebug pDbg, const ResponseApdu& pResponseApdu) { - QDebugStateSaver saver(pDbg); - pDbg << QByteArray(pResponseApdu).toHex(); - return pDbg; + return privacy::logApdu(pDbg, pResponseApdu); } diff --git a/src/card/base/apdu/SecureMessagingApdu.cpp b/src/card/base/apdu/SecureMessagingApdu.cpp index 035f82510..20e6c991f 100644 --- a/src/card/base/apdu/SecureMessagingApdu.cpp +++ b/src/card/base/apdu/SecureMessagingApdu.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SecureMessagingApdu.h" diff --git a/src/card/base/apdu/SecureMessagingApdu.h b/src/card/base/apdu/SecureMessagingApdu.h index 73f4b584f..dbc5653db 100644 --- a/src/card/base/apdu/SecureMessagingApdu.h +++ b/src/card/base/apdu/SecureMessagingApdu.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/apdu/SecureMessagingCommand.cpp b/src/card/base/apdu/SecureMessagingCommand.cpp index db64d8fc9..102c472f3 100644 --- a/src/card/base/apdu/SecureMessagingCommand.cpp +++ b/src/card/base/apdu/SecureMessagingCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SecureMessagingCommand.h" diff --git a/src/card/base/apdu/SecureMessagingCommand.h b/src/card/base/apdu/SecureMessagingCommand.h index 2757f9227..3152090ee 100644 --- a/src/card/base/apdu/SecureMessagingCommand.h +++ b/src/card/base/apdu/SecureMessagingCommand.h @@ -1,16 +1,17 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Command APDU for SecureMessaging + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once + #include "CommandApdu.h" #include "SecureMessagingApdu.h" + +class test_SecureMessaging; + + namespace governikus { @@ -22,6 +23,7 @@ class SecureMessagingCommand : public SecureMessagingApdu { Q_DISABLE_COPY(SecureMessagingCommand) + friend class ::test_SecureMessaging; private: QSharedPointer mExpectedLength; diff --git a/src/card/base/apdu/SecureMessagingResponse.cpp b/src/card/base/apdu/SecureMessagingResponse.cpp index 90858eaeb..0b5726c69 100644 --- a/src/card/base/apdu/SecureMessagingResponse.cpp +++ b/src/card/base/apdu/SecureMessagingResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "SecureMessagingResponse.h" diff --git a/src/card/base/apdu/SecureMessagingResponse.h b/src/card/base/apdu/SecureMessagingResponse.h index 2188ee12e..54ef9803a 100644 --- a/src/card/base/apdu/SecureMessagingResponse.h +++ b/src/card/base/apdu/SecureMessagingResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/apdu/SecureMessagingTypes.cpp b/src/card/base/apdu/SecureMessagingTypes.cpp index a7ffdbadd..c36d31035 100644 --- a/src/card/base/apdu/SecureMessagingTypes.cpp +++ b/src/card/base/apdu/SecureMessagingTypes.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "SecureMessagingTypes.h" diff --git a/src/card/base/apdu/SecureMessagingTypes.h b/src/card/base/apdu/SecureMessagingTypes.h index 09d4462d6..d6fc59bc4 100644 --- a/src/card/base/apdu/SecureMessagingTypes.h +++ b/src/card/base/apdu/SecureMessagingTypes.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/apdu/CommandData.cpp b/src/card/base/asn1/ASN1Struct.cpp similarity index 56% rename from src/card/base/apdu/CommandData.cpp rename to src/card/base/asn1/ASN1Struct.cpp index 9e02d755d..73c061a99 100644 --- a/src/card/base/apdu/CommandData.cpp +++ b/src/card/base/asn1/ASN1Struct.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ -#include "CommandData.h" +#include "ASN1Struct.h" #include "asn1/ASN1TemplateUtil.h" #include "asn1/ASN1Util.h" @@ -10,13 +10,14 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card) -CommandData::CommandData(int pClass, DATA_TAG pTag, const QByteArray& pData) +ASN1Struct::ASN1Struct(int pClass, DATA_TAG pTag, const QByteArray& pData) : mClass(pClass) , mTag(pTag) , mSimpleData(pData) @@ -25,7 +26,7 @@ CommandData::CommandData(int pClass, DATA_TAG pTag, const QByteArray& pData) } -CommandData::CommandData(const QByteArray& pData) +ASN1Struct::ASN1Struct(const QByteArray& pData) : mClass(V_ASN1_UNIVERSAL) , mTag(NONE) , mSimpleData() @@ -41,7 +42,7 @@ CommandData::CommandData(const QByteArray& pData) const auto result = ASN1_get_object(&p, &size, &tagNumber, &tagClass, static_cast(data.length())); if (result & 0x80) { - qCritical() << "Could not parse CommandData:" << getOpenSslError(); + qCritical() << "Could not parse ASN1Struct:" << getOpenSslError(); return; } @@ -49,13 +50,13 @@ CommandData::CommandData(const QByteArray& pData) const auto objectSize = ASN1_object_size(false, dataSize, tagNumber); if (data.size() < objectSize) { - qCritical() << "Unexpected end of CommandData"; + qCritical() << "Unexpected end of ASN1Struct"; return; } if (mTag != NONE || data.size() > objectSize || !mComplexData.isEmpty()) { - mComplexData += CommandData(data.mid(0, objectSize)); + mComplexData += ASN1Struct(data.mid(0, objectSize)); data.remove(0, objectSize); continue; } @@ -74,7 +75,7 @@ CommandData::CommandData(const QByteArray& pData) } -QByteArray CommandData::getData(int pClass, DATA_TAG pTag) const +QByteArray ASN1Struct::getData(int pClass, DATA_TAG pTag) const { if (mClass == pClass && mTag == pTag && !mSimpleData.isNull()) { @@ -94,7 +95,7 @@ QByteArray CommandData::getData(int pClass, DATA_TAG pTag) const } -QByteArray CommandData::getObject(int pClass, DATA_TAG pTag) const +QByteArray ASN1Struct::getObject(int pClass, DATA_TAG pTag) const { if (mClass == pClass && mTag == pTag) { @@ -114,13 +115,13 @@ QByteArray CommandData::getObject(int pClass, DATA_TAG pTag) const } -void CommandData::append(const QByteArray& pData) +void ASN1Struct::append(const QByteArray& pData) { - mComplexData += CommandData(pData); + mComplexData += ASN1Struct(pData); } -void CommandData::append(DATA_TAG pTag, int pValue) +void ASN1Struct::append(DATA_TAG pTag, int pValue) { QSharedPointer type(ASN1_TYPE_new(), [](ASN1_TYPE* pType){ASN1_TYPE_free(pType);}); type->type = V_ASN1_INTEGER; @@ -129,30 +130,30 @@ void CommandData::append(DATA_TAG pTag, int pValue) { qCCritical(card) << "Encoding error on ASN1_INTEGER"; } - CommandData integer(Asn1TypeUtil::encode(type.data())); - append(pTag, integer.getData(V_ASN1_UNIVERSAL, INTEGER)); + ASN1Struct integer(Asn1TypeUtil::encode(type.data())); + append(pTag, integer.getData(V_ASN1_UNIVERSAL, UNI_INTEGER)); } -void CommandData::append(DATA_TAG pTag, const Oid& pOid) +void ASN1Struct::append(DATA_TAG pTag, const Oid& pOid) { - append(pTag, pOid.getData()); + append(pTag, QByteArray(pOid)); } -void CommandData::append(DATA_TAG pTag, PacePasswordId pPassword) +void ASN1Struct::append(DATA_TAG pTag, PacePasswordId pPassword) { append(pTag, QByteArray(1, Enum::getValue(pPassword))); } -void CommandData::append(DATA_TAG pTag, const QByteArray& pData) +void ASN1Struct::append(DATA_TAG pTag, const QByteArray& pData) { - mComplexData += CommandData(V_ASN1_CONTEXT_SPECIFIC, pTag, pData); + mComplexData += ASN1Struct(V_ASN1_CONTEXT_SPECIFIC, pTag, pData); } -CommandData::operator QByteArray() const +ASN1Struct::operator QByteArray() const { if (mSimpleData.isNull()) { @@ -175,7 +176,7 @@ CommandData::operator QByteArray() const #ifndef QT_NO_DEBUG -int CommandData::getObjectCount() const +int ASN1Struct::getObjectCount() const { int counter = 1; for (const auto& entry : std::as_const(mComplexData)) @@ -186,4 +187,46 @@ int CommandData::getObjectCount() const } +void ASN1Struct::print(QDebug pDbg, int pLevel) const +{ + static const QMap classNames({ + {0x00, "UNIVERSAL"_L1}, + {0x40, "APPLICATION"_L1}, + {0x80, "CONTEXT_SPECIFIC"_L1}, + {0xc0, "PRIVATE"_L1} + }); + + pDbg << '\n' << QString(4 * pLevel, ' '_L1) << '[' << classNames.value(mClass, "UNKNOWN"_L1) << ' ' << mTag << ']'; + if (!mSimpleData.isNull()) + { + pDbg << ' ' << mSimpleData.toHex(); + return; + } + + for (const auto& child : std::as_const(mComplexData)) + { + child.print(pDbg, pLevel + 1); + } +} + + #endif + + +namespace governikus +{ + +QDebug operator<<(QDebug pDbg, const ASN1Struct& pASN1Struct) +{ + QDebugStateSaver saver(pDbg); +#ifndef QT_NO_DEBUG + pDbg.noquote().nospace() << "ASN1Struct:"; + pASN1Struct.print(pDbg, 0); +#else + pDbg.noquote() << QByteArray(pASN1Struct).toHex(); +#endif + return pDbg; +} + + +} // namespace governikus diff --git a/src/card/base/apdu/CommandData.h b/src/card/base/asn1/ASN1Struct.h similarity index 59% rename from src/card/base/apdu/CommandData.h rename to src/card/base/asn1/ASN1Struct.h index a78cadf01..4dbf8a36c 100644 --- a/src/card/base/apdu/CommandData.h +++ b/src/card/base/asn1/ASN1Struct.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -8,46 +8,59 @@ #include "asn1/Oid.h" #include -#include +#include #include namespace governikus { -class CommandData +class ASN1Struct { public: - // According to TR-03110-3, chapter B.(1|2|3) and B.14.* enum DATA_TAG : int { NONE = -1, + + // According to TR-03110-3, chapter B.(1|2|3), B.14.* and C3.2 + CERTIFICATE_EXTENSION_CONTENT_0 = 0, CRYPTOGRAPHIC_MECHANISM_REFERENCE = 0, CA_EPHEMERAL_PUBLIC_KEY = 0, MAPPING_DATA = 1, - INTEGER = 2, + RI_FIRST_IDENTIFIER = 1, PACE_EPHEMERAL_PUBLIC_KEY = 3, PUBLIC_KEY_REFERENCE = 3, PRIVATE_KEY_REFERENCE = 4, AUTHENTICATION_TOKEN = 5, - RI_EPHEMERAL_PUBLIC_KEY = 6, + EC_PUBLIC_POINT = 6, AUXILIARY_AUTHENTICATED_DATA = 7, TA_EPHEMERAL_PUBLIC_KEY = 17, DYNAMIC_AUTHENTICATION_DATA = 28, CERTIFICATE_SIGNATURE = 55, + PUBLIC_KEY = 73, CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE = 76, - CERTIFICATE_BODY = 78 + CERTIFICATE_BODY = 78, + + // According to ASN.1 + UNI_BOOLEAN = 1, + UNI_INTEGER = 2, + UNI_BITSTRING = 3, + UNI_OCTETSTRING = 4, + UNI_NULL = 5, + UNI_OBJECT_IDENTIFIER = 6, + UNI_SEQUENCE = 16, + UNI_SET = 17 }; private: int mClass; int mTag; QByteArray mSimpleData; - QVector mComplexData; + QList mComplexData; public: - explicit CommandData(int pClass = V_ASN1_UNIVERSAL, DATA_TAG pTag = NONE, const QByteArray& pData = QByteArray()); - explicit CommandData(const QByteArray& pData); + explicit ASN1Struct(int pClass = V_ASN1_UNIVERSAL, DATA_TAG pTag = NONE, const QByteArray& pData = QByteArray()); + explicit ASN1Struct(const QByteArray& pData); [[nodiscard]] QByteArray getData(int pClass, DATA_TAG pTag) const; [[nodiscard]] QByteArray getObject(int pClass, DATA_TAG pTag) const; @@ -62,7 +75,10 @@ class CommandData #ifndef QT_NO_DEBUG int getObjectCount() const; + void print(QDebug pDbg, int pLevel) const; #endif }; +QDebug operator<<(QDebug pDbg, const ASN1Struct& pASN1Struct); + } // namespace governikus diff --git a/src/card/base/asn1/ASN1TemplateUtil.cpp b/src/card/base/asn1/ASN1TemplateUtil.cpp index ff1c7dff4..be169d890 100644 --- a/src/card/base/asn1/ASN1TemplateUtil.cpp +++ b/src/card/base/asn1/ASN1TemplateUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "ASN1TemplateUtil.h" diff --git a/src/card/base/asn1/ASN1TemplateUtil.h b/src/card/base/asn1/ASN1TemplateUtil.h index eba6f3f8e..73244d395 100644 --- a/src/card/base/asn1/ASN1TemplateUtil.h +++ b/src/card/base/asn1/ASN1TemplateUtil.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -114,11 +114,10 @@ template QSharedPointer decodeObject(const QByteArray& pData, bool pLogging = true) { ERR_clear_error(); - const char* tmp = pData.constData(); - const auto** dataPointer = reinterpret_cast(&tmp); T* object = nullptr; - if (!decodeAsn1Object(&object, dataPointer, static_cast(pData.length())) && pLogging) + const auto* dataPointer = reinterpret_cast(pData.constData()); + if (!decodeAsn1Object(&object, &dataPointer, static_cast(pData.length())) && pLogging) { qCWarning(card) << "Cannot decode ASN.1 object:" << getOpenSslError(); } diff --git a/src/card/base/asn1/ASN1Util.cpp b/src/card/base/asn1/ASN1Util.cpp index bf2fc676a..61a757378 100644 --- a/src/card/base/asn1/ASN1Util.cpp +++ b/src/card/base/asn1/ASN1Util.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "asn1/ASN1Util.h" diff --git a/src/card/base/asn1/ASN1Util.h b/src/card/base/asn1/ASN1Util.h index bb8225c22..c6b96dba4 100644 --- a/src/card/base/asn1/ASN1Util.h +++ b/src/card/base/asn1/ASN1Util.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/AccessRoleAndRight.cpp b/src/card/base/asn1/AccessRoleAndRight.cpp index 1e4ddebe6..ad11147d8 100644 --- a/src/card/base/asn1/AccessRoleAndRight.cpp +++ b/src/card/base/asn1/AccessRoleAndRight.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "AccessRoleAndRight.h" @@ -61,12 +61,12 @@ const QList& AccessRoleAndRightsUtil::allRights() mAllRights += AccessRight::WRITE_DG19; mAllRights += AccessRight::WRITE_DG20; mAllRights += AccessRight::WRITE_DG21; + mAllRights += AccessRight::WRITE_DG22; - mAllRights += AccessRight::RFU_32; - mAllRights += AccessRight::RFU_31; - mAllRights += AccessRight::RFU_30; - mAllRights += AccessRight::RFU_29; + mAllRights += AccessRight::RFU; + mAllRights += AccessRight::PSA; + mAllRights += AccessRight::READ_DG22; mAllRights += AccessRight::READ_DG21; mAllRights += AccessRight::READ_DG20; mAllRights += AccessRight::READ_DG19; @@ -126,6 +126,8 @@ QString AccessRoleAndRightsUtil::toDisplayText(AccessRight pRight) { switch (pRight) { + case AccessRight::READ_DG22: + case AccessRight::WRITE_DG22: case AccessRight::READ_DG21: case AccessRight::WRITE_DG21: //: LABEL ALL_PLATFORMS @@ -236,6 +238,7 @@ QString AccessRoleAndRightsUtil::toDisplayText(AccessRight pRight) //: LABEL ALL_PLATFORMS return tr("Privileged terminal"); + case AccessRight::PSA: case AccessRight::RESTRICTED_IDENTIFICATION: //: LABEL ALL_PLATFORMS return tr("Pseudonym"); @@ -248,11 +251,7 @@ QString AccessRoleAndRightsUtil::toDisplayText(AccessRight pRight) //: LABEL ALL_PLATFORMS return tr("Age verification"); - /* 32-29: reserved for future use */ - case AccessRight::RFU_29: - case AccessRight::RFU_30: - case AccessRight::RFU_31: - case AccessRight::RFU_32: + case AccessRight::RFU: //: LABEL ALL_PLATFORMS return tr("Unknown (reserved)"); } diff --git a/src/card/base/asn1/AccessRoleAndRight.h b/src/card/base/asn1/AccessRoleAndRight.h index 185d1ce1b..10f80c8c9 100644 --- a/src/card/base/asn1/AccessRoleAndRight.h +++ b/src/card/base/asn1/AccessRoleAndRight.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -30,10 +30,10 @@ defineTypedEnumType(AccessRight, uint, WRITE_DG19 = 35, WRITE_DG20 = 34, WRITE_DG21 = 33, - RFU_32 = 32, /* Reserved for Future Use */ - RFU_31 = 31, /* Reserved for Future Use */ - RFU_30 = 30, /* Reserved for Future Use */ - RFU_29 = 29, /* Reserved for Future Use */ + WRITE_DG22 = 32, + RFU = 31, + PSA = 30, + READ_DG22 = 29, READ_DG21 = 28, READ_DG20 = 27, READ_DG19 = 26, @@ -97,11 +97,6 @@ defineTypedEnumType(AccessRightNames, std::underlying_type_t, ) #undef TYPE -[[nodiscard]] inline uint qHash(governikus::AccessRight pAccessRight) -{ - return static_cast(pAccessRight); -} - defineEnumType(AccessRole, CVCA = 3, DV_od = 2, DV_no_f = 1, AT = 0, UNKNOWN = -1 diff --git a/src/card/base/asn1/ApplicationTemplate.cpp b/src/card/base/asn1/ApplicationTemplate.cpp index 2f739feb2..f5f268380 100644 --- a/src/card/base/asn1/ApplicationTemplate.cpp +++ b/src/card/base/asn1/ApplicationTemplate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationTemplate.h" @@ -47,12 +47,6 @@ IMPLEMENT_ASN1_OBJECT(ApplicationTemplate) } // namespace governikus -ApplicationTemplate::application_template_st(const ApplicationTemplate& pCopy) - : mApplicationIdentifier(pCopy.mApplicationIdentifier) -{ -} - - ApplicationTemplate::~application_template_st() { /* diff --git a/src/card/base/asn1/ApplicationTemplate.h b/src/card/base/asn1/ApplicationTemplate.h index 853a78a3e..99b146080 100644 --- a/src/card/base/asn1/ApplicationTemplate.h +++ b/src/card/base/asn1/ApplicationTemplate.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -45,8 +45,7 @@ using ApplicationTemplate = struct application_template_st static QSharedPointer decode(const QByteArray& pBytes); - application_template_st(const application_template_st& pCopy); - application_template_st& operator=(const application_template_st&) = delete; + Q_DISABLE_COPY(application_template_st) ~application_template_st(); /** diff --git a/src/card/base/asn1/ApplicationTemplates.cpp b/src/card/base/asn1/ApplicationTemplates.cpp index e2cd3231b..c6d9eed66 100644 --- a/src/card/base/asn1/ApplicationTemplates.cpp +++ b/src/card/base/asn1/ApplicationTemplates.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationTemplates.h" #include "ASN1TemplateUtil.h" #include "ASN1Util.h" +#include "asn1/ASN1Struct.h" #include #include @@ -31,7 +32,7 @@ IMPLEMENT_ASN1_OBJECT(ApplicationTemplatesInternal) QSharedPointer ApplicationTemplates::decode(const QByteArray& pBytes) { // Add "SET OF" class/tag and add length, as they are not part of the card data structure. - const QByteArray setBytes = Asn1Util::encode(V_ASN1_UNIVERSAL, 17, pBytes, true); + const QByteArray setBytes = Asn1Util::encode(V_ASN1_UNIVERSAL, ASN1Struct::UNI_SET, pBytes, true); auto applicationTemplatesStruct = decodeObject(setBytes); if (applicationTemplatesStruct == nullptr) @@ -39,7 +40,7 @@ QSharedPointer ApplicationTemplates::decode(const QByteArr return QSharedPointer(); } - QVector> applicationTemplates; + QList> applicationTemplates; for (int i = 0; i < sk_ApplicationTemplate_num(applicationTemplatesStruct.data()); ++i) { ApplicationTemplate* applicationTemplateStruct = sk_ApplicationTemplate_value(applicationTemplatesStruct.data(), i); @@ -63,7 +64,7 @@ QSharedPointer ApplicationTemplates::decode(const QByteArr ApplicationTemplates::ApplicationTemplates(const QByteArray& pBytes, - const QVector>& pApplicationTemplates) + const QList>& pApplicationTemplates) : mContentBytes(pBytes) , mApplicationTemplates(pApplicationTemplates) { @@ -76,13 +77,13 @@ const QByteArray& ApplicationTemplates::getContentBytes() const } -const QVector>& ApplicationTemplates::getApplicationTemplates() const +const QList>& ApplicationTemplates::getApplicationTemplates() const { return mApplicationTemplates; } -bool ApplicationTemplates::contains(const QByteArray& pIdentifier) +bool ApplicationTemplates::contains(const QByteArray& pIdentifier) const { return std::any_of(mApplicationTemplates.constBegin(), mApplicationTemplates.constEnd(), [pIdentifier](const auto& entry) { diff --git a/src/card/base/asn1/ApplicationTemplates.h b/src/card/base/asn1/ApplicationTemplates.h index 17238e969..73c649821 100644 --- a/src/card/base/asn1/ApplicationTemplates.h +++ b/src/card/base/asn1/ApplicationTemplates.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,8 +12,8 @@ #include "ApplicationTemplate.h" #include +#include #include -#include namespace governikus @@ -36,20 +36,20 @@ class ApplicationTemplates private: const QByteArray mContentBytes; - const QVector> mApplicationTemplates; + const QList> mApplicationTemplates; ApplicationTemplates(const QByteArray& pBytes, - const QVector>& pApplicationTemplates); + const QList>& pApplicationTemplates); static QByteArray buildAsn1LengthField(unsigned int pLength); public: static QSharedPointer decode(const QByteArray& pBytes); - bool contains(const QByteArray& pIdentifier); + bool contains(const QByteArray& pIdentifier) const; [[nodiscard]] const QByteArray& getContentBytes() const; - [[nodiscard]] const QVector>& getApplicationTemplates() const; + [[nodiscard]] const QList>& getApplicationTemplates() const; [[nodiscard]] qsizetype count() const; }; diff --git a/src/card/base/asn1/AuthenticatedAuxiliaryData.cpp b/src/card/base/asn1/AuthenticatedAuxiliaryData.cpp index c31fb53c4..c5edd5f05 100644 --- a/src/card/base/asn1/AuthenticatedAuxiliaryData.cpp +++ b/src/card/base/asn1/AuthenticatedAuxiliaryData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AuthenticatedAuxiliaryData.h" diff --git a/src/card/base/asn1/AuthenticatedAuxiliaryData.h b/src/card/base/asn1/AuthenticatedAuxiliaryData.h index 3939d2e53..4e1f36049 100644 --- a/src/card/base/asn1/AuthenticatedAuxiliaryData.h +++ b/src/card/base/asn1/AuthenticatedAuxiliaryData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/CVCertificate.cpp b/src/card/base/asn1/CVCertificate.cpp index ee88e504d..3f354b4a5 100644 --- a/src/card/base/asn1/CVCertificate.cpp +++ b/src/card/base/asn1/CVCertificate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CVCertificate.h" @@ -8,6 +8,7 @@ #include "ASN1Util.h" #include +#include Q_DECLARE_LOGGING_CATEGORY(card) @@ -78,9 +79,9 @@ int CVCertificate::decodeCallback(int pOperation, ASN1_VALUE** pVal, const ASN1_ } -QVector> CVCertificate::fromRaw(const QByteArrayList& pByteList) +QList> CVCertificate::fromRaw(const QByteArrayList& pByteList) { - QVector> cvcs; + QList> cvcs; for (const auto& data : pByteList) { if (const auto& cvc = CVCertificate::fromRaw(data)) @@ -98,16 +99,6 @@ QSharedPointer CVCertificate::fromRaw(const QByteArray& pBy } -#ifndef QT_NO_DEBUG -QSharedPointer CVCertificate::fromHex(const QByteArray& pBytes) -{ - return fromRaw(QByteArray::fromHex(pBytes)); -} - - -#endif - - QByteArray CVCertificate::encode() const { return encodeObject(this); @@ -198,10 +189,10 @@ QDebug operator<<(QDebug pDbg, const QSharedPointer& } -QDebug operator<<(QDebug pDbg, const QVector>& pCvcs) +QDebug operator<<(QDebug pDbg, const QList>& pCvcs) { QDebugStateSaver saver(pDbg); - pDbg.nospace() << "QVector("; + pDbg.nospace() << "QList("; for (const auto& cvc : pCvcs) { pDbg.nospace() << cvc << ","; diff --git a/src/card/base/asn1/CVCertificate.h b/src/card/base/asn1/CVCertificate.h index 6aee6d877..1939e77ce 100644 --- a/src/card/base/asn1/CVCertificate.h +++ b/src/card/base/asn1/CVCertificate.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -48,11 +48,8 @@ using CVCertificate = struct cvcertificate_st SIGNATURE* mSignature; ECDSA_SIG* mEcdsaSignature; - static QVector> fromRaw(const QByteArrayList& pByteList); + static QList> fromRaw(const QByteArrayList& pByteList); static QSharedPointer fromRaw(const QByteArray& pBytes); -#ifndef QT_NO_DEBUG - static QSharedPointer fromHex(const QByteArray& pBytes); -#endif [[nodiscard]] QByteArray encode() const; [[nodiscard]] const CVCertificateBody& getBody() const; @@ -89,4 +86,4 @@ inline bool operator!=(const CVCertificate& pLeft, const CVCertificate& pRight) QDebug operator<<(QDebug pDbg, const governikus::CVCertificate& pCvc); QDebug operator<<(QDebug pDbg, const QSharedPointer& pCvc); QDebug operator<<(QDebug pDbg, const QSharedPointer& pCvc); -QDebug operator<<(QDebug pDbg, const QVector>& pCvcs); +QDebug operator<<(QDebug pDbg, const QList>& pCvcs); diff --git a/src/card/base/asn1/CVCertificateBody.cpp b/src/card/base/asn1/CVCertificateBody.cpp index 8807642da..168a0b6e6 100644 --- a/src/card/base/asn1/CVCertificateBody.cpp +++ b/src/card/base/asn1/CVCertificateBody.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CVCertificateBody.h" #include "ASN1Util.h" #include "SecurityProtocol.h" +#include "asn1/ASN1Struct.h" #include @@ -23,54 +24,25 @@ ASN1_ITEM_TEMPLATE(CertificateProfileIdentifier) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x29, CertificateProfileIdentifier, ASN1_OCTET_STRING) ASN1_ITEM_TEMPLATE_END(CertificateProfileIdentifier) - -ASN1_SEQUENCE(CERTIFICATEEXTENSION_st) = { - - ASN1_SIMPLE(CERTIFICATEEXTENSION_st, mOid, ASN1_OBJECT), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject1, ASN1_OCTET_STRING, 0x00), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject2, ASN1_OCTET_STRING, 0x01), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject3, ASN1_OCTET_STRING, 0x02), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject4, ASN1_OCTET_STRING, 0x03), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject5, ASN1_OCTET_STRING, 0x04), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject6, ASN1_OCTET_STRING, 0x05), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject7, ASN1_OCTET_STRING, 0x06), - ASN1_IMP_OPT(CERTIFICATEEXTENSION_st, mObject8, ASN1_OCTET_STRING, 0x07) -} - - -ASN1_SEQUENCE_END(CERTIFICATEEXTENSION_st) - -IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEEXTENSION) - -ASN1_ITEM_TEMPLATE(CERTIFICATEEXTENSION) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x13, CERTIFICATEEXTENSION, CERTIFICATEEXTENSION_st) -ASN1_ITEM_TEMPLATE_END(CERTIFICATEEXTENSION) - - -ASN1_ITEM_TEMPLATE(CERTIFICATEEXTENSIONS) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x05, CERTIFICATEEXTENSIONS, CERTIFICATEEXTENSION) -ASN1_ITEM_TEMPLATE_END(CERTIFICATEEXTENSIONS) - +ASN1_ITEM_TEMPLATE(CAR) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x02, CAR, ASN1_OCTET_STRING) +ASN1_ITEM_TEMPLATE_END(CAR) ASN1_ITEM_TEMPLATE(CHR) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x20, CHR, ASN1_OCTET_STRING) ASN1_ITEM_TEMPLATE_END(CHR) - -ASN1_ITEM_TEMPLATE(CAR) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x02, CAR, ASN1_OCTET_STRING) -ASN1_ITEM_TEMPLATE_END(CAR) - +ASN1_ITEM_TEMPLATE(DATE_EFF) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x25, DATE, ASN1_OCTET_STRING) +ASN1_ITEM_TEMPLATE_END(DATE_EFF) ASN1_ITEM_TEMPLATE(DATE_EXPIRE) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x24, DATE, ASN1_OCTET_STRING) ASN1_ITEM_TEMPLATE_END(DATE_EXPIRE) - -ASN1_ITEM_TEMPLATE(DATE_EFF) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x25, DATE, ASN1_OCTET_STRING) -ASN1_ITEM_TEMPLATE_END(DATE_EFF) - +ASN1_ITEM_TEMPLATE(CERTIFICATEEXTENSIONS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_APPLICATION, 0x05, CERTIFICATEEXTENSIONS, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(CERTIFICATEEXTENSIONS) ASN1_SEQUENCE(certificateprofilebody_st) = { ASN1_SIMPLE(certificateprofilebody_st, mCertificateProfileIdentifier, CertificateProfileIdentifier), @@ -173,18 +145,22 @@ QCryptographicHash::Algorithm CVCertificateBody::getHashAlgorithm() const } -QHash CVCertificateBody::getExtensions() const +QByteArray CVCertificateBody::getExtension(const Oid& pOid) const { - QHash ext; - - if (mExtensions != nullptr) + if (mExtensions) { - for (int i = 0; i < sk_CERTIFICATEEXTENSION_num(mExtensions); i++) + for (int i = 0; i < sk_ASN1_TYPE_num(mExtensions); i++) { - const CERTIFICATEEXTENSION* extension = sk_CERTIFICATEEXTENSION_value(mExtensions, i); - ext.insert(Oid(extension->mOid), Asn1OctetStringUtil::getValue(extension->mObject1)); + const ASN1Struct extension(Asn1TypeUtil::encode(sk_ASN1_TYPE_value(mExtensions, i))); + if (Oid(extension.getData(V_ASN1_UNIVERSAL, ASN1Struct::UNI_OBJECT_IDENTIFIER)) == pOid) + { + // Currently we only return the first simple ASN.1 value found in the structure. The + // only known case where more information is given is ID_SECTOR_PS (BSI TR-03110-3 + // C.3.2.2). But this information is not used/requested by the eID-Client. + return extension.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::CERTIFICATE_EXTENSION_CONTENT_0); + } } } - return ext; + return QByteArray(); } diff --git a/src/card/base/asn1/CVCertificateBody.h b/src/card/base/asn1/CVCertificateBody.h index 6f64feb34..08b4d8f1f 100644 --- a/src/card/base/asn1/CVCertificateBody.h +++ b/src/card/base/asn1/CVCertificateBody.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -21,21 +21,6 @@ namespace governikus { -using CERTIFICATEEXTENSION = struct CERTIFICATEEXTENSION_st -{ - ASN1_OBJECT* mOid; - ASN1_OCTET_STRING* mObject1; - ASN1_OCTET_STRING* mObject2; - ASN1_OCTET_STRING* mObject3; - ASN1_OCTET_STRING* mObject4; - ASN1_OCTET_STRING* mObject5; - ASN1_OCTET_STRING* mObject6; - ASN1_OCTET_STRING* mObject7; - ASN1_OCTET_STRING* mObject8; -}; -DECLARE_ASN1_FUNCTIONS(CERTIFICATEEXTENSION) -DEFINE_STACK_OF(CERTIFICATEEXTENSION) - using CVCertificateBody = struct certificateprofilebody_st { ASN1_OCTET_STRING* mCertificateProfileIdentifier; @@ -45,7 +30,7 @@ using CVCertificateBody = struct certificateprofilebody_st CHAT* mChat; ASN1_OCTET_STRING* mEffectiveDate; ASN1_OCTET_STRING* mExpirationDate; - STACK_OF(CERTIFICATEEXTENSION) * mExtensions; + STACK_OF(ASN1_TYPE) * mExtensions; static QSharedPointer decode(const QByteArray& pBytes); QByteArray encode(); @@ -65,7 +50,7 @@ using CVCertificateBody = struct certificateprofilebody_st [[nodiscard]] QDate getCertificateEffectiveDate() const; [[nodiscard]] QCryptographicHash::Algorithm getHashAlgorithm() const; - [[nodiscard]] QHash getExtensions() const; + [[nodiscard]] QByteArray getExtension(const Oid& pOid) const; }; DECLARE_ASN1_FUNCTIONS(CVCertificateBody) diff --git a/src/card/base/asn1/CVCertificateChain.cpp b/src/card/base/asn1/CVCertificateChain.cpp index bd559a8fb..bf42c22fd 100644 --- a/src/card/base/asn1/CVCertificateChain.cpp +++ b/src/card/base/asn1/CVCertificateChain.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CVCertificateChain.h" @@ -9,13 +9,13 @@ using namespace governikus; CVCertificateChain::CVCertificateChain(bool pProductive) - : CVCertificateChain(QVector>(), pProductive) + : CVCertificateChain(QList>(), pProductive) { } -CVCertificateChain::CVCertificateChain(const QVector>& pCvcs, bool pProductive) - : QVector>(pCvcs) +CVCertificateChain::CVCertificateChain(const QList>& pCvcs, bool pProductive) + : QList>(pCvcs) , mProductive(pProductive) { if (!isValid()) diff --git a/src/card/base/asn1/CVCertificateChain.h b/src/card/base/asn1/CVCertificateChain.h index e98a2f155..990826c2d 100644 --- a/src/card/base/asn1/CVCertificateChain.h +++ b/src/card/base/asn1/CVCertificateChain.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,20 +14,20 @@ #include "CVCertificate.h" -#include +#include namespace governikus { class CVCertificateChain - : public QVector> + : public QList> { private: bool mProductive; public: explicit CVCertificateChain(bool pProductive = true); - explicit CVCertificateChain(const QVector>& pCvcs, bool pProductive); + explicit CVCertificateChain(const QList>& pCvcs, bool pProductive); /*! * Return the document verifier certificate. diff --git a/src/card/base/asn1/CVCertificateChainBuilder.cpp b/src/card/base/asn1/CVCertificateChainBuilder.cpp index 3c6548701..84657a5ce 100644 --- a/src/card/base/asn1/CVCertificateChainBuilder.cpp +++ b/src/card/base/asn1/CVCertificateChainBuilder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CVCertificateChainBuilder.h" @@ -20,13 +20,13 @@ bool CVCertificateChainBuilder::isChild(const QSharedPointer>(), &CVCertificateChainBuilder::isChild) + : ChainBuilder(QList>(), &CVCertificateChainBuilder::isChild) , mProductive(pProductive) { } -CVCertificateChainBuilder::CVCertificateChainBuilder(const QVector>& pCvcPool, bool pProductive) +CVCertificateChainBuilder::CVCertificateChainBuilder(const QList>& pCvcPool, bool pProductive) : ChainBuilder(pCvcPool, &CVCertificateChainBuilder::isChild) , mProductive(pProductive) { diff --git a/src/card/base/asn1/CVCertificateChainBuilder.h b/src/card/base/asn1/CVCertificateChainBuilder.h index 34ced642f..7c430a15d 100644 --- a/src/card/base/asn1/CVCertificateChainBuilder.h +++ b/src/card/base/asn1/CVCertificateChainBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -35,7 +35,7 @@ class CVCertificateChainBuilder /*! * Creates a new instance. All chains are build using the CVCs passed in as parameter. */ - explicit CVCertificateChainBuilder(const QVector>& pCvcPool, bool pProductive); + explicit CVCertificateChainBuilder(const QList>& pCvcPool, bool pProductive); /*! diff --git a/src/card/base/asn1/CertificateDescription.cpp b/src/card/base/asn1/CertificateDescription.cpp index c98e37d1d..193e1742b 100644 --- a/src/card/base/asn1/CertificateDescription.cpp +++ b/src/card/base/asn1/CertificateDescription.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CertificateDescription.h" diff --git a/src/card/base/asn1/CertificateDescription.h b/src/card/base/asn1/CertificateDescription.h index 7beb93c96..b6535e889 100644 --- a/src/card/base/asn1/CertificateDescription.h +++ b/src/card/base/asn1/CertificateDescription.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/ChainBuilder.h b/src/card/base/asn1/ChainBuilder.h index 240120068..2697bd1cd 100644 --- a/src/card/base/asn1/ChainBuilder.h +++ b/src/card/base/asn1/ChainBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,7 +12,7 @@ #pragma once -#include +#include #include #include @@ -24,10 +24,10 @@ template class ChainBuilder { private: - QVector> mChains; + QList> mChains; std::function mIsChildFunc; - void buildChain(const QVector& pAllElements, const QVector& pChain) + void buildChain(const QList& pAllElements, const QList& pChain) { bool chainComplete = true; @@ -40,14 +40,14 @@ class ChainBuilder if (mIsChildFunc(elem, pChain.last())) { - QVector extendedChain(pChain); + QList extendedChain(pChain); extendedChain += elem; buildChain(pAllElements, extendedChain); chainComplete = false; } else if (mIsChildFunc(pChain.first(), elem)) { - QVector extendedChain({elem}); + QList extendedChain({elem}); extendedChain += pChain; buildChain(pAllElements, extendedChain); chainComplete = false; @@ -61,28 +61,28 @@ class ChainBuilder } - bool isSubChain(const QVector& pSubChain) + bool isSubChain(const QList& pSubChain) { - return std::any_of(mChains.constBegin(), mChains.constEnd(), [&pSubChain] (const QVector& pChain) { + return std::any_of(mChains.constBegin(), mChains.constEnd(), [&pSubChain] (const QList& pChain) { return std::search(pChain.constBegin(), pChain.constEnd(), pSubChain.constBegin(), pSubChain.constEnd()) != pChain.constEnd(); }); } protected: - QMutableVectorIterator> getChainIterator() + QMutableListIterator> getChainIterator() { - return QMutableVectorIterator>(mChains); + return QMutableListIterator>(mChains); } public: - ChainBuilder(const QVector& pAllElements, const std::function& pIsChildFunc) + ChainBuilder(const QList& pAllElements, const std::function& pIsChildFunc) : mChains() , mIsChildFunc(pIsChildFunc) { for (const auto& elem : pAllElements) { - const QVector chain({elem}); + const QList chain({elem}); if (!isSubChain(chain)) { buildChain(pAllElements, chain); @@ -91,7 +91,7 @@ class ChainBuilder } - const QVector>& getChains() const + const QList>& getChains() const { return mChains; } diff --git a/src/card/base/asn1/Chat.cpp b/src/card/base/asn1/Chat.cpp index 1da099ded..9703a2162 100644 --- a/src/card/base/asn1/Chat.cpp +++ b/src/card/base/asn1/Chat.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Chat.h" diff --git a/src/card/base/asn1/Chat.h b/src/card/base/asn1/Chat.h index 29c2dab31..187027cb6 100644 --- a/src/card/base/asn1/Chat.h +++ b/src/card/base/asn1/Chat.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/ChipAuthenticationInfo.cpp b/src/card/base/asn1/ChipAuthenticationInfo.cpp index f09e82860..acd51a9e8 100644 --- a/src/card/base/asn1/ChipAuthenticationInfo.cpp +++ b/src/card/base/asn1/ChipAuthenticationInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ChipAuthenticationInfo.h" @@ -8,10 +8,15 @@ #include "ASN1Util.h" #include "SecurityProtocol.h" +#include + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(card) + + namespace governikus { diff --git a/src/card/base/asn1/ChipAuthenticationInfo.h b/src/card/base/asn1/ChipAuthenticationInfo.h index 80f8b7359..e53a8fa3d 100644 --- a/src/card/base/asn1/ChipAuthenticationInfo.h +++ b/src/card/base/asn1/ChipAuthenticationInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/EFCardSecurity.cpp b/src/card/base/asn1/EFCardSecurity.cpp index 43e7c1967..ff56675a4 100644 --- a/src/card/base/asn1/EFCardSecurity.cpp +++ b/src/card/base/asn1/EFCardSecurity.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "EFCardSecurity.h" @@ -70,6 +70,18 @@ QSharedPointer EFCardSecurity::decode(const QByteArray& pBytes) return QSharedPointer(); } + const QSharedPointer certs(CMS_get1_certs(contentInfo.data()), [](STACK_OF(X509)* pInfo){sk_X509_pop_free(pInfo, X509_free);}); + for (int i = 0; certs && i < sk_X509_num(certs.data()); ++i) + { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + const +#endif + auto* const name = X509_get_subject_name(sk_X509_value(certs.data(), i)); + const int index = X509_NAME_get_index_by_NID(name, NID_serialNumber, -1); + const auto* const serial = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index)); + qCDebug(card) << "Parsed EFCardSecurity signed with DocSigner:" << Asn1StringUtil::getValue(serial); + } + return QSharedPointer::create(securityInfos); } diff --git a/src/card/base/asn1/EFCardSecurity.h b/src/card/base/asn1/EFCardSecurity.h index b4c4a0a1b..01a3697a7 100644 --- a/src/card/base/asn1/EFCardSecurity.h +++ b/src/card/base/asn1/EFCardSecurity.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/EcdsaPublicKey.cpp b/src/card/base/asn1/EcdsaPublicKey.cpp index 7d3d5d241..ea07eda53 100644 --- a/src/card/base/asn1/EcdsaPublicKey.cpp +++ b/src/card/base/asn1/EcdsaPublicKey.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "EcdsaPublicKey.h" diff --git a/src/card/base/asn1/EcdsaPublicKey.h b/src/card/base/asn1/EcdsaPublicKey.h index c03d3a929..36f768ee7 100644 --- a/src/card/base/asn1/EcdsaPublicKey.h +++ b/src/card/base/asn1/EcdsaPublicKey.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/base/asn1/MobileEIDTypeInfo.cpp b/src/card/base/asn1/MobileEIDTypeInfo.cpp index 45e808680..dc4e576a5 100644 --- a/src/card/base/asn1/MobileEIDTypeInfo.cpp +++ b/src/card/base/asn1/MobileEIDTypeInfo.cpp @@ -1,15 +1,20 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "MobileEIDTypeInfo.h" #include "ASN1TemplateUtil.h" +#include + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(card) + + namespace governikus { diff --git a/src/card/base/asn1/MobileEIDTypeInfo.h b/src/card/base/asn1/MobileEIDTypeInfo.h index b0d24a8e7..ed4fcb2ec 100644 --- a/src/card/base/asn1/MobileEIDTypeInfo.h +++ b/src/card/base/asn1/MobileEIDTypeInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/Oid.cpp b/src/card/base/asn1/Oid.cpp index a18f7114b..565aac502 100644 --- a/src/card/base/asn1/Oid.cpp +++ b/src/card/base/asn1/Oid.cpp @@ -1,9 +1,10 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "Oid.h" +#include "ASN1Struct.h" #include "EnumHelper.h" #include "Initializer.h" @@ -144,7 +145,8 @@ void Oid::createKnownOids() cKnownOids[KnownOid::ID_PLAIN_FORMAT] = OBJ_create("0.4.0.127.0.7.3.1.3.1.1", "id-plainFormat", "BSI TR-03110 Part 4 Version 2.21 Plain Text Format 2.2.6.1"); cKnownOids[KnownOid::ID_HTML_FORMAT] = OBJ_create("0.4.0.127.0.7.3.1.3.1.2", "id-htmlFormat", "BSI TR-03110 Part 4 Version 2.21 HTML Format 2.2.6.2"); cKnownOids[KnownOid::ID_PFD_FORMAT] = OBJ_create("0.4.0.127.0.7.3.1.3.1.3", "id-pdfFormat", "BSI TR-03110 Part 4 Version 2.21 PDF Format 2.2.6.3"); - cKnownOids[KnownOid::ID_SECTOR] = OBJ_create("0.4.0.127.0.7.3.1.3.2", "id-sector", "BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Restricted Identification C.3.2.1"); + cKnownOids[KnownOid::ID_SECTOR_RI] = OBJ_create("0.4.0.127.0.7.3.1.3.2", "id-sector-ri", "BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Restricted Identification C.3.2.1"); + cKnownOids[KnownOid::ID_SECTOR_PS] = OBJ_create("0.4.0.127.0.7.3.1.3.3", "id-sector-ps", "BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Pseudonymous Signatures C.3.2.2"); cKnownOids[KnownOid::ID_EID_TYPE] = OBJ_create("0.4.0.127.0.7.3.2.3", "id-eIDType", "Draft Smart-eID"); cKnownOids[KnownOid::ID_CARD_EID_TYPE] = OBJ_create("0.4.0.127.0.7.3.2.3.1", "id-cardEIDType", "Draft Smart-eID - 1"); @@ -187,12 +189,16 @@ Oid::Oid(const ASN1_OBJECT* pObject) } -Oid::Oid(const QByteArray& pOid) - : mObject(OBJ_txt2obj(pOid.constData(), 0)) +Oid::Oid(const QByteArray& pData) + : mObject(nullptr) { + const QByteArray& der = ASN1Struct(V_ASN1_UNIVERSAL, ASN1Struct::UNI_OBJECT_IDENTIFIER, pData); + const auto* derPointer = reinterpret_cast(der.constData()); + d2i_ASN1_OBJECT(&mObject, &derPointer, static_cast(der.length())); + if (!mObject) { - qCritical() << "Invalid text input, was not able to create a valid OID for:" << pOid; + qCritical() << "d2i_ASN1_OBJECT failed, was not able to create a valid OID"; return; } @@ -239,7 +245,7 @@ Oid& Oid::operator=(Oid&& pOid) noexcept } -QByteArray Oid::getData() const +Oid::operator QByteArray() const { if (!mObject) { @@ -252,34 +258,6 @@ QByteArray Oid::getData() const } -Oid::operator QByteArray() const -{ - if (!mObject) - { - return QByteArray(); - } - - const int oidSize = OBJ_obj2txt(nullptr, 0, mObject, 1); - if (oidSize < 1) - { - return QByteArray(); - } - - QByteArray description(oidSize + 1, '\0'); // +1 = null termination - OBJ_obj2txt(description.data(), static_cast(description.size()), mObject, 1); - description.resize(oidSize); // remove null termination - - if (const int nid = OBJ_obj2nid(mObject); nid != NID_undef) - { - description += QByteArray(" ("); - description += QByteArray(OBJ_nid2sn(nid)); - description += QByteArray(")"); - } - - return description; -} - - bool Oid::isUndefined() const { return mObject == nullptr || OBJ_obj2nid(mObject) == NID_undef; @@ -308,4 +286,40 @@ bool Oid::operator!=(const Oid& pOther) const } +namespace governikus +{ +QDebug operator<<(QDebug pDbg, const Oid& pOid) +{ + QDebugStateSaver saver(pDbg); + + if (!pOid.mObject) + { + pDbg.noquote() << "undefined"; + return pDbg; + } + + const int oidSize = OBJ_obj2txt(nullptr, 0, pOid.mObject, 1); + if (oidSize < 1) + { + pDbg.noquote() << "undefined"; + return pDbg; + } + + QByteArray description(oidSize + 1, '\0'); // +1 = null termination + OBJ_obj2txt(description.data(), static_cast(description.size()), pOid.mObject, 1); + description.resize(oidSize); // remove null termination + + if (const int nid = OBJ_obj2nid(pOid.mObject); nid != NID_undef) + { + description += QByteArray(" ("); + description += QByteArray(OBJ_nid2sn(nid)); + description += QByteArray(")"); + } + + pDbg.noquote() << description; + return pDbg; +} + + +} // namespace governikus #include "moc_Oid.cpp" diff --git a/src/card/base/asn1/Oid.h b/src/card/base/asn1/Oid.h index 05a5b418c..088c32068 100644 --- a/src/card/base/asn1/Oid.h +++ b/src/card/base/asn1/Oid.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -122,7 +122,8 @@ defineEnumType(KnownOid , ID_PLAIN_FORMAT , ID_HTML_FORMAT , ID_PFD_FORMAT - , ID_SECTOR + , ID_SECTOR_RI + , ID_SECTOR_PS , ID_EID_TYPE , ID_CARD_EID_TYPE , ID_MOBILE_EID_TYPE @@ -132,6 +133,7 @@ defineEnumType(KnownOid class Oid { + friend QDebug operator<<(QDebug, const Oid&); friend class ::test_Oid; private: @@ -145,7 +147,7 @@ class Oid Oid(); Oid(KnownOid pOid); explicit Oid(const ASN1_OBJECT* pObject); - explicit Oid(const QByteArray& pTxt); + explicit Oid(const QByteArray& pData); Oid(const Oid& pOid); Oid(Oid&& pOid) noexcept; ~Oid(); @@ -154,7 +156,6 @@ class Oid Oid& operator=(Oid&&) noexcept; bool isUndefined() const; - QByteArray getData() const; explicit operator QByteArray() const; bool operator==(const Oid& pOther) const; @@ -163,16 +164,11 @@ class Oid inline auto qHash(const Oid& pOid) { - return qHash(pOid.getData()); + return qHash(QByteArray(pOid)); } -inline QDebug operator<<(QDebug pDbg, const Oid& pOid) -{ - QDebugStateSaver saver(pDbg); - pDbg.noquote() << QByteArray(pOid); - return pDbg; -} +QDebug operator<<(QDebug pDbg, const Oid& pOid); } // namespace governikus diff --git a/src/card/base/asn1/PaceInfo.cpp b/src/card/base/asn1/PaceInfo.cpp index 54a23b3d8..7273036f4 100644 --- a/src/card/base/asn1/PaceInfo.cpp +++ b/src/card/base/asn1/PaceInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "PaceInfo.h" @@ -74,6 +74,53 @@ QSharedPointer PaceInfo::decode(const QByteArray& pBytes) } +int PaceInfo::getMappedNid(int pCurveIndex) +{ + switch (pCurveIndex) + { + case 8: + // According to RFC 5480 2.1.1.1 secp192r1 equals NID_X9_62_prime192v1 + return NID_X9_62_prime192v1; + + case 9: + return NID_brainpoolP192r1; + + case 10: + // cannot be used with IM + return NID_secp224r1; + + case 11: + return NID_brainpoolP224r1; + + case 12: + // According to RFC 5480 2.1.1.1 secp256r1 equals NID_X9_62_prime256v1 + return NID_X9_62_prime256v1; + + case 13: + return NID_brainpoolP256r1; + + case 14: + return NID_brainpoolP320r1; + + case 15: + return NID_secp384r1; + + case 16: + return NID_brainpoolP384r1; + + case 17: + return NID_brainpoolP512r1; + + case 18: + return NID_secp521r1; + + default: + qCWarning(card) << "Standardized elliptic curve" << pCurveIndex << "not supported"; + return NID_undef; + } +} + + int PaceInfo::getVersion() const { return Asn1IntegerUtil::getValue(mDelegate->mVersion); @@ -140,50 +187,3 @@ bool PaceInfo::isStandardizedDomainParameters() const return false; } - - -int PaceInfo::getMappedNid(int pCurveIndex) -{ - switch (pCurveIndex) - { - case 8: - // According to RFC 5480 2.1.1.1 secp192r1 equals NID_X9_62_prime192v1 - return NID_X9_62_prime192v1; - - case 9: - return NID_brainpoolP192r1; - - case 10: - // cannot be used with IM - return NID_secp224r1; - - case 11: - return NID_brainpoolP224r1; - - case 12: - // According to RFC 5480 2.1.1.1 secp256r1 equals NID_X9_62_prime256v1 - return NID_X9_62_prime256v1; - - case 13: - return NID_brainpoolP256r1; - - case 14: - return NID_brainpoolP320r1; - - case 15: - return NID_secp384r1; - - case 16: - return NID_brainpoolP384r1; - - case 17: - return NID_brainpoolP512r1; - - case 18: - return NID_secp521r1; - - default: - qCWarning(card) << "Standardized elliptic curve" << pCurveIndex << "not supported"; - return NID_undef; - } -} diff --git a/src/card/base/asn1/PaceInfo.h b/src/card/base/asn1/PaceInfo.h index 859c8b3a4..2a70f06c5 100644 --- a/src/card/base/asn1/PaceInfo.h +++ b/src/card/base/asn1/PaceInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -56,11 +56,11 @@ class PaceInfo explicit PaceInfo(const QSharedPointer& pDelegate); [[nodiscard]] ASN1_OBJECT* getProtocolObjectIdentifier() const override; - [[nodiscard]] static int getMappedNid(int pCurveIndex); static bool acceptsProtocol(const ASN1_OBJECT* pObjectIdentifier); public: static QSharedPointer decode(const QByteArray& pBytes); + [[nodiscard]] static int getMappedNid(int pCurveIndex); [[nodiscard]] int getVersion() const; [[nodiscard]] bool hasParameterId() const; diff --git a/src/card/base/asn1/SecurityInfo.cpp b/src/card/base/asn1/SecurityInfo.cpp index bd1ba10fb..cb4240d0c 100644 --- a/src/card/base/asn1/SecurityInfo.cpp +++ b/src/card/base/asn1/SecurityInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SecurityInfo.h" diff --git a/src/card/base/asn1/SecurityInfo.h b/src/card/base/asn1/SecurityInfo.h index ab4c6eb37..5ef755245 100644 --- a/src/card/base/asn1/SecurityInfo.h +++ b/src/card/base/asn1/SecurityInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/asn1/SecurityInfos.cpp b/src/card/base/asn1/SecurityInfos.cpp index 4da68e6b1..afc100065 100644 --- a/src/card/base/asn1/SecurityInfos.cpp +++ b/src/card/base/asn1/SecurityInfos.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SecurityInfos.h" @@ -40,9 +40,9 @@ QSharedPointer SecurityInfos::decode(const QByteArray& pBytes) return QSharedPointer(); } - QVector> securityInfos; - QVector> paceInfos; - QVector> chipAuthenticationInfos; + QList> securityInfos; + QList> paceInfos; + QList> chipAuthenticationInfos; QSharedPointer mobileEIDTypeInfo; for (int i = 0; i < sk_securityinfo_st_num(securityInfosStruct.data()); ++i) @@ -87,9 +87,9 @@ QSharedPointer SecurityInfos::decode(const QByteArray& pBytes) SecurityInfos::SecurityInfos(const QByteArray& pBytes, - const QVector>& pSecurityInfos, - const QVector>& pPaceInfos, - const QVector>& pChipAuthenticationInfos, + const QList>& pSecurityInfos, + const QList>& pPaceInfos, + const QList>& pChipAuthenticationInfos, const QSharedPointer& pMobileEIDTypeInfo) : mContentBytes(pBytes) , mSecurityInfos(pSecurityInfos) @@ -106,19 +106,19 @@ const QByteArray& SecurityInfos::getContentBytes() const } -const QVector>& SecurityInfos::getSecurityInfos() const +const QList>& SecurityInfos::getSecurityInfos() const { return mSecurityInfos; } -const QVector>& SecurityInfos::getPaceInfos() const +const QList>& SecurityInfos::getPaceInfos() const { return mPaceInfos; } -const QVector>& SecurityInfos::getChipAuthenticationInfos() const +const QList>& SecurityInfos::getChipAuthenticationInfos() const { return mChipAuthenticationInfos; } diff --git a/src/card/base/asn1/SecurityInfos.h b/src/card/base/asn1/SecurityInfos.h index 95499f1ea..951afda3f 100644 --- a/src/card/base/asn1/SecurityInfos.h +++ b/src/card/base/asn1/SecurityInfos.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,8 +14,8 @@ #include "SecurityInfo.h" #include +#include #include -#include namespace governikus @@ -37,15 +37,15 @@ class SecurityInfos private: const QByteArray mContentBytes; - const QVector> mSecurityInfos; - const QVector> mPaceInfos; - const QVector> mChipAuthenticationInfos; + const QList> mSecurityInfos; + const QList> mPaceInfos; + const QList> mChipAuthenticationInfos; const QSharedPointer mMobileEIDTypeInfo; SecurityInfos(const QByteArray& pBytes, - const QVector>& pSecurityInfos, - const QVector>& pPaceInfos, - const QVector>& pChipAuthenticationInfos, + const QList>& pSecurityInfos, + const QList>& pPaceInfos, + const QList>& pChipAuthenticationInfos, const QSharedPointer& pMobileEIDTypeInfo); public: @@ -53,9 +53,9 @@ class SecurityInfos static QSharedPointer decode(const QByteArray& pBytes); [[nodiscard]] const QByteArray& getContentBytes() const; - [[nodiscard]] const QVector>& getSecurityInfos() const; - [[nodiscard]] const QVector>& getPaceInfos() const; - [[nodiscard]] const QVector>& getChipAuthenticationInfos() const; + [[nodiscard]] const QList>& getSecurityInfos() const; + [[nodiscard]] const QList>& getPaceInfos() const; + [[nodiscard]] const QList>& getChipAuthenticationInfos() const; [[nodiscard]] const QSharedPointer& getMobileEIDTypeInfo() const; }; diff --git a/src/card/base/asn1/SignatureChecker.cpp b/src/card/base/asn1/SignatureChecker.cpp index e64675042..e14b6005c 100644 --- a/src/card/base/asn1/SignatureChecker.cpp +++ b/src/card/base/asn1/SignatureChecker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "asn1/SignatureChecker.h" @@ -18,7 +18,7 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card) -SignatureChecker::SignatureChecker(const QVector>& pCertificateChain) +SignatureChecker::SignatureChecker(const QList>& pCertificateChain) : mCertificateChain(pCertificateChain) { } @@ -72,7 +72,7 @@ bool SignatureChecker::checkSignature(const QSharedPointer& } const QSharedPointer ctx = EcUtil::create(EVP_PKEY_CTX_new(signingKey.data(), nullptr)); - if (!EVP_PKEY_verify_init(ctx.data())) + if (EVP_PKEY_verify_init(ctx.data()) <= 0) { qCCritical(card) << "Cannot init verify ctx"; return false; @@ -86,7 +86,7 @@ bool SignatureChecker::checkSignature(const QSharedPointer& reinterpret_cast(hash.data()), static_cast(hash.size())); - if (result == -1) + if (result != 1 && result != 0) { qCCritical(card) << "Signature verification failed, an error occurred:" << getOpenSslError(); } diff --git a/src/card/base/asn1/SignatureChecker.h b/src/card/base/asn1/SignatureChecker.h index d0cf83906..7fbed9808 100644 --- a/src/card/base/asn1/SignatureChecker.h +++ b/src/card/base/asn1/SignatureChecker.h @@ -1,12 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "asn1/CVCertificate.h" -#include +#include namespace governikus { @@ -14,12 +14,12 @@ namespace governikus class SignatureChecker { private: - const QVector> mCertificateChain; + const QList> mCertificateChain; bool checkSignature(const QSharedPointer& pCert, const QSharedPointer& pSigningCert, const EcdsaPublicKey* pKey) const; public: - explicit SignatureChecker(const QVector>& pCertificateChain); + explicit SignatureChecker(const QList>& pCertificateChain); ~SignatureChecker() = default; [[nodiscard]] bool check() const; diff --git a/src/card/base/command/BaseCardCommand.cpp b/src/card/base/command/BaseCardCommand.cpp index 823e6028a..a79235f3b 100644 --- a/src/card/base/command/BaseCardCommand.cpp +++ b/src/card/base/command/BaseCardCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "BaseCardCommand.h" diff --git a/src/card/base/command/BaseCardCommand.h b/src/card/base/command/BaseCardCommand.h index 1c638ebb1..4b259e332 100644 --- a/src/card/base/command/BaseCardCommand.h +++ b/src/card/base/command/BaseCardCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/CreateCardConnectionCommand.cpp b/src/card/base/command/CreateCardConnectionCommand.cpp index a5bd68269..fb3cb49ff 100644 --- a/src/card/base/command/CreateCardConnectionCommand.cpp +++ b/src/card/base/command/CreateCardConnectionCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "CreateCardConnectionCommand.h" @@ -39,12 +39,23 @@ void CreateCardConnectionCommand::execute() { Q_ASSERT(QObject::thread() == QThread::currentThread()); - if (connect(mReaderManagerWorker.data(), &ReaderManagerWorker::fireCardConnectionWorkerCreated, this, &CreateCardConnectionCommand::onCardConnectionWorkerCreated, Qt::UniqueConnection)) + if (connect(mReaderManagerWorker.data(), &ReaderManagerWorker::fireCardConnectionWorkerCreated, this, &CreateCardConnectionCommand::onCardConnectionWorkerCreated)) { const auto& localCopy = mReaderManagerWorker; const auto& name = mReaderName; QMetaObject::invokeMethod(localCopy.data(), [localCopy, name] { - localCopy->createCardConnectionWorker(name); + localCopy->createCardConnectionWorker(name, [] (const QSharedPointer& pWorker) -> QSharedPointer { + if (pWorker) + { + const auto application = pWorker->getReaderInfo().getCardInfo().getApplication(); + if (application != FileRef() && !pWorker->selectApplicationRoot(application)) + { + return nullptr; + } + } + + return pWorker; + }); }, Qt::QueuedConnection); } else diff --git a/src/card/base/command/CreateCardConnectionCommand.h b/src/card/base/command/CreateCardConnectionCommand.h index 6aa29b671..d33cbeae3 100644 --- a/src/card/base/command/CreateCardConnectionCommand.h +++ b/src/card/base/command/CreateCardConnectionCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/DestroyPaceChannelCommand.cpp b/src/card/base/command/DestroyPaceChannelCommand.cpp index 8364f0628..ba4e00adb 100644 --- a/src/card/base/command/DestroyPaceChannelCommand.cpp +++ b/src/card/base/command/DestroyPaceChannelCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "DestroyPaceChannelCommand.h" @@ -7,9 +7,15 @@ using namespace governikus; -DestroyPaceChannelCommand::DestroyPaceChannelCommand(QSharedPointer pCardConnectionWorker) +DestroyPaceChannelCommand::DestroyPaceChannelCommand(QSharedPointer pCardConnectionWorker, + const QString& pSlotHandle) : BaseCardCommand(pCardConnectionWorker) + , mSlotHandle(pSlotHandle) + , mSecureMessagingStopped(false) { + connect(pCardConnectionWorker.data(), &CardConnectionWorker::fireSecureMessagingStopped, this, [this](){ + mSecureMessagingStopped = true; + }); } diff --git a/src/card/base/command/DestroyPaceChannelCommand.h b/src/card/base/command/DestroyPaceChannelCommand.h index 0e934cb15..d9baf99f9 100644 --- a/src/card/base/command/DestroyPaceChannelCommand.h +++ b/src/card/base/command/DestroyPaceChannelCommand.h @@ -1,9 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Command to destroy a Pace channel. + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -11,8 +7,12 @@ #include "BaseCardCommand.h" #include "CardConnectionWorker.h" +#include + + class test_DestroyPaceChannelCommand; + namespace governikus { @@ -22,12 +22,30 @@ class DestroyPaceChannelCommand Q_OBJECT friend class ::test_DestroyPaceChannelCommand; + private: + const QString mSlotHandle; + bool mSecureMessagingStopped; + protected: void internalExecute() override; ~DestroyPaceChannelCommand() override = default; public: - explicit DestroyPaceChannelCommand(QSharedPointer pCardConnectionWorker); + explicit DestroyPaceChannelCommand(QSharedPointer pCardConnectionWorker, + const QString& pSlotHandle); + + [[nodiscard]] const QString& getSlotHandle() const + { + return mSlotHandle; + } + + + [[nodiscard]] bool getSecureMessagingStopped() const + { + return mSecureMessagingStopped; + } + + }; } // namespace governikus diff --git a/src/card/base/command/DidAuthenticateEAC1Command.cpp b/src/card/base/command/DidAuthenticateEAC1Command.cpp index eb74080f0..971ff60d9 100644 --- a/src/card/base/command/DidAuthenticateEAC1Command.cpp +++ b/src/card/base/command/DidAuthenticateEAC1Command.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateEAC1Command.h" diff --git a/src/card/base/command/DidAuthenticateEAC1Command.h b/src/card/base/command/DidAuthenticateEAC1Command.h index 73b464781..cb9e91873 100644 --- a/src/card/base/command/DidAuthenticateEAC1Command.h +++ b/src/card/base/command/DidAuthenticateEAC1Command.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/DidAuthenticateEAC2Command.cpp b/src/card/base/command/DidAuthenticateEAC2Command.cpp index cea6160e8..0a7f07789 100644 --- a/src/card/base/command/DidAuthenticateEAC2Command.cpp +++ b/src/card/base/command/DidAuthenticateEAC2Command.cpp @@ -1,15 +1,16 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateEAC2Command.h" #include "GlobalStatus.h" #include "apdu/CommandApdu.h" -#include "apdu/CommandData.h" #include "apdu/GeneralAuthenticateResponse.h" +#include "asn1/ASN1Struct.h" #include "asn1/ChipAuthenticationInfo.h" #include "asn1/EFCardSecurity.h" +#include "pace/ec/EcUtil.h" #include @@ -82,26 +83,12 @@ void DidAuthenticateEAC2Command::internalExecute() Oid taProtocol = mCvcChain.getTerminalCvc()->getBody().getPublicKey().getOid(); QByteArray chr = mCvcChain.getTerminalCvc()->getBody().getCertificateHolderReference(); - QByteArray ephemeralPublicKey = QByteArray::fromHex(mEphemeralPublicKeyAsHex); - if (ephemeralPublicKey.size() % 2 == 0) - { - /* - * According to TR-03111, chapter 3.2.1 the uncompressed encoding of an elliptic curve point is: - * 0x04 | xCoordinate | yCoordinate - * In contrast the AGETO and mtG server just sends xCoordinate | yCoordinate. - * - * We fix this by prepending 0x04 - */ - ephemeralPublicKey.prepend(0x04); - } - QByteArray compressedEphemeralPublicKey = ephemeralPublicKey.mid(1, (ephemeralPublicKey.size() - 1) / 2); - QByteArray signature = QByteArray::fromHex(mSignatureAsHex); setReturnCode(performTerminalAuthentication(taProtocol, chr, mAuthenticatedAuxiliaryDataAsBinary, - compressedEphemeralPublicKey, + EcUtil::compressPoint(ephemeralPublicKey), signature)); if (getReturnCode() != CardReturnCode::OK) @@ -154,9 +141,9 @@ CardReturnCode DidAuthenticateEAC2Command::putCertificateChain(const CVCertifica for (const auto& cvCertificate : pCvcChain) { QByteArray car = cvCertificate->getBody().getCertificationAuthorityReference(); - CommandData cmdDataSet; - cmdDataSet.append(CommandData::PUBLIC_KEY_REFERENCE, car); - CommandApdu cmdApduSet(Ins::MSE_SET, CommandApdu::VERIFICATION, CommandApdu::DIGITAL_SIGNATURE_TEMPLATE, cmdDataSet); + ASN1Struct cmdDataSet; + cmdDataSet.append(ASN1Struct::PUBLIC_KEY_REFERENCE, car); + CommandApdu cmdApduSet(Ins::MSE_SET, CommandApdu::TERMINAL_AUTHENTICATION, CommandApdu::DIGITAL_SIGNATURE_TEMPLATE, cmdDataSet); qCDebug(card) << "Performing TA MSE:Set DST with CAR" << car; const auto& [mseReturnCode, mseResult] = getCardConnectionWorker()->transmit(cmdApduSet); @@ -172,7 +159,7 @@ CardReturnCode DidAuthenticateEAC2Command::putCertificateChain(const CVCertifica return CardReturnCode::PROTOCOL_ERROR; } - CommandData cmdDataVerify; + ASN1Struct cmdDataVerify; cmdDataVerify.append(cvCertificate->getRawBody()); cmdDataVerify.append(cvCertificate->getRawSignature()); CommandApdu cmdApduVerify(Ins::PSO_VERIFY, CommandApdu::IMPLICIT, CommandApdu::SELF_DESCRIPTIVE, cmdDataVerify); @@ -208,12 +195,12 @@ CardReturnCode DidAuthenticateEAC2Command::performTerminalAuthentication(const O const QByteArray& pCompressedEphemeralPublicKey, const QByteArray& pSignature) { - CommandData cmdData; - cmdData.append(CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE, pTaProtocol); - cmdData.append(CommandData::PUBLIC_KEY_REFERENCE, pChr); + ASN1Struct cmdData; + cmdData.append(ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE, pTaProtocol); + cmdData.append(ASN1Struct::PUBLIC_KEY_REFERENCE, pChr); cmdData.append(pAuxiliaryData); - cmdData.append(CommandData::TA_EPHEMERAL_PUBLIC_KEY, pCompressedEphemeralPublicKey); - CommandApdu cmdApdu(Ins::MSE_SET, CommandApdu::VERIFICATION, CommandApdu::AUTHENTICATION_TEMPLATE, cmdData); + cmdData.append(ASN1Struct::TA_EPHEMERAL_PUBLIC_KEY, pCompressedEphemeralPublicKey); + CommandApdu cmdApdu(Ins::MSE_SET, CommandApdu::TERMINAL_AUTHENTICATION, CommandApdu::AUTHENTICATION_TEMPLATE, cmdData); qCDebug(card) << "Performing TA MSE:Set AT"; const auto& [mseReturnCode, mseResult] = getCardConnectionWorker()->transmit(cmdApdu); @@ -251,11 +238,11 @@ CardReturnCode DidAuthenticateEAC2Command::performTerminalAuthentication(const O CardReturnCode DidAuthenticateEAC2Command::performChipAuthentication(QSharedPointer pChipAuthInfo, const QByteArray& pEphemeralPublicKey) { - CommandData cmdDataSet; - cmdDataSet.append(CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE, pChipAuthInfo->getOid()); + ASN1Struct cmdDataSet; + cmdDataSet.append(ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE, pChipAuthInfo->getOid()); if (pChipAuthInfo->hasKeyId()) { - cmdDataSet.append(CommandData::PRIVATE_KEY_REFERENCE, pChipAuthInfo->getKeyId()); + cmdDataSet.append(ASN1Struct::PRIVATE_KEY_REFERENCE, pChipAuthInfo->getKeyId()); } CommandApdu cmdApduSet(Ins::MSE_SET, CommandApdu::CHIP_AUTHENTICATION, CommandApdu::AUTHENTICATION_TEMPLATE, cmdDataSet); @@ -272,8 +259,8 @@ CardReturnCode DidAuthenticateEAC2Command::performChipAuthentication(QSharedPoin return CardReturnCode::PROTOCOL_ERROR; } - CommandData cmdDataCa(V_ASN1_APPLICATION, CommandData::DYNAMIC_AUTHENTICATION_DATA); - cmdDataCa.append(CommandData::CA_EPHEMERAL_PUBLIC_KEY, pEphemeralPublicKey); + ASN1Struct cmdDataCa(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA); + cmdDataCa.append(ASN1Struct::CA_EPHEMERAL_PUBLIC_KEY, pEphemeralPublicKey); CommandApdu cmdApduCa(Ins::GENERAL_AUTHENTICATE, 0, 0, cmdDataCa, CommandApdu::SHORT_MAX_LE); qCDebug(card) << "Performing CA General Authenticate"; const auto& [gaReturnCode, gaGenericResponse] = getCardConnectionWorker()->transmit(cmdApduCa); diff --git a/src/card/base/command/DidAuthenticateEAC2Command.h b/src/card/base/command/DidAuthenticateEAC2Command.h index e1fe2103c..069e1d6ec 100644 --- a/src/card/base/command/DidAuthenticateEAC2Command.h +++ b/src/card/base/command/DidAuthenticateEAC2Command.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/EstablishPaceChannelCommand.cpp b/src/card/base/command/EstablishPaceChannelCommand.cpp index 1b6dd7be3..b2b0a2edf 100644 --- a/src/card/base/command/EstablishPaceChannelCommand.cpp +++ b/src/card/base/command/EstablishPaceChannelCommand.cpp @@ -1,11 +1,9 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "EstablishPaceChannelCommand.h" -#include "apdu/CommandApdu.h" - using namespace governikus; @@ -57,17 +55,4 @@ void EstablishPaceChannelCommand::internalExecute() mPaceOutput = getCardConnectionWorker()->establishPaceChannel(mPacePasswordId, mPacePassword, mEffectiveChat, mCertificateDescription); } setReturnCode(mPaceOutput.getPaceReturnCode()); - - if (mPacePasswordId == PacePasswordId::PACE_PUK && getReturnCode() == CardReturnCode::OK) - { - const CommandApdu cmdApdu(Ins::RESET_RETRY_COUNTER, CommandApdu::UNBLOCK, CommandApdu::PIN); - auto [returnCode, response] = getCardConnectionWorker()->transmit(cmdApdu); - setReturnCode(returnCode); - if (getReturnCode() == CardReturnCode::OK && response.getSW1() == SW1::ERROR_COMMAND_NOT_ALLOWED) - { - getCardConnectionWorker()->setPukInoperative(); - mPaceOutput.setPaceReturnCode(CardReturnCode::PUK_INOPERATIVE); - setReturnCode(mPaceOutput.getPaceReturnCode()); - } - } } diff --git a/src/card/base/command/EstablishPaceChannelCommand.h b/src/card/base/command/EstablishPaceChannelCommand.h index 49f422843..42e52dc45 100644 --- a/src/card/base/command/EstablishPaceChannelCommand.h +++ b/src/card/base/command/EstablishPaceChannelCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/ExecuteCommand.cpp b/src/card/base/command/ExecuteCommand.cpp index fb3ec8dc4..b783624e3 100644 --- a/src/card/base/command/ExecuteCommand.cpp +++ b/src/card/base/command/ExecuteCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "ExecuteCommand.h" diff --git a/src/card/base/command/ExecuteCommand.h b/src/card/base/command/ExecuteCommand.h index 04e9aabf9..baf4cd71c 100644 --- a/src/card/base/command/ExecuteCommand.h +++ b/src/card/base/command/ExecuteCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/ResetRetryCounterCommand.cpp b/src/card/base/command/ResetRetryCounterCommand.cpp new file mode 100644 index 000000000..42d0591d4 --- /dev/null +++ b/src/card/base/command/ResetRetryCounterCommand.cpp @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "ResetRetryCounterCommand.h" + +using namespace governikus; + + +ResetRetryCounterCommand::ResetRetryCounterCommand(QSharedPointer pCardConnectionWorker) + : BaseCardCommand(pCardConnectionWorker) +{ +} + + +void ResetRetryCounterCommand::internalExecute() +{ + const CommandApdu cmdApdu(Ins::RESET_RETRY_COUNTER, CommandApdu::UNBLOCK, CommandApdu::PIN); + auto [returnCode, response] = getCardConnectionWorker()->transmit(cmdApdu); + setReturnCode(returnCode); + if (getReturnCode() == CardReturnCode::OK && response.getSW1() == SW1::ERROR_COMMAND_NOT_ALLOWED) + { + getCardConnectionWorker()->setPukInoperative(); + setReturnCode(CardReturnCode::PUK_INOPERATIVE); + } +} diff --git a/src/card/base/command/ResetRetryCounterCommand.h b/src/card/base/command/ResetRetryCounterCommand.h new file mode 100644 index 000000000..39c2d74d0 --- /dev/null +++ b/src/card/base/command/ResetRetryCounterCommand.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "BaseCardCommand.h" + +class test_ResetRetryCounterCommand; + +namespace governikus +{ + +class ResetRetryCounterCommand + : public BaseCardCommand +{ + Q_OBJECT + friend class ::test_ResetRetryCounterCommand; + + protected: + void internalExecute() override; + ~ResetRetryCounterCommand() override = default; + + public: + explicit ResetRetryCounterCommand(QSharedPointer pCardConnectionWorker); + +}; + +} // namespace governikus diff --git a/src/card/base/command/SetEidPinCommand.cpp b/src/card/base/command/SetEidPinCommand.cpp index 1028a8359..cde10eb45 100644 --- a/src/card/base/command/SetEidPinCommand.cpp +++ b/src/card/base/command/SetEidPinCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "SetEidPinCommand.h" @@ -20,6 +20,7 @@ SetEidPinCommand::SetEidPinCommand(QSharedPointer pCardCon void SetEidPinCommand::internalExecute() { auto [returnCode, responseApdu] = getCardConnectionWorker()->setEidPin(mNewPin, mTimeoutSeconds); + returnCode = responseApdu.isEmpty() ? CardReturnCode::RESPONSE_EMPTY : returnCode; setReturnCode(returnCode); mResponseApdu = responseApdu; } diff --git a/src/card/base/command/SetEidPinCommand.h b/src/card/base/command/SetEidPinCommand.h index 0fb326027..5220266bf 100644 --- a/src/card/base/command/SetEidPinCommand.h +++ b/src/card/base/command/SetEidPinCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/command/TransmitCommand.cpp b/src/card/base/command/TransmitCommand.cpp index 5d86739ca..304701c03 100644 --- a/src/card/base/command/TransmitCommand.cpp +++ b/src/card/base/command/TransmitCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TransmitCommand.h" @@ -12,13 +12,15 @@ #include + Q_DECLARE_LOGGING_CATEGORY(card) + using namespace governikus; TransmitCommand::TransmitCommand(QSharedPointer pCardConnectionWorker, - const QVector& pInputApduInfos, + const QList& pInputApduInfos, const QString& pSlotHandle) : BaseCardCommand(pCardConnectionWorker) , mInputApduInfos(pInputApduInfos) diff --git a/src/card/base/command/TransmitCommand.h b/src/card/base/command/TransmitCommand.h index 64084180e..3543fa12c 100644 --- a/src/card/base/command/TransmitCommand.h +++ b/src/card/base/command/TransmitCommand.h @@ -1,9 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Command to transmit data to/from the card. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -12,8 +8,9 @@ #include "CardConnectionWorker.h" #include "InputAPDUInfo.h" + class test_TransmitCommand; -class test_CardConnection; + namespace governikus { @@ -23,10 +20,9 @@ class TransmitCommand { Q_OBJECT friend class ::test_TransmitCommand; - friend class ::test_CardConnection; private: - const QVector mInputApduInfos; + const QList mInputApduInfos; const QString mSlotHandle; QByteArrayList mOutputApduAsHex; bool mSecureMessagingStopped; @@ -37,7 +33,7 @@ class TransmitCommand public: explicit TransmitCommand(QSharedPointer pCardConnectionWorker, - const QVector& pInputApduInfos, + const QList& pInputApduInfos, const QString& pSlotHandle); static bool isAcceptable(const InputAPDUInfo& pInputApduInfo, const ResponseApdu& pResponse); diff --git a/src/card/base/command/UpdateRetryCounterCommand.cpp b/src/card/base/command/UpdateRetryCounterCommand.cpp index e5452d8a4..7613436a4 100644 --- a/src/card/base/command/UpdateRetryCounterCommand.cpp +++ b/src/card/base/command/UpdateRetryCounterCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "UpdateRetryCounterCommand.h" diff --git a/src/card/base/command/UpdateRetryCounterCommand.h b/src/card/base/command/UpdateRetryCounterCommand.h index c75c2a052..6a8745c06 100644 --- a/src/card/base/command/UpdateRetryCounterCommand.h +++ b/src/card/base/command/UpdateRetryCounterCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/CipherMac.cpp b/src/card/base/pace/CipherMac.cpp index ba5a262b3..a640d320a 100644 --- a/src/card/base/pace/CipherMac.cpp +++ b/src/card/base/pace/CipherMac.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/CipherMac.h" diff --git a/src/card/base/pace/CipherMac.h b/src/card/base/pace/CipherMac.h index dbb21f593..a207f54d3 100644 --- a/src/card/base/pace/CipherMac.h +++ b/src/card/base/pace/CipherMac.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/EstablishPaceChannelCode.cpp b/src/card/base/pace/EstablishPaceChannelCode.cpp index 7b864cbbf..8d4246751 100644 --- a/src/card/base/pace/EstablishPaceChannelCode.cpp +++ b/src/card/base/pace/EstablishPaceChannelCode.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "EstablishPaceChannelCode.h" diff --git a/src/card/base/pace/EstablishPaceChannelCode.h b/src/card/base/pace/EstablishPaceChannelCode.h index d60b4d8a4..648800f63 100644 --- a/src/card/base/pace/EstablishPaceChannelCode.h +++ b/src/card/base/pace/EstablishPaceChannelCode.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/KeyAgreement.cpp b/src/card/base/pace/KeyAgreement.cpp index d0d4f9ba3..838824cc1 100644 --- a/src/card/base/pace/KeyAgreement.cpp +++ b/src/card/base/pace/KeyAgreement.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ @@ -7,7 +7,7 @@ #include "GlobalStatus.h" #include "apdu/CommandApdu.h" -#include "apdu/CommandData.h" +#include "asn1/ASN1Struct.h" #include "asn1/PaceInfo.h" #include "pace/CipherMac.h" #include "pace/KeyDerivationFunction.h" @@ -42,7 +42,7 @@ KeyAgreement::CardResult KeyAgreement::createTransmitResult(CardReturnCode pRetu CardReturnCode newReturnCode = CardReturnCode::COMMAND_FAILED; if (pResponseApdu.isEmpty()) { - newReturnCode = CardReturnCode::RETRY_ALLOWED; + newReturnCode = CardReturnCode::RESPONSE_EMPTY; } else if (pReturnCode == CardReturnCode::OK) { @@ -95,7 +95,7 @@ KeyAgreementStatus KeyAgreement::perform(const QByteArray& pPin) case CardReturnCode::COMMAND_FAILED: return KeyAgreementStatus::COMMUNICATION_ERROR; - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: return KeyAgreementStatus::RETRY_ALLOWED; default: @@ -111,7 +111,7 @@ KeyAgreementStatus KeyAgreement::perform(const QByteArray& pPin) case CardReturnCode::PROTOCOL_ERROR: return KeyAgreementStatus::PROTOCOL_ERROR; - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: return KeyAgreementStatus::RETRY_ALLOWED; default: @@ -181,7 +181,7 @@ KeyAgreementStatus KeyAgreement::performMutualAuthenticate() KeyAgreement::CardResult KeyAgreement::transmitGAEncryptedNonce() { - CommandData cmdData(V_ASN1_APPLICATION, CommandData::DYNAMIC_AUTHENTICATION_DATA); + ASN1Struct cmdData(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA); CommandApdu cmdApdu(Ins::GENERAL_AUTHENTICATE, 0, 0, cmdData, CommandApdu::SHORT_MAX_LE); cmdApdu.enableCommandChaining(); @@ -193,8 +193,8 @@ KeyAgreement::CardResult KeyAgreement::transmitGAEncryptedNonce() KeyAgreement::CardResult KeyAgreement::transmitGAEphemeralPublicKey(const QByteArray& pEphemeralPublicKey) { - CommandData cmdData(V_ASN1_APPLICATION, CommandData::DYNAMIC_AUTHENTICATION_DATA); - cmdData.append(CommandData::PACE_EPHEMERAL_PUBLIC_KEY, pEphemeralPublicKey); + ASN1Struct cmdData(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA); + cmdData.append(ASN1Struct::PACE_EPHEMERAL_PUBLIC_KEY, pEphemeralPublicKey); CommandApdu cmdApdu(Ins::GENERAL_AUTHENTICATE, 0, 0, cmdData, CommandApdu::SHORT_MAX_LE); cmdApdu.enableCommandChaining(); @@ -207,8 +207,8 @@ KeyAgreement::CardResult KeyAgreement::transmitGAEphemeralPublicKey(const QByteA KeyAgreement::CardResult KeyAgreement::transmitGAMappingData(const QByteArray& pMappingData) const { // sende den PublicKey (D.3.4.) - CommandData cmdData(V_ASN1_APPLICATION, CommandData::DYNAMIC_AUTHENTICATION_DATA); - cmdData.append(CommandData::MAPPING_DATA, pMappingData); + ASN1Struct cmdData(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA); + cmdData.append(ASN1Struct::MAPPING_DATA, pMappingData); CommandApdu cmdApdu(Ins::GENERAL_AUTHENTICATE, 0, 0, cmdData, CommandApdu::SHORT_MAX_LE); cmdApdu.enableCommandChaining(); @@ -220,8 +220,8 @@ KeyAgreement::CardResult KeyAgreement::transmitGAMappingData(const QByteArray& p GAMutualAuthenticationResponse KeyAgreement::transmitGAMutualAuthentication(const QByteArray& pMutualAuthenticationData) { - CommandData cmdData(V_ASN1_APPLICATION, CommandData::DYNAMIC_AUTHENTICATION_DATA); - cmdData.append(CommandData::AUTHENTICATION_TOKEN, pMutualAuthenticationData); + ASN1Struct cmdData(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA); + cmdData.append(ASN1Struct::AUTHENTICATION_TOKEN, pMutualAuthenticationData); CommandApdu cmdApdu(Ins::GENERAL_AUTHENTICATE, 0, 0, cmdData, CommandApdu::SHORT_MAX_LE); auto [returnCode, responseApdu] = mCardConnectionWorker->transmit(cmdApdu); diff --git a/src/card/base/pace/KeyAgreement.h b/src/card/base/pace/KeyAgreement.h index 0428ee0b1..5691a3344 100644 --- a/src/card/base/pace/KeyAgreement.h +++ b/src/card/base/pace/KeyAgreement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/KeyDerivationFunction.cpp b/src/card/base/pace/KeyDerivationFunction.cpp index 6c4dc00fc..15e832075 100644 --- a/src/card/base/pace/KeyDerivationFunction.cpp +++ b/src/card/base/pace/KeyDerivationFunction.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/KeyDerivationFunction.h" diff --git a/src/card/base/pace/KeyDerivationFunction.h b/src/card/base/pace/KeyDerivationFunction.h index b1efef7fb..ee852acb6 100644 --- a/src/card/base/pace/KeyDerivationFunction.h +++ b/src/card/base/pace/KeyDerivationFunction.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/PaceHandler.cpp b/src/card/base/pace/PaceHandler.cpp index 1df3938b2..ea0265e34 100644 --- a/src/card/base/pace/PaceHandler.cpp +++ b/src/card/base/pace/PaceHandler.cpp @@ -1,13 +1,13 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/PaceHandler.h" #include "SecurityProtocol.h" #include "apdu/CommandApdu.h" -#include "apdu/CommandData.h" #include "apdu/PacePinStatus.h" +#include "asn1/ASN1Struct.h" #include "asn1/PaceInfo.h" #include "pace/KeyAgreement.h" @@ -58,8 +58,8 @@ CardReturnCode PaceHandler::establishPaceChannel(PacePasswordId pPasswordId, con case CardReturnCode::COMMAND_FAILED: return CardReturnCode::COMMAND_FAILED; - case CardReturnCode::RETRY_ALLOWED: - return CardReturnCode::RETRY_ALLOWED; + case CardReturnCode::RESPONSE_EMPTY: + return CardReturnCode::RESPONSE_EMPTY; default: break; @@ -69,7 +69,7 @@ CardReturnCode PaceHandler::establishPaceChannel(PacePasswordId pPasswordId, con switch (keyAgreementStatus) { case KeyAgreementStatus::RETRY_ALLOWED: - return CardReturnCode::RETRY_ALLOWED; + return CardReturnCode::RESPONSE_EMPTY; case KeyAgreementStatus::PROTOCOL_ERROR: return CardReturnCode::PROTOCOL_ERROR; @@ -146,10 +146,10 @@ bool PaceHandler::isSupportedProtocol(const QSharedPointer& pPac CardReturnCode PaceHandler::transmitMSESetAT(PacePasswordId pPasswordId) { - CommandData cmdData; - cmdData.append(CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE, mPaceInfo->getOid()); - cmdData.append(CommandData::PUBLIC_KEY_REFERENCE, pPasswordId); - cmdData.append(CommandData::PRIVATE_KEY_REFERENCE, mPaceInfo->getParameterId()); + ASN1Struct cmdData; + cmdData.append(ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE, mPaceInfo->getOid()); + cmdData.append(ASN1Struct::PUBLIC_KEY_REFERENCE, pPasswordId); + cmdData.append(ASN1Struct::PRIVATE_KEY_REFERENCE, mPaceInfo->getParameterId()); if (!mChat.isNull()) { cmdData.append(mChat); @@ -162,7 +162,7 @@ CardReturnCode PaceHandler::transmitMSESetAT(PacePasswordId pPasswordId) if (cardReturnCode != CardReturnCode::OK) { qCCritical(card) << "Error on MSE:Set AT"; - return response.isEmpty() ? CardReturnCode::RETRY_ALLOWED : CardReturnCode::PROTOCOL_ERROR; + return response.isEmpty() ? CardReturnCode::RESPONSE_EMPTY : CardReturnCode::PROTOCOL_ERROR; } if (PacePinStatus::getRetryCounter(response.getStatusCode()) < 1) { diff --git a/src/card/base/pace/PaceHandler.h b/src/card/base/pace/PaceHandler.h index 5ba90274d..2c6eca53a 100644 --- a/src/card/base/pace/PaceHandler.h +++ b/src/card/base/pace/PaceHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/SecureMessaging.cpp b/src/card/base/pace/SecureMessaging.cpp index dd1a91e04..5d579ddda 100644 --- a/src/card/base/pace/SecureMessaging.cpp +++ b/src/card/base/pace/SecureMessaging.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "apdu/SecureMessagingCommand.h" @@ -95,9 +95,9 @@ CommandApdu SecureMessaging::encrypt(const CommandApdu& pCommandApdu) QByteArray formattedEncryptedData; if (!pCommandApdu.getData().isEmpty()) { - QByteArray paddedCommandData = padToCipherBlockSize(pCommandApdu.getData()); + QByteArray paddedASN1Struct = padToCipherBlockSize(pCommandApdu.getData()); mCipher.setIv(getEncryptedIv()); - QByteArray encryptedData = mCipher.encrypt(paddedCommandData).prepend(0x01); + QByteArray encryptedData = mCipher.encrypt(paddedASN1Struct).prepend(0x01); auto encryptedDataObject = newObject(); Asn1OctetStringUtil::setValue(encryptedData, encryptedDataObject.data()); @@ -109,7 +109,7 @@ CommandApdu SecureMessaging::encrypt(const CommandApdu& pCommandApdu) if (pCommandApdu.getLe() > CommandApdu::NO_LE) { auto protectedLeObject = newObject(); - Asn1OctetStringUtil::setValue(createSecuredLe(pCommandApdu.getLe()), protectedLeObject.data()); + Asn1OctetStringUtil::setValue(pCommandApdu.generateLengthField(pCommandApdu.getLe()), protectedLeObject.data()); securedLe = encodeObject(protectedLeObject.data()); } QByteArray mac = createMac(securedHeader, formattedEncryptedData, securedLe); @@ -170,21 +170,6 @@ QByteArray SecureMessaging::createSecuredHeader(const CommandApdu& pCommandApdu) } -QByteArray SecureMessaging::createSecuredLe(int pLe) const -{ - QByteArray buffer; - if (pLe > CommandApdu::NO_LE) - { - if (pLe > CommandApdu::SHORT_MAX_LE) - { - buffer += static_cast(pLe >> 0x08 & 0xFF); - } - buffer += static_cast(pLe >> 0x00 & 0xFF); - } - return buffer; -} - - QByteArray SecureMessaging::createMac(const QByteArray& pSecuredHeader, const QByteArray& pFormattedEncryptedData, const QByteArray& pSecuredLe) diff --git a/src/card/base/pace/SecureMessaging.h b/src/card/base/pace/SecureMessaging.h index bca230301..3f0ad3ad4 100644 --- a/src/card/base/pace/SecureMessaging.h +++ b/src/card/base/pace/SecureMessaging.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -35,8 +35,6 @@ class SecureMessaging final [[nodiscard]] QByteArray getSendSequenceCounter() const; QByteArray getEncryptedIv(); - [[nodiscard]] QByteArray createSecuredLe(int pLe) const; - public: SecureMessaging(const SecurityProtocol& pSecurityProtocol, const QByteArray& pEncKey, const QByteArray& pMacKey); ~SecureMessaging() = default; diff --git a/src/card/base/pace/SymmetricCipher.cpp b/src/card/base/pace/SymmetricCipher.cpp index 98cf9b2e3..3d0e6a401 100644 --- a/src/card/base/pace/SymmetricCipher.cpp +++ b/src/card/base/pace/SymmetricCipher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/SymmetricCipher.h" @@ -76,7 +76,7 @@ QByteArray SymmetricCipher::encrypt(const QByteArray& pPlainData) return QByteArray(); } - QVector cryptogram(pPlainData.size()); + QList cryptogram(pPlainData.size()); int update_len = 0; if (!EVP_EncryptUpdate(mCtx, cryptogram.data(), &update_len, reinterpret_cast(pPlainData.constData()), static_cast(pPlainData.size()))) { @@ -141,7 +141,7 @@ QByteArray SymmetricCipher::decrypt(const QByteArray& pEncryptedData) return QByteArray(); } - QVector plaintext(pEncryptedData.size()); + QList plaintext(pEncryptedData.size()); int update_len = 0; if (!EVP_DecryptUpdate(mCtx, plaintext.data(), &update_len, reinterpret_cast(pEncryptedData.constData()), static_cast(pEncryptedData.size()))) { diff --git a/src/card/base/pace/SymmetricCipher.h b/src/card/base/pace/SymmetricCipher.h index 40c042578..d18f22c19 100644 --- a/src/card/base/pace/SymmetricCipher.h +++ b/src/card/base/pace/SymmetricCipher.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pace/ec/EcUtil.cpp b/src/card/base/pace/ec/EcUtil.cpp index 415813b9f..10db88f26 100644 --- a/src/card/base/pace/ec/EcUtil.cpp +++ b/src/card/base/pace/ec/EcUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "EcUtil.h" @@ -28,6 +28,21 @@ QSharedPointer EcUtil::createCurve(int pNid) } +QByteArray EcUtil::compressPoint(const QByteArray& pPoint) +{ + if (pPoint.size() % 2 == 0 || pPoint.at(0) != 0x04) + { + qCCritical(card) << "Unable to apply compression on point:" << pPoint.toHex(); + return pPoint; + } + + // Compression as defined in TR 03110-3 A.2.2.3 without a leading + // byte in front of the x coordinate indicating the compression type, + // i.e. not the typical SECG SEC1 v1.0 format used by OpenSSL. + return pPoint.mid(1, (pPoint.size() - 1) / 2); +} + + QByteArray EcUtil::point2oct(const QSharedPointer& pCurve, const EC_POINT* pPoint, bool pCompressed) { if (pCurve.isNull() || pPoint == nullptr) diff --git a/src/card/base/pace/ec/EcUtil.h b/src/card/base/pace/ec/EcUtil.h index 4f88085e8..b575341bc 100644 --- a/src/card/base/pace/ec/EcUtil.h +++ b/src/card/base/pace/ec/EcUtil.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,6 +24,8 @@ namespace governikus class EcUtil { public: + static QByteArray compressPoint(const QByteArray& pPoint); + static QByteArray point2oct(const QSharedPointer& pCurve, const EC_POINT* pPoint, bool pCompressed = false); static QSharedPointer oct2point(const QSharedPointer& pCurve, const QByteArray& pCompressedData); diff --git a/src/card/base/pace/ec/EcdhGenericMapping.cpp b/src/card/base/pace/ec/EcdhGenericMapping.cpp index cdee20f4c..3e2d1d437 100644 --- a/src/card/base/pace/ec/EcdhGenericMapping.cpp +++ b/src/card/base/pace/ec/EcdhGenericMapping.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "EcdhGenericMapping.h" @@ -16,7 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(card) EcdhGenericMapping::EcdhGenericMapping(const QSharedPointer& pCurve) : mCurve(pCurve) - , mTerminalKey() + , mLocalKey() { } @@ -27,7 +27,7 @@ const QSharedPointer& EcdhGenericMapping::getCurve() const } -QByteArray EcdhGenericMapping::generateTerminalMappingData() +QByteArray EcdhGenericMapping::generateLocalMappingData() { if (!mCurve) { @@ -35,34 +35,34 @@ QByteArray EcdhGenericMapping::generateTerminalMappingData() return QByteArray(); } - mTerminalKey = EcUtil::generateKey(mCurve); + mLocalKey = EcUtil::generateKey(mCurve); #if OPENSSL_VERSION_NUMBER >= 0x30000000L - return EcUtil::getEncodedPublicKey(mTerminalKey); + return EcUtil::getEncodedPublicKey(mLocalKey); #else - return EcUtil::point2oct(mCurve, EC_KEY_get0_public_key(mTerminalKey.data())); + return EcUtil::point2oct(mCurve, EC_KEY_get0_public_key(mLocalKey.data())); #endif } -bool EcdhGenericMapping::generateEphemeralDomainParameters(const QByteArray& pCardMappingData, +bool EcdhGenericMapping::generateEphemeralDomainParameters(const QByteArray& pRemoteMappingData, const QByteArray& pNonce) { - QSharedPointer cardPubKey = EcUtil::oct2point(mCurve, pCardMappingData); - if (cardPubKey == nullptr) + QSharedPointer remotePubKey = EcUtil::oct2point(mCurve, pRemoteMappingData); + if (remotePubKey == nullptr) { return false; } #if OPENSSL_VERSION_NUMBER >= 0x30000000L - const QSharedPointer terminalPubKeyPtr = EcUtil::oct2point(mCurve, EcUtil::getEncodedPublicKey(mTerminalKey)); - const EC_POINT* terminalPubKey = terminalPubKeyPtr.data(); + const QSharedPointer localPubKeyPtr = EcUtil::oct2point(mCurve, EcUtil::getEncodedPublicKey(mLocalKey)); + const EC_POINT* localPubKey = localPubKeyPtr.data(); #else - const EC_POINT* terminalPubKey = EC_KEY_get0_public_key(mTerminalKey.data()); + const EC_POINT* localPubKey = EC_KEY_get0_public_key(mLocalKey.data()); #endif - if (!EC_POINT_cmp(mCurve.data(), terminalPubKey, cardPubKey.data(), nullptr)) + if (!EC_POINT_cmp(mCurve.data(), localPubKey, remotePubKey.data(), nullptr)) { qCCritical(card) << "The exchanged public keys are equal."; return false; @@ -75,17 +75,17 @@ bool EcdhGenericMapping::generateEphemeralDomainParameters(const QByteArray& pCa return false; } - return setGenerator(createNewGenerator(cardPubKey, s)); + return setGenerator(createNewGenerator(remotePubKey, s)); } -QSharedPointer EcdhGenericMapping::createNewGenerator(const QSharedPointer& pCardPubKey, const QSharedPointer& pS) +QSharedPointer EcdhGenericMapping::createNewGenerator(const QSharedPointer& pRemotePubKey, const QSharedPointer& pS) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L - const auto& privKeyPtr = EcUtil::getPrivateKey(mTerminalKey); + const auto& privKeyPtr = EcUtil::getPrivateKey(mLocalKey); const BIGNUM* privKey = privKeyPtr.data(); #else - const BIGNUM* privKey = EC_KEY_get0_private_key(mTerminalKey.data()); + const BIGNUM* privKey = EC_KEY_get0_private_key(mLocalKey.data()); #endif if (!privKey) @@ -95,7 +95,7 @@ QSharedPointer EcdhGenericMapping::createNewGenerator(const QSharedPoi } QSharedPointer H = EcUtil::create(EC_POINT_new(mCurve.data())); - if (!EC_POINT_mul(mCurve.data(), H.data(), nullptr, pCardPubKey.data(), privKey, nullptr)) + if (!EC_POINT_mul(mCurve.data(), H.data(), nullptr, pRemotePubKey.data(), privKey, nullptr)) { qCCritical(card) << "Calculation of elliptic curve point H failed"; return QSharedPointer(); diff --git a/src/card/base/pace/ec/EcdhGenericMapping.h b/src/card/base/pace/ec/EcdhGenericMapping.h index 3a06cd1b1..bdfa5a895 100644 --- a/src/card/base/pace/ec/EcdhGenericMapping.h +++ b/src/card/base/pace/ec/EcdhGenericMapping.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -23,12 +23,12 @@ class EcdhGenericMapping private: const QSharedPointer mCurve; #if OPENSSL_VERSION_NUMBER >= 0x30000000L - QSharedPointer mTerminalKey; + QSharedPointer mLocalKey; #else - QSharedPointer mTerminalKey; + QSharedPointer mLocalKey; #endif - QSharedPointer createNewGenerator(const QSharedPointer& pCardPubKey, const QSharedPointer& pS); + QSharedPointer createNewGenerator(const QSharedPointer& pRemotePubKey, const QSharedPointer& pS); bool setGenerator(const QSharedPointer& pNewGenerator) const; @@ -38,18 +38,18 @@ class EcdhGenericMapping [[nodiscard]] const QSharedPointer& getCurve() const; /*! - * \brief Generates the terminal's mapping data, that will be sent to the card. - * \return the terminal's mapping data + * \brief Generates the local mapping data, that will be sent to the remote. + * \return The local mapping data */ - QByteArray generateTerminalMappingData(); + QByteArray generateLocalMappingData(); /*! * \brief Generates the ephemeral domain parameters. - * \param pCardMappingData the card's mapping data + * \param pRemoteMappingData the card's mapping data * \param pNonce the nonce that was generated by the card * \return the terminal's mapping data */ - bool generateEphemeralDomainParameters(const QByteArray& pCardMappingData, const QByteArray& pNonce); + bool generateEphemeralDomainParameters(const QByteArray& pRemoteMappingData, const QByteArray& pNonce); }; } // namespace governikus diff --git a/src/card/base/pace/ec/EcdhKeyAgreement.cpp b/src/card/base/pace/ec/EcdhKeyAgreement.cpp index 065cf388e..0f0ae0939 100644 --- a/src/card/base/pace/ec/EcdhKeyAgreement.cpp +++ b/src/card/base/pace/ec/EcdhKeyAgreement.cpp @@ -1,15 +1,17 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "EcdhKeyAgreement.h" #include "EcUtil.h" +#include "asn1/ASN1Struct.h" #include "asn1/ASN1Util.h" #include "asn1/PaceInfo.h" #include + using namespace governikus; @@ -17,17 +19,6 @@ Q_DECLARE_LOGGING_CATEGORY(card) Q_DECLARE_LOGGING_CATEGORY(secure) -QByteArray EcdhKeyAgreement::encodeUncompressedPublicKey(const QSharedPointer& pPaceInfo, const QSharedPointer& pCurve, const QSharedPointer& pPoint) -{ - const QByteArray& publicKeyData = - Asn1Util::encode(V_ASN1_UNIVERSAL, 6, pPaceInfo->getOid().getData()) + - Asn1Util::encode(V_ASN1_CONTEXT_SPECIFIC, 6, EcUtil::point2oct(pCurve, pPoint.data())); - const QByteArray publicKey = Asn1Util::encode(V_ASN1_APPLICATION, 73, publicKeyData, true); - - return publicKey; -} - - EcdhKeyAgreement::EcdhKeyAgreement(const QSharedPointer& pPaceInfo, const QSharedPointer& pCardConnectionWorker, const QSharedPointer& pMapping) @@ -84,7 +75,7 @@ KeyAgreement::CardResult EcdhKeyAgreement::determineSharedSecret(const QByteArra CardReturnCode EcdhKeyAgreement::determineEphemeralDomainParameters(const QByteArray& pNonce) { - QByteArray terminalMappingData = mMapping->generateTerminalMappingData(); + QByteArray terminalMappingData = mMapping->generateLocalMappingData(); auto [resultCode, cardMappingData] = transmitGAMappingData(terminalMappingData); if (resultCode != CardReturnCode::OK) { @@ -152,13 +143,13 @@ KeyAgreement::CardResult EcdhKeyAgreement::performKeyExchange() QByteArray EcdhKeyAgreement::getUncompressedTerminalPublicKey() { - return encodeUncompressedPublicKey(getPaceInfo(), mMapping->getCurve(), mTerminalPublicKey); + return encodeUncompressedPublicKey(getPaceInfo()->getOid(), EcUtil::point2oct(mMapping->getCurve(), mTerminalPublicKey.data())); } QByteArray EcdhKeyAgreement::getUncompressedCardPublicKey() { - return encodeUncompressedPublicKey(getPaceInfo(), mMapping->getCurve(), mCardPublicKey); + return encodeUncompressedPublicKey(getPaceInfo()->getOid(), EcUtil::point2oct(mMapping->getCurve(), mCardPublicKey.data())); } @@ -166,3 +157,11 @@ QByteArray EcdhKeyAgreement::getCompressedCardPublicKey() { return EcUtil::point2oct(mMapping->getCurve(), mCardPublicKey.data(), true); } + + +QByteArray EcdhKeyAgreement::encodeUncompressedPublicKey(const Oid& pOid, const QByteArray& pKey) +{ + const QByteArray oID = Asn1Util::encode(V_ASN1_UNIVERSAL, ASN1Struct::UNI_OBJECT_IDENTIFIER, QByteArray(pOid)); + const QByteArray publicPoint = Asn1Util::encode(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::EC_PUBLIC_POINT, pKey); + return Asn1Util::encode(V_ASN1_APPLICATION, ASN1Struct::PUBLIC_KEY, oID + publicPoint, true); +} diff --git a/src/card/base/pace/ec/EcdhKeyAgreement.h b/src/card/base/pace/ec/EcdhKeyAgreement.h index e8a480721..4eb2f2c76 100644 --- a/src/card/base/pace/ec/EcdhKeyAgreement.h +++ b/src/card/base/pace/ec/EcdhKeyAgreement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -29,8 +29,6 @@ class EcdhKeyAgreement CardReturnCode determineEphemeralDomainParameters(const QByteArray& pNonce); CardResult performKeyExchange(); - static QByteArray encodeUncompressedPublicKey(const QSharedPointer& pPaceInfo, const QSharedPointer& pCurve, const QSharedPointer& pPoint); - KeyAgreement::CardResult determineSharedSecret(const QByteArray& pNonce) override; QByteArray getUncompressedTerminalPublicKey() override; QByteArray getUncompressedCardPublicKey() override; @@ -43,6 +41,8 @@ class EcdhKeyAgreement public: static QSharedPointer create(const QSharedPointer& pPaceInfo, const QSharedPointer& pCardConnectionWorker); + + static QByteArray encodeUncompressedPublicKey(const Oid& pOid, const QByteArray& pKey); }; } // namespace governikus diff --git a/src/card/base/pinpad/DestroyPaceChannelBuilder.cpp b/src/card/base/pinpad/DestroyPaceChannelBuilder.cpp index 56cae7658..3b422e950 100644 --- a/src/card/base/pinpad/DestroyPaceChannelBuilder.cpp +++ b/src/card/base/pinpad/DestroyPaceChannelBuilder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "DestroyPaceChannelBuilder.h" @@ -12,7 +12,7 @@ using namespace governikus; -QByteArray DestroyPaceChannelBuilder::createCommandData() const +QByteArray DestroyPaceChannelBuilder::createASN1Struct() const { // Command data according to PC/SC Part 10 amendment 1.1 static const char INDEX_DESTROY_PACE_CHANNEL = 0x03; @@ -25,7 +25,7 @@ QByteArray DestroyPaceChannelBuilder::createCommandData() const } -CommandApdu DestroyPaceChannelBuilder::createCommandDataCcid() const +CommandApdu DestroyPaceChannelBuilder::createASN1StructCcid() const { return CommandApdu(CCID_DESTROY_PACE_CHANNEL); } diff --git a/src/card/base/pinpad/DestroyPaceChannelBuilder.h b/src/card/base/pinpad/DestroyPaceChannelBuilder.h index 47ba9e344..84bd27da3 100644 --- a/src/card/base/pinpad/DestroyPaceChannelBuilder.h +++ b/src/card/base/pinpad/DestroyPaceChannelBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -22,12 +22,12 @@ class DestroyPaceChannelBuilder /** * Defined in pcsc10_v2.02.08_amd1.1 */ - [[nodiscard]] QByteArray createCommandData() const; + [[nodiscard]] QByteArray createASN1Struct() const; /** * Defined in BSI-TR-03119_V1_pdf */ - [[nodiscard]] CommandApdu createCommandDataCcid() const; + [[nodiscard]] CommandApdu createASN1StructCcid() const; }; diff --git a/src/card/base/pinpad/EstablishPaceChannel.cpp b/src/card/base/pinpad/EstablishPaceChannel.cpp index e01c37ec8..175dde8ec 100644 --- a/src/card/base/pinpad/EstablishPaceChannel.cpp +++ b/src/card/base/pinpad/EstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "EstablishPaceChannel.h" @@ -232,7 +232,7 @@ QByteArray EstablishPaceChannel::createInputData() const } -QByteArray EstablishPaceChannel::createCommandData() const +QByteArray EstablishPaceChannel::createASN1Struct() const { // Command data according to PC/SC Part 10 amendment 1.1 static const char INDEX_ESTABLISH_PACE_CHANNEL = 0x02; @@ -255,7 +255,7 @@ QByteArray EstablishPaceChannel::createCommandData() const } -QByteArray EstablishPaceChannel::createCommandDataCcid() const +QByteArray EstablishPaceChannel::createASN1StructCcid() const { auto channelInput = newObject(); diff --git a/src/card/base/pinpad/EstablishPaceChannel.h b/src/card/base/pinpad/EstablishPaceChannel.h index 7212c0a22..9f8fd9e44 100644 --- a/src/card/base/pinpad/EstablishPaceChannel.h +++ b/src/card/base/pinpad/EstablishPaceChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -73,12 +73,12 @@ class EstablishPaceChannel /** * Defined in pcsc10_v2.02.08_amd1.1 section 2.5.12 */ - [[nodiscard]] QByteArray createCommandData() const; + [[nodiscard]] QByteArray createASN1Struct() const; /** * Defined in BSI-TR-03119_V1_pdf */ - [[nodiscard]] QByteArray createCommandDataCcid() const; + [[nodiscard]] QByteArray createASN1StructCcid() const; #ifndef QT_NO_DEBUG bool operator==(const EstablishPaceChannel& pOther) const diff --git a/src/card/base/pinpad/EstablishPaceChannelOutput.cpp b/src/card/base/pinpad/EstablishPaceChannelOutput.cpp index deac1de59..5100b8952 100644 --- a/src/card/base/pinpad/EstablishPaceChannelOutput.cpp +++ b/src/card/base/pinpad/EstablishPaceChannelOutput.cpp @@ -1,11 +1,10 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "EstablishPaceChannelOutput.h" #include "LengthValue.h" -#include "apdu/ResponseApdu.h" #include "asn1/ASN1Util.h" #include @@ -127,10 +126,11 @@ EstablishPaceChannelErrorCode EstablishPaceChannelOutput::generateReturnCode(Car case CardReturnCode::OK: case CardReturnCode::OK_PUK: + case CardReturnCode::OK_CAN: return EstablishPaceChannelErrorCode::NoError; case CardReturnCode::CARD_NOT_FOUND: - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: return EstablishPaceChannelErrorCode::NoCard; case CardReturnCode::INPUT_TIME_OUT: @@ -261,7 +261,7 @@ bool EstablishPaceChannelOutput::parseOutputData(const QByteArray& pOutput) // Response data according to PC/SC Part 10 amendment 1.1 mStatusMseSetAt = pOutput.mid(0, 2); - qCDebug(card) << "mStatusMseSetAt:" << mStatusMseSetAt.toHex() << StatusCode(qFromBigEndian(std::as_const(mStatusMseSetAt).data())); + qCDebug(card) << "mStatusMseSetAt:" << mStatusMseSetAt.toHex() << getStatusCodeMseSetAt(); int it = 2; const auto& efCardAccess = LengthValue::readByteArray(pOutput, it); @@ -345,7 +345,7 @@ bool EstablishPaceChannelOutput::parseFromCcid(const QByteArray& pOutput) if (channelOutput->mStatusMSESetAt) { mStatusMseSetAt = Asn1OctetStringUtil::getValue(channelOutput->mStatusMSESetAt); - qCDebug(card) << "mStatusMseSetAt:" << mStatusMseSetAt.toHex() << StatusCode(qFromBigEndian(std::as_const(mStatusMseSetAt).data())); + qCDebug(card) << "mStatusMseSetAt:" << mStatusMseSetAt.toHex() << getStatusCodeMseSetAt(); } if (channelOutput->mEfCardAccess) @@ -388,6 +388,12 @@ void EstablishPaceChannelOutput::setPaceReturnCode(CardReturnCode pPaceReturnCod } +StatusCode EstablishPaceChannelOutput::getStatusCodeMseSetAt() const +{ + return ResponseApdu(mStatusMseSetAt).getStatusCode(); +} + + const QByteArray& EstablishPaceChannelOutput::getStatusMseSetAt() const { return mStatusMseSetAt; diff --git a/src/card/base/pinpad/EstablishPaceChannelOutput.h b/src/card/base/pinpad/EstablishPaceChannelOutput.h index 07389e300..8ea4b6bd7 100644 --- a/src/card/base/pinpad/EstablishPaceChannelOutput.h +++ b/src/card/base/pinpad/EstablishPaceChannelOutput.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,7 @@ #pragma once #include "CardReturnCode.h" +#include "apdu/ResponseApdu.h" #include "asn1/SecurityInfos.h" #include "pace/EstablishPaceChannelCode.h" @@ -83,6 +84,7 @@ class EstablishPaceChannelOutput [[nodiscard]] CardReturnCode getPaceReturnCode() const; void setPaceReturnCode(CardReturnCode pPaceReturnCode); + [[nodiscard]] StatusCode getStatusCodeMseSetAt() const; [[nodiscard]] const QByteArray& getStatusMseSetAt() const; void setStatusMseSetAt(const QByteArray& pStatusMseSetAt); diff --git a/src/card/base/pinpad/LengthValue.h b/src/card/base/pinpad/LengthValue.h index 47190bcde..65cfce3b2 100644 --- a/src/card/base/pinpad/LengthValue.h +++ b/src/card/base/pinpad/LengthValue.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/base/pinpad/PinModify.cpp b/src/card/base/pinpad/PinModify.cpp index d5320bd26..8948c7b46 100644 --- a/src/card/base/pinpad/PinModify.cpp +++ b/src/card/base/pinpad/PinModify.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PinModify.h" diff --git a/src/card/base/pinpad/PinModify.h b/src/card/base/pinpad/PinModify.h index b9f0112b9..49f348291 100644 --- a/src/card/base/pinpad/PinModify.h +++ b/src/card/base/pinpad/PinModify.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/base/pinpad/PinModifyOutput.cpp b/src/card/base/pinpad/PinModifyOutput.cpp index a0f89b503..0a60b94bf 100644 --- a/src/card/base/pinpad/PinModifyOutput.cpp +++ b/src/card/base/pinpad/PinModifyOutput.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PinModifyOutput.h" diff --git a/src/card/base/pinpad/PinModifyOutput.h b/src/card/base/pinpad/PinModifyOutput.h index 2cdd15248..390eace97 100644 --- a/src/card/base/pinpad/PinModifyOutput.h +++ b/src/card/base/pinpad/PinModifyOutput.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/drivers/DeviceListener.cpp b/src/card/drivers/DeviceListener.cpp index 01bd1e81f..26a68076c 100644 --- a/src/card/drivers/DeviceListener.cpp +++ b/src/card/drivers/DeviceListener.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "DeviceListener.h" diff --git a/src/card/drivers/DeviceListener.h b/src/card/drivers/DeviceListener.h index d1606adbb..d04c4a4ca 100644 --- a/src/card/drivers/DeviceListener.h +++ b/src/card/drivers/DeviceListener.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/drivers/ReaderDetector.cpp b/src/card/drivers/ReaderDetector.cpp index 2eee65953..83af93b85 100644 --- a/src/card/drivers/ReaderDetector.cpp +++ b/src/card/drivers/ReaderDetector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderDetector.h" @@ -31,10 +31,10 @@ ReaderDetector::~ReaderDetector() } -QVector ReaderDetector::getAttachedSupportedDevices() const +QList ReaderDetector::getAttachedSupportedDevices() const { const auto& readerConfiguration = Env::getSingleton(); - QVector attachedSupportedDevices; + QList attachedSupportedDevices; const auto& devIds = attachedDevIds(); for (const auto& devId : devIds) @@ -51,7 +51,7 @@ QVector ReaderDetector::getAttachedSupportedDevices() c ReaderConfigurationInfo ReaderDetector::getReaderConfigurationInfo(const QString& pReaderName) const { - QVector attachedSupportedDevices = getAttachedSupportedDevices(); + QList attachedSupportedDevices = getAttachedSupportedDevices(); attachedSupportedDevices += Env::getSingleton()->getVirtualReaderConfigurationInfos(); for (const auto& info : std::as_const(attachedSupportedDevices)) diff --git a/src/card/drivers/ReaderDetector.h b/src/card/drivers/ReaderDetector.h index 35ab24cb8..c2fd4776a 100644 --- a/src/card/drivers/ReaderDetector.h +++ b/src/card/drivers/ReaderDetector.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -25,8 +25,8 @@ #include #endif +#include #include -#include namespace governikus { @@ -59,7 +59,7 @@ class ReaderDetector ~ReaderDetector() override; public: - [[nodiscard]] virtual QVector attachedDevIds() const; + [[nodiscard]] virtual QList attachedDevIds() const; #ifdef Q_OS_WIN bool nativeEventFilter(const QByteArray& pEventType, void* pMessage, qintptr* pResult) override; @@ -69,7 +69,7 @@ class ReaderDetector * \brief getAttachedDevices produce a list of supported devices that are * attached to the system */ - [[nodiscard]] QVector getAttachedSupportedDevices() const; + [[nodiscard]] QList getAttachedSupportedDevices() const; [[nodiscard]] ReaderConfigurationInfo getReaderConfigurationInfo(const QString& pReaderName) const; diff --git a/src/card/drivers/ReaderDetector_generic.cpp b/src/card/drivers/ReaderDetector_generic.cpp index d8ae0afa7..21a49fd5f 100644 --- a/src/card/drivers/ReaderDetector_generic.cpp +++ b/src/card/drivers/ReaderDetector_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderDetector.h" @@ -20,7 +20,7 @@ bool ReaderDetector::terminateNativeEvents() } -QVector ReaderDetector::attachedDevIds() const +QList ReaderDetector::attachedDevIds() const { - return QVector(); + return QList(); } diff --git a/src/card/drivers/ReaderDetector_linux.cpp b/src/card/drivers/ReaderDetector_linux.cpp index cc4f193fe..08f6468f9 100644 --- a/src/card/drivers/ReaderDetector_linux.cpp +++ b/src/card/drivers/ReaderDetector_linux.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderDetector.h" @@ -38,9 +38,9 @@ bool ReaderDetector::terminateNativeEvents() } -QVector ReaderDetector::attachedDevIds() const +QList ReaderDetector::attachedDevIds() const { - QVector result; + QList result; #if __has_include() // http://www.signal11.us/oss/udev/ diff --git a/src/card/drivers/ReaderDetector_osx.cpp b/src/card/drivers/ReaderDetector_osx.cpp index 9629666a7..06cf79539 100644 --- a/src/card/drivers/ReaderDetector_osx.cpp +++ b/src/card/drivers/ReaderDetector_osx.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderDetector.h" @@ -39,7 +39,7 @@ static bool listenTo(const io_name_t notificationType, ReaderDetector* readerDet //https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/AH_Finding_Devices.html CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); - IONotificationPortRef notificationObject = IONotificationPortCreate(kIOMasterPortDefault); + IONotificationPortRef notificationObject = IONotificationPortCreate(kIOMainPortDefault); CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject); CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); kern_return_t kr = IOServiceAddMatchingNotification( @@ -146,22 +146,20 @@ static UsbId getDeviceIds(io_object_t pDevice) } -QVector ReaderDetector::attachedDevIds() const +QList ReaderDetector::attachedDevIds() const { - QVector result; - mach_port_t myMasterPort = kIOMasterPortDefault; + QList result; io_iterator_t deviceIterator = 0; - io_object_t currentDevice = 0; - kern_return_t createIteratorResult = IORegistryCreateIterator(myMasterPort, kIOUSBPlane, kIORegistryIterateRecursively, &deviceIterator); + kern_return_t createIteratorResult = IORegistryCreateIterator(kIOMainPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &deviceIterator); if (createIteratorResult != kIOReturnSuccess) { qCWarning(card_drivers) << "creation of device iterator failed, exiting"; - return QVector(); + return QList(); } - currentDevice = IOIteratorNext(deviceIterator); + io_object_t currentDevice = IOIteratorNext(deviceIterator); while (currentDevice != 0) { UsbId ids = getDeviceIds(currentDevice); diff --git a/src/card/drivers/ReaderDetector_win.cpp b/src/card/drivers/ReaderDetector_win.cpp index 81323d7e8..694013b4a 100644 --- a/src/card/drivers/ReaderDetector_win.cpp +++ b/src/card/drivers/ReaderDetector_win.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderDetector.h" @@ -109,9 +109,9 @@ static uint getProductId(const QString& pDevId) } -QVector ReaderDetector::attachedDevIds() const +QList ReaderDetector::attachedDevIds() const { - QVector result; + QList result; for (auto stringDevId : attachedDevStringIds()) { diff --git a/src/card/nfc/NfcCard.cpp b/src/card/nfc/NfcCard.cpp index eab0c56dc..2f18553d7 100644 --- a/src/card/nfc/NfcCard.cpp +++ b/src/card/nfc/NfcCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "NfcCard.h" @@ -90,6 +90,13 @@ void NfcCard::setProgressMessage(const QString& pMessage, int pProgress) } +void NfcCard::setErrorMessage(const QString& pMessage) +{ + QString message = generateErrorMessage(pMessage); + Q_EMIT fireSetProgressMessage(message); +} + + ResponseApduResult NfcCard::transmit(const CommandApdu& pCmd) { if (!mIsValid || mNearFieldTarget == nullptr) @@ -113,12 +120,7 @@ ResponseApduResult NfcCard::transmit(const CommandApdu& pCmd) return {CardReturnCode::COMMAND_FAILED}; } -#if defined(Q_OS_IOS) - constexpr int timeoutMsecs = 3000; -#else - constexpr int timeoutMsecs = 1500; -#endif - if (!mNearFieldTarget->waitForRequestCompleted(id, timeoutMsecs)) + if (!mNearFieldTarget->waitForRequestCompleted(id, 3000)) { qCWarning(card_nfc) << "Transmit timeout reached"; return {CardReturnCode::COMMAND_FAILED}; @@ -132,6 +134,7 @@ ResponseApduResult NfcCard::transmit(const CommandApdu& pCmd) } const QByteArray recvBuffer = response.toByteArray(); - qCDebug(card_nfc) << "Transmit response APDU:" << recvBuffer.toHex(); - return {CardReturnCode::OK, ResponseApdu(recvBuffer)}; + const ResponseApdu responseApdu(recvBuffer); + qCDebug(card_nfc) << "Transmit response APDU:" << responseApdu; + return {CardReturnCode::OK, responseApdu}; } diff --git a/src/card/nfc/NfcCard.h b/src/card/nfc/NfcCard.h index e92dc846d..f69a6deef 100644 --- a/src/card/nfc/NfcCard.h +++ b/src/card/nfc/NfcCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -36,6 +36,7 @@ class NfcCard CardReturnCode releaseConnection() override; bool isConnected() const override; void setProgressMessage(const QString& pMessage, int pProgress = -1) override; + void setErrorMessage(const QString& pMessage) override; ResponseApduResult transmit(const CommandApdu& pCmd) override; diff --git a/src/card/nfc/NfcReader.cpp b/src/card/nfc/NfcReader.cpp index 1c552f5fc..d0efc6af1 100644 --- a/src/card/nfc/NfcReader.cpp +++ b/src/card/nfc/NfcReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "NfcReader.h" @@ -45,6 +45,22 @@ void NfcReader::targetDetected(QNearFieldTarget* pTarget) mCard.reset(new NfcCard(pTarget)); connect(mCard.data(), &NfcCard::fireSetProgressMessage, this, &NfcReader::setProgressMessage); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)) + #define GOV_UNSUPPORTED_TARGET_ERROR UnsupportedTargetError +#elif defined(GOVERNIKUS_QT) && (QT_VERSION >= QT_VERSION_CHECK(6, 6, 3)) + #define GOV_UNSUPPORTED_TARGET_ERROR SecurityViolation +#endif +#ifdef GOV_UNSUPPORTED_TARGET_ERROR + connect(mCard.data(), &NfcCard::fireTargetError, this, [this](QNearFieldTarget::Error pError) { + if (pError == QNearFieldTarget::GOV_UNSUPPORTED_TARGET_ERROR) + { + setInfoCardInfo(CardInfo(CardType::UNKNOWN)); + qCInfo(card_nfc) << "Card inserted:" << getReaderInfo().getCardInfo(); + Q_EMIT fireCardInserted(getReaderInfo()); + } + }); + #undef GOV_UNSUPPORTED_TARGET_ERROR +#endif fetchCardInfo(); if (!getCard()) @@ -68,12 +84,13 @@ void NfcReader::targetDetected(QNearFieldTarget* pTarget) } const auto& info = Env::getSingleton()->isUsedAsSDK() - ? Env::getSingleton()->getMessages().getSessionInProgress() + ? Card::generateProgressMessage(QString(), 0) //: INFO IOS Feedback when a new ID card has been detected : tr("ID card detected. Please do not move the device!"); mNfManager.setUserInformation(info); + qCInfo(card_nfc) << "Card inserted:" << getReaderInfo().getCardInfo(); Q_EMIT fireCardInserted(getReaderInfo()); } @@ -84,8 +101,14 @@ void NfcReader::targetLost(QNearFieldTarget* pTarget) if (pTarget != nullptr && mCard && mCard->invalidateTarget(pTarget)) { mCard.reset(); - removeCardInfo(); - Q_EMIT fireCardRemoved(getReaderInfo()); + + if (getReaderInfo().getCardInfo().getCardType() != CardType::NONE) + { + removeCardInfo(); + + qCInfo(card_nfc) << "Card removed"; + Q_EMIT fireCardRemoved(getReaderInfo()); + } } } @@ -97,7 +120,7 @@ void NfcReader::setProgressMessage(const QString& pMessage) NfcReader::NfcReader() - : ConnectableReader(ReaderManagerPlugInType::NFC, QStringLiteral("NFC")) + : ConnectableReader(ReaderManagerPluginType::NFC, QStringLiteral("NFC")) , mNfManager() , mCard() { @@ -168,7 +191,7 @@ void NfcReader::disconnectReader(const QString& pError) : tr("Scanning process has been finished successfully."); mNfManager.setUserInformation(info); } - mNfManager.stopTargetDetection(pError); + mNfManager.stopTargetDetection(Card::generateErrorMessage(pError)); #else Q_UNUSED(pError) #endif diff --git a/src/card/nfc/NfcReader.h b/src/card/nfc/NfcReader.h index 658f658c7..e5773aa34 100644 --- a/src/card/nfc/NfcReader.h +++ b/src/card/nfc/NfcReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/nfc/NfcReaderManagerPlugIn.cpp b/src/card/nfc/NfcReaderManagerPlugin.cpp similarity index 65% rename from src/card/nfc/NfcReaderManagerPlugIn.cpp rename to src/card/nfc/NfcReaderManagerPlugin.cpp index 841c9845f..b96c1e90f 100644 --- a/src/card/nfc/NfcReaderManagerPlugIn.cpp +++ b/src/card/nfc/NfcReaderManagerPlugin.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ -#include "NfcReaderManagerPlugIn.h" +#include "NfcReaderManagerPlugin.h" #include #include @@ -17,10 +17,10 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_nfc) -QAtomicPointer NfcReaderManagerPlugIn::instance = nullptr; +QAtomicPointer NfcReaderManagerPlugin::instance = nullptr; -void NfcReaderManagerPlugIn::onNfcAdapterStateChanged(bool pEnabled) +void NfcReaderManagerPlugin::onNfcAdapterStateChanged(bool pEnabled) { if (getInfo().isEnabled() == pEnabled || !mNfcReader) { @@ -28,7 +28,7 @@ void NfcReaderManagerPlugIn::onNfcAdapterStateChanged(bool pEnabled) } qCDebug(card_nfc) << "NfcAdapterStateChanged:" << pEnabled; - setPlugInEnabled(pEnabled); + setPluginEnabled(pEnabled); if (pEnabled) { Q_EMIT fireReaderAdded(mNfcReader->getReaderInfo()); @@ -49,13 +49,13 @@ void NfcReaderManagerPlugIn::onNfcAdapterStateChanged(bool pEnabled) } -void NfcReaderManagerPlugIn::onReaderDisconnected() +void NfcReaderManagerPlugin::onReaderDisconnected() { - ReaderManagerPlugIn::stopScan(); + ReaderManagerPlugin::stopScan(); } -void NfcReaderManagerPlugIn::setReaderMode(bool pEnabled) +void NfcReaderManagerPlugin::setReaderMode(bool pEnabled) { #ifdef Q_OS_ANDROID if (QNativeInterface::QAndroidApplication::isActivityContext()) @@ -71,9 +71,9 @@ void NfcReaderManagerPlugIn::setReaderMode(bool pEnabled) } -void NfcReaderManagerPlugIn::enqueueReaderMode(bool pEnabled) +void NfcReaderManagerPlugin::enqueueReaderMode(bool pEnabled) { - if (auto* plugin = NfcReaderManagerPlugIn::instance.loadRelaxed()) + if (auto* plugin = NfcReaderManagerPlugin::instance.loadRelaxed()) { QMetaObject::invokeMethod(plugin, [plugin, pEnabled] { if (plugin->mNfcReader) @@ -95,7 +95,7 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_MainActivity_setReaderMod Q_UNUSED(pEnv) Q_UNUSED(pObj) - NfcReaderManagerPlugIn::enqueueReaderMode(pEnabled); + NfcReaderManagerPlugin::enqueueReaderMode(pEnabled); } @@ -103,8 +103,8 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_MainActivity_setReaderMod #endif -NfcReaderManagerPlugIn::NfcReaderManagerPlugIn() - : ReaderManagerPlugIn(ReaderManagerPlugInType::NFC, +NfcReaderManagerPlugin::NfcReaderManagerPlugin() + : ReaderManagerPlugin(ReaderManagerPluginType::NFC, QNearFieldManager().isSupported(QNearFieldTarget::TagTypeSpecificAccess) ) , mNfcReader(nullptr) @@ -113,13 +113,13 @@ NfcReaderManagerPlugIn::NfcReaderManagerPlugIn() } -NfcReaderManagerPlugIn::~NfcReaderManagerPlugIn() +NfcReaderManagerPlugin::~NfcReaderManagerPlugin() { instance = nullptr; } -QList NfcReaderManagerPlugIn::getReaders() const +QList NfcReaderManagerPlugin::getReaders() const { if (getInfo().isEnabled() && mNfcReader) { @@ -130,9 +130,9 @@ QList NfcReaderManagerPlugIn::getReaders() const } -void NfcReaderManagerPlugIn::init() +void NfcReaderManagerPlugin::init() { - ReaderManagerPlugIn::init(); + ReaderManagerPlugin::init(); if (!getInfo().isAvailable() || mNfcReader) { @@ -140,12 +140,12 @@ void NfcReaderManagerPlugIn::init() } mNfcReader.reset(new NfcReader()); - connect(mNfcReader.data(), &NfcReader::fireCardInserted, this, &NfcReaderManagerPlugIn::fireCardInserted); - connect(mNfcReader.data(), &NfcReader::fireCardRemoved, this, &NfcReaderManagerPlugIn::fireCardRemoved); - connect(mNfcReader.data(), &NfcReader::fireCardInfoChanged, this, &NfcReaderManagerPlugIn::fireCardInfoChanged); - connect(mNfcReader.data(), &NfcReader::fireReaderPropertiesUpdated, this, &NfcReaderManagerPlugIn::fireReaderPropertiesUpdated); - connect(mNfcReader.data(), &NfcReader::fireNfcAdapterStateChanged, this, &NfcReaderManagerPlugIn::onNfcAdapterStateChanged); - connect(mNfcReader.data(), &NfcReader::fireReaderDisconnected, this, &NfcReaderManagerPlugIn::onReaderDisconnected); + connect(mNfcReader.data(), &NfcReader::fireCardInserted, this, &NfcReaderManagerPlugin::fireCardInserted); + connect(mNfcReader.data(), &NfcReader::fireCardRemoved, this, &NfcReaderManagerPlugin::fireCardRemoved); + connect(mNfcReader.data(), &NfcReader::fireCardInfoChanged, this, &NfcReaderManagerPlugin::fireCardInfoChanged); + connect(mNfcReader.data(), &NfcReader::fireReaderPropertiesUpdated, this, &NfcReaderManagerPlugin::fireReaderPropertiesUpdated); + connect(mNfcReader.data(), &NfcReader::fireNfcAdapterStateChanged, this, &NfcReaderManagerPlugin::onNfcAdapterStateChanged); + connect(mNfcReader.data(), &NfcReader::fireReaderDisconnected, this, &NfcReaderManagerPlugin::onReaderDisconnected); qCDebug(card_nfc) << "Add reader" << mNfcReader->getName(); setReaderMode(true); @@ -153,7 +153,7 @@ void NfcReaderManagerPlugIn::init() } -void NfcReaderManagerPlugIn::shutdown() +void NfcReaderManagerPlugin::shutdown() { if (mNfcReader) { @@ -164,21 +164,21 @@ void NfcReaderManagerPlugIn::shutdown() } -void NfcReaderManagerPlugIn::startScan(bool pAutoConnect) +void NfcReaderManagerPlugin::startScan(bool pAutoConnect) { if (mNfcReader) { mNfcReader->connectReader(); - ReaderManagerPlugIn::startScan(pAutoConnect); + ReaderManagerPlugin::startScan(pAutoConnect); } } -void NfcReaderManagerPlugIn::stopScan(const QString& pError) +void NfcReaderManagerPlugin::stopScan(const QString& pError) { if (mNfcReader) { mNfcReader->disconnectReader(pError); - ReaderManagerPlugIn::stopScan(pError); + ReaderManagerPlugin::stopScan(pError); } } diff --git a/src/card/nfc/NfcReaderManagerPlugIn.h b/src/card/nfc/NfcReaderManagerPlugin.h similarity index 59% rename from src/card/nfc/NfcReaderManagerPlugIn.h rename to src/card/nfc/NfcReaderManagerPlugin.h index 3fc53f2cf..378fb5688 100644 --- a/src/card/nfc/NfcReaderManagerPlugIn.h +++ b/src/card/nfc/NfcReaderManagerPlugin.h @@ -1,15 +1,15 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Implementation of \ref ReaderManagerPlugIn for NFC on Android. + * \brief Implementation of \ref ReaderManagerPlugin for NFC on Android. */ #pragma once #include "NfcReader.h" -#include "ReaderManagerPlugIn.h" +#include "ReaderManagerPlugin.h" #include #include @@ -18,15 +18,15 @@ namespace governikus { -class NfcReaderManagerPlugIn - : public ReaderManagerPlugIn +class NfcReaderManagerPlugin + : public ReaderManagerPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) private: - static QAtomicPointer instance; + static QAtomicPointer instance; QScopedPointer mNfcReader; @@ -38,8 +38,8 @@ class NfcReaderManagerPlugIn static void setReaderMode(bool pEnabled); static void enqueueReaderMode(bool pEnabled); - NfcReaderManagerPlugIn(); - ~NfcReaderManagerPlugIn() override; + NfcReaderManagerPlugin(); + ~NfcReaderManagerPlugin() override; [[nodiscard]] QList getReaders() const override; diff --git a/src/card/nfc/metadata.json b/src/card/nfc/metadata.json index 68f991325..9d968cfcb 100644 --- a/src/card/nfc/metadata.json +++ b/src/card/nfc/metadata.json @@ -1,4 +1,4 @@ { - "name" : "NfcReaderManagerPlugIn", + "name" : "NfcReaderManagerPlugin", "dependencies" : [] } diff --git a/src/card/pcsc/PcscCard.cpp b/src/card/pcsc/PcscCard.cpp index 57ba32458..6c52664cb 100644 --- a/src/card/pcsc/PcscCard.cpp +++ b/src/card/pcsc/PcscCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PcscCard.h" @@ -264,7 +264,7 @@ PcscCard::CardResult PcscCard::transmit(const QByteArray& pSendBuffer, QByteArray data(8192, '\0'); auto dataReceived = static_cast(data.size()); - qCDebug(card_pcsc) << "SCardTransmit cmdBuffer:" << pSendBuffer.toHex(); + qCDebug(card_pcsc) << "Transmit command APDU::" << CommandApdu(pSendBuffer); const PCSC_RETURNCODE returnCode = SCardTransmit(mCardHandle, pSendPci, reinterpret_cast(pSendBuffer.data()), @@ -273,13 +273,13 @@ PcscCard::CardResult PcscCard::transmit(const QByteArray& pSendBuffer, reinterpret_cast(data.data()), &dataReceived); - qCDebug(card_pcsc) << "SCardTransmit for" << mReader->getName() << ':' << pcsc::toString(returnCode); + qCDebug(card_pcsc) << "Transmit for" << mReader->getName() << ':' << pcsc::toString(returnCode); switch (returnCode) { case pcsc::Scard_S_Success: data.resize(static_cast(dataReceived)); - qCDebug(card_pcsc) << "SCardTransmit resBuffer:" << data.toHex(); + qCDebug(card_pcsc) << "Transmit response APDU:" << ResponseApdu(data); if (data.size() < 2) { @@ -320,19 +320,18 @@ PcscCard::CardResult PcscCard::transmit(const QByteArray& pSendBuffer, EstablishPaceChannelOutput PcscCard::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, - const QByteArray& pCertificateDescription, - quint8 pTimeoutSeconds) + const QByteArray& pCertificateDescription) { Q_UNUSED(pPreferredPinLength) - Q_UNUSED(pTimeoutSeconds) + if (!mReader->hasFeature(FeatureID::EXECUTE_PACE)) { return EstablishPaceChannelOutput(CardReturnCode::COMMAND_FAILED); } - PCSC_INT cmdID = mReader->getFeatureValue(FeatureID::EXECUTE_PACE); + PCSC_INT cmdID = mReader->getFeatureValue(FeatureID::EXECUTE_PACE); EstablishPaceChannel builder(pPasswordId, pChat, pCertificateDescription); - auto [returnCode, controlRes] = control(cmdID, builder.createCommandData()); + auto [returnCode, controlRes] = control(cmdID, builder.createASN1Struct()); if (returnCode != pcsc::Scard_S_Success) { qCWarning(card_pcsc) << "Control to establish PACE channel failed"; @@ -357,7 +356,7 @@ CardReturnCode PcscCard::destroyPaceChannel() PCSC_INT cmdID = mReader->getFeatureValue(FeatureID::EXECUTE_PACE); DestroyPaceChannelBuilder builder; - auto [returnCode, controlRes] = control(cmdID, builder.createCommandData()); + auto [returnCode, controlRes] = control(cmdID, builder.createASN1Struct()); if (returnCode != pcsc::Scard_S_Success) { qCWarning(card_pcsc) << "Control to destroy PACE channel failed"; @@ -404,8 +403,8 @@ ResponseApduResult PcscCard::setEidPin(quint8 pTimeoutSeconds) { return {CardReturnCode::COMMAND_FAILED}; } - PCSC_INT cmdID = mReader->getFeatureValue(FeatureID::MODIFY_PIN_DIRECT); + PCSC_INT cmdID = mReader->getFeatureValue(FeatureID::MODIFY_PIN_DIRECT); PinModify pinModify(pTimeoutSeconds); auto [returnCode, controlRes] = control(cmdID, pinModify.createCcid()); if (returnCode != pcsc::Scard_S_Success) diff --git a/src/card/pcsc/PcscCard.h b/src/card/pcsc/PcscCard.h index e7d17432b..f9e4cee6c 100644 --- a/src/card/pcsc/PcscCard.h +++ b/src/card/pcsc/PcscCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -57,7 +57,7 @@ class PcscCard ResponseApduResult transmit(const CommandApdu& pCmd) override; - EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds) override; + EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) override; CardReturnCode destroyPaceChannel() override; diff --git a/src/card/pcsc/PcscReader.cpp b/src/card/pcsc/PcscReader.cpp index 72485a177..dd1cc4b7a 100644 --- a/src/card/pcsc/PcscReader.cpp +++ b/src/card/pcsc/PcscReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PcscCard.h" @@ -10,13 +10,23 @@ #include +#if defined(Q_OS_MACOS) + #define CM_IOCTL_GET_FEATURE_REQUEST (0x42000000 + 3400) +#elif defined(PCSCLITE_VERSION_NUMBER) + #include +#else +// PC/SC Part 10 v2.02.09 November 2012 - 2.2 GET_FEATURE_REQUEST + #define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) +#endif + + using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_pcsc) PcscReader::PcscReader(const QString& pReaderName) - : Reader(ReaderManagerPlugInType::PCSC, pReaderName) + : Reader(ReaderManagerPluginType::PCSC, pReaderName) , mReaderState() , mReaderFeatures(nullptr) , mPcscCard() @@ -156,46 +166,26 @@ static QString SCARD_STATE_toString(DWORD i) void PcscReader::updateCard() { - PCSC_RETURNCODE returnCode = SCardGetStatusChange(mContextHandle, 0, &mReaderState, 1); - if (returnCode == pcsc::Scard_E_Timeout) + if (!readCardStatus()) { return; } - else if (returnCode == pcsc::Scard_E_Unknown_Reader) - { - qCWarning(card_pcsc) << "SCardGetStatusChange:" << pcsc::toString(returnCode); - qCWarning(card_pcsc) << "Reader unknown, stop updating reader information"; - if (getTimerId() != 0) - { - killTimer(getTimerId()); - setTimerId(0); - } - return; - } - else if (returnCode != pcsc::Scard_S_Success) - { - qCWarning(card_pcsc) << "SCardGetStatusChange:" << pcsc::toString(returnCode); - qCWarning(card_pcsc) << "Cannot update reader"; - return; - } - else if ((mReaderState.dwEventState & SCARD_STATE_CHANGED) == 0) + + if ((mReaderState.dwEventState & SCARD_STATE_CHANGED) == 0) { return; } - else if ((mReaderState.dwEventState & (SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE)) != 0) + + if (mReaderState.dwEventState & (SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE)) { return; } qCDebug(card_pcsc) << "old state:" << SCARD_STATE_toString(mReaderState.dwCurrentState) << "| new state:" << SCARD_STATE_toString(mReaderState.dwEventState); - - bool newPresent = (mReaderState.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT; - bool newExclusive = (mReaderState.dwEventState & SCARD_STATE_EXCLUSIVE) == SCARD_STATE_EXCLUSIVE; - mReaderState.dwCurrentState = mReaderState.dwEventState; - if (!newPresent) + if ((mReaderState.dwCurrentState & SCARD_STATE_PRESENT) == 0) { if (!mPcscCard.isNull()) { @@ -208,34 +198,37 @@ void PcscReader::updateCard() return; } - if (mPcscCard || newExclusive) + if (mPcscCard || (mReaderState.dwCurrentState & SCARD_STATE_EXCLUSIVE)) { return; } qCDebug(card_pcsc) << "ATR:" << QByteArray(reinterpret_cast(mReaderState.rgbAtr), static_cast(mReaderState.cbAtr)).toHex(' '); - static const int MAX_TRY_COUNT = 5; - for (int tryCount = 0; tryCount < MAX_TRY_COUNT; ++tryCount) +#ifdef Q_OS_MACOS + for (int tryCount = 0; tryCount < 3; ++tryCount) +#endif { mPcscCard.reset(new PcscCard(this)); fetchCardInfo(); - if (getReaderInfo().hasEid()) +#ifdef Q_OS_MACOS + if (getReaderInfo().getCardType() == CardType::UNKNOWN) { - break; + qCDebug(card_pcsc) << "Unknown card detected, retrying"; + continue; } - qCDebug(card_pcsc) << "Unknown card detected, retrying"; + break; +#endif } qCInfo(card_pcsc) << "Card inserted:" << getReaderInfo().getCardInfo(); - fetchGetReaderInfo(); Q_EMIT fireCardInserted(getReaderInfo()); } -void PcscReader::fetchGetReaderInfo() +void PcscReader::printGetReaderInfo() const { if (mPcscCard.isNull()) { @@ -294,13 +287,6 @@ PCSC_RETURNCODE PcscReader::readReaderFeatures() qCDebug(card_pcsc) << "SCardDisconnect for" << readerName << ':' << pcsc::toString(disconnectCode); }); - // control (get features) -#if defined(PCSCLITE_VERSION_NUMBER) - PCSC_INT CM_IOCTL_GET_FEATURE_REQUEST = 0x42000D48; -#else - PCSC_INT CM_IOCTL_GET_FEATURE_REQUEST = 0x00313520; -#endif - QByteArray buffer(1024, '\0'); const std::array inBuffer({0, 0}); @@ -326,6 +312,36 @@ PCSC_RETURNCODE PcscReader::readReaderFeatures() } +bool PcscReader::readCardStatus() +{ + PCSC_RETURNCODE returnCode = SCardGetStatusChange(mContextHandle, 0, &mReaderState, 1); + switch (returnCode) + { + case pcsc::Scard_S_Success: + return true; + + case pcsc::Scard_E_Timeout: + break; + + case pcsc::Scard_E_Unknown_Reader: + qCWarning(card_pcsc) << "SCardGetStatusChange:" << pcsc::toString(returnCode); + qCWarning(card_pcsc) << "Reader unknown, stop updating reader information"; + if (getTimerId() != 0) + { + killTimer(getTimerId()); + setTimerId(0); + } + break; + + default: + qCWarning(card_pcsc) << "SCardGetStatusChange:" << pcsc::toString(returnCode); + qCWarning(card_pcsc) << "Cannot update reader"; + break; + } + return false; +} + + Card* PcscReader::getCard() const { return mPcscCard.data(); diff --git a/src/card/pcsc/PcscReader.h b/src/card/pcsc/PcscReader.h index 7d121b8e3..9d1c78157 100644 --- a/src/card/pcsc/PcscReader.h +++ b/src/card/pcsc/PcscReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -33,9 +33,10 @@ class PcscReader SCARDCONTEXT mContextHandle; - void fetchGetReaderInfo(); PCSC_RETURNCODE readReaderFeatures(); + [[nodiscard]] bool readCardStatus(); + void updateCard() override; public: @@ -43,6 +44,8 @@ class PcscReader [[nodiscard]] PCSC_RETURNCODE init(); ~PcscReader() override; + void printGetReaderInfo() const override; + [[nodiscard]] Card* getCard() const override; [[nodiscard]] SCARD_READERSTATE getState() const; diff --git a/src/card/pcsc/PcscReaderFeature.cpp b/src/card/pcsc/PcscReaderFeature.cpp index 994d467d0..55d72c9ad 100644 --- a/src/card/pcsc/PcscReaderFeature.cpp +++ b/src/card/pcsc/PcscReaderFeature.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PcscReaderFeature.h" diff --git a/src/card/pcsc/PcscReaderFeature.h b/src/card/pcsc/PcscReaderFeature.h index d6bdc10ac..d8c6f4fc4 100644 --- a/src/card/pcsc/PcscReaderFeature.h +++ b/src/card/pcsc/PcscReaderFeature.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/pcsc/PcscReaderManagerPlugIn.cpp b/src/card/pcsc/PcscReaderManagerPlugin.cpp similarity index 79% rename from src/card/pcsc/PcscReaderManagerPlugIn.cpp rename to src/card/pcsc/PcscReaderManagerPlugin.cpp index 69fb1a106..8efc191c5 100644 --- a/src/card/pcsc/PcscReaderManagerPlugIn.cpp +++ b/src/card/pcsc/PcscReaderManagerPlugin.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ -#include "PcscReaderManagerPlugIn.h" +#include "PcscReaderManagerPlugin.h" #include "PcscReader.h" @@ -15,22 +15,22 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_pcsc) -PcscReaderManagerPlugIn::PcscReaderManagerPlugIn() - : ReaderManagerPlugIn(ReaderManagerPlugInType::PCSC, true) +PcscReaderManagerPlugin::PcscReaderManagerPlugin() + : ReaderManagerPlugin(ReaderManagerPluginType::PCSC, true) , mContextHandle(0) , mTimer() , mReaders() { setObjectName(QStringLiteral("PcscReaderManager")); - connect(&mTimer, &QTimer::timeout, this, &PcscReaderManagerPlugIn::updateReaders); + connect(&mTimer, &QTimer::timeout, this, &PcscReaderManagerPlugin::updateReaders); #ifdef PCSCLITE_VERSION_NUMBER - setPlugInValue(ReaderManagerPlugInInfo::Key::PCSC_LITE_VERSION, QStringLiteral(PCSCLITE_VERSION_NUMBER)); + setPluginValue(ReaderManagerPluginInfo::Key::PCSC_LITE_VERSION, QStringLiteral(PCSCLITE_VERSION_NUMBER)); #endif } -PcscReaderManagerPlugIn::~PcscReaderManagerPlugIn() +PcscReaderManagerPlugin::~PcscReaderManagerPlugin() { Q_ASSERT(!mTimer.isActive()); Q_ASSERT(mContextHandle == 0); @@ -42,29 +42,30 @@ PcscReaderManagerPlugIn::~PcscReaderManagerPlugIn() } -QList PcscReaderManagerPlugIn::getReaders() const +QList PcscReaderManagerPlugin::getReaders() const { return mReaders.values(); } -void PcscReaderManagerPlugIn::startScan(bool pAutoConnect) +void PcscReaderManagerPlugin::startScan(bool pAutoConnect) { PCSC_RETURNCODE returnCode = SCardEstablishContext(SCARD_SCOPE_USER, nullptr, nullptr, &mContextHandle); - setPlugInEnabled(returnCode == pcsc::Scard_S_Success); + setPluginEnabled(returnCode == pcsc::Scard_S_Success); qCDebug(card_pcsc) << "SCardEstablishContext:" << pcsc::toString(returnCode); if (!getInfo().isEnabled()) { qCWarning(card_pcsc) << "Not started: Cannot establish context"; + setInitialScanState(ReaderManagerPluginInfo::InitialScan::FAILED); return; } mTimer.start(500); - ReaderManagerPlugIn::startScan(pAutoConnect); + ReaderManagerPlugin::startScan(pAutoConnect); } -void PcscReaderManagerPlugIn::stopScan(const QString& pError) +void PcscReaderManagerPlugin::stopScan(const QString& pError) { mTimer.stop(); @@ -79,17 +80,18 @@ void PcscReaderManagerPlugIn::stopScan(const QString& pError) } } removeReaders(mReaders.keys()); - ReaderManagerPlugIn::stopScan(pError); + ReaderManagerPlugin::stopScan(pError); } -void PcscReaderManagerPlugIn::updateReaders() +void PcscReaderManagerPlugin::updateReaders() { QStringList readersToAdd; PCSC_RETURNCODE returnCode = readReaderNames(readersToAdd); if (returnCode != pcsc::Scard_S_Success && returnCode != pcsc::Scard_E_No_Readers_Available) { qCWarning(card_pcsc) << "Cannot update readers, returnCode:" << returnCode; + setInitialScanState(ReaderManagerPluginInfo::InitialScan::FAILED); if (returnCode == pcsc::Scard_E_No_Service && mTimer.isActive()) { @@ -134,10 +136,11 @@ void PcscReaderManagerPlugIn::updateReaders() removeReaders(readersToRemove); addReaders(readersToAdd); + setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); } -QString PcscReaderManagerPlugIn::extractReaderName(const PCSC_CHAR_PTR pReaderPointer) const +QString PcscReaderManagerPlugin::extractReaderName(const PCSC_CHAR_PTR pReaderPointer) const { #if defined(Q_OS_WIN) && defined(UNICODE) return QString::fromWCharArray(pReaderPointer); @@ -149,7 +152,7 @@ QString PcscReaderManagerPlugIn::extractReaderName(const PCSC_CHAR_PTR pReaderPo } -void PcscReaderManagerPlugIn::addReaders(const QStringList& pReaderNames) +void PcscReaderManagerPlugin::addReaders(const QStringList& pReaderNames) { for (const auto& readerName : pReaderNames) { @@ -163,9 +166,9 @@ void PcscReaderManagerPlugIn::addReaders(const QStringList& pReaderNames) Reader* reader = pcscReader.release(); mReaders.insert(readerName, reader); - connect(reader, &Reader::fireCardInserted, this, &PcscReaderManagerPlugIn::fireCardInserted); - connect(reader, &Reader::fireCardRemoved, this, &PcscReaderManagerPlugIn::fireCardRemoved); - connect(reader, &Reader::fireCardInfoChanged, this, &PcscReaderManagerPlugIn::fireCardInfoChanged); + connect(reader, &Reader::fireCardInserted, this, &PcscReaderManagerPlugin::fireCardInserted); + connect(reader, &Reader::fireCardRemoved, this, &PcscReaderManagerPlugin::fireCardRemoved); + connect(reader, &Reader::fireCardInfoChanged, this, &PcscReaderManagerPlugin::fireCardInfoChanged); qCDebug(card_pcsc) << "fireReaderAdded:" << readerName << "(" << mReaders.size() << "reader in total )"; Q_EMIT fireReaderAdded(reader->getReaderInfo()); @@ -173,7 +176,7 @@ void PcscReaderManagerPlugIn::addReaders(const QStringList& pReaderNames) } -void PcscReaderManagerPlugIn::removeReader(const QString& pReaderName) +void PcscReaderManagerPlugin::removeReader(const QString& pReaderName) { if (!mReaders.contains(pReaderName)) { @@ -189,7 +192,7 @@ void PcscReaderManagerPlugIn::removeReader(const QString& pReaderName) } -void PcscReaderManagerPlugIn::removeReaders(const QStringList& pReaderNames) +void PcscReaderManagerPlugin::removeReaders(const QStringList& pReaderNames) { for (const auto& readerName : pReaderNames) { @@ -198,7 +201,7 @@ void PcscReaderManagerPlugIn::removeReaders(const QStringList& pReaderNames) } -PCSC_RETURNCODE PcscReaderManagerPlugIn::readReaderNames(QStringList& pReaderNames) const +PCSC_RETURNCODE PcscReaderManagerPlugin::readReaderNames(QStringList& pReaderNames) const { if (mContextHandle == 0) { diff --git a/src/card/pcsc/PcscReaderManagerPlugIn.h b/src/card/pcsc/PcscReaderManagerPlugin.h similarity index 63% rename from src/card/pcsc/PcscReaderManagerPlugIn.h rename to src/card/pcsc/PcscReaderManagerPlugin.h index a36f844b5..0d375efb4 100644 --- a/src/card/pcsc/PcscReaderManagerPlugIn.h +++ b/src/card/pcsc/PcscReaderManagerPlugin.h @@ -1,35 +1,35 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Implementation of \ref ReaderManagerPlugIn for PCSC. + * \brief Implementation of \ref ReaderManagerPlugin for PCSC. */ #pragma once #include "PcscUtils.h" #include "Reader.h" -#include "ReaderManagerPlugIn.h" +#include "ReaderManagerPlugin.h" #include #include #include -class test_PcscReaderManagerPlugIn; +class test_PcscReaderManagerPlugin; namespace governikus { -class PcscReaderManagerPlugIn - : public ReaderManagerPlugIn +class PcscReaderManagerPlugin + : public ReaderManagerPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) - friend class ::test_PcscReaderManagerPlugIn; + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) + friend class ::test_PcscReaderManagerPlugin; private: SCARDCONTEXT mContextHandle; @@ -45,8 +45,8 @@ class PcscReaderManagerPlugIn void removeReaders(const QStringList& pReaderNames); public: - PcscReaderManagerPlugIn(); - ~PcscReaderManagerPlugIn() override; + PcscReaderManagerPlugin(); + ~PcscReaderManagerPlugin() override; [[nodiscard]] QList getReaders() const override; diff --git a/src/card/pcsc/PcscUtils.cpp b/src/card/pcsc/PcscUtils.cpp index 98d4b879c..9bdebd234 100644 --- a/src/card/pcsc/PcscUtils.cpp +++ b/src/card/pcsc/PcscUtils.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PcscUtils.h" diff --git a/src/card/pcsc/PcscUtils.h b/src/card/pcsc/PcscUtils.h index 68f279300..3ec08a9c4 100644 --- a/src/card/pcsc/PcscUtils.h +++ b/src/card/pcsc/PcscUtils.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/pcsc/metadata.json b/src/card/pcsc/metadata.json index c23f3ba9b..c51553989 100644 --- a/src/card/pcsc/metadata.json +++ b/src/card/pcsc/metadata.json @@ -1,4 +1,4 @@ { - "name" : "PcscReaderManagerPlugIn", + "name" : "PcscReaderManagerPlugin", "dependencies" : [] } diff --git a/src/card/simulator/SimulatorCard.cpp b/src/card/simulator/SimulatorCard.cpp index afddf9b01..6d5cb2951 100644 --- a/src/card/simulator/SimulatorCard.cpp +++ b/src/card/simulator/SimulatorCard.cpp @@ -1,31 +1,36 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SimulatorCard.h" #include "FileRef.h" +#include "Randomizer.h" #include "VolatileSettings.h" -#include "apdu/CommandData.h" #include "apdu/FileCommand.h" #include "apdu/GeneralAuthenticateResponse.h" +#include "asn1/ASN1Struct.h" #include "asn1/ASN1TemplateUtil.h" #include "asn1/ASN1Util.h" #include "pace/CipherMac.h" #include "pace/KeyDerivationFunction.h" #include "pace/ec/EcUtil.h" +#include "pace/ec/EcdhGenericMapping.h" +#include "pace/ec/EcdhKeyAgreement.h" #include #include #include #include -#include +#if OPENSSL_VERSION_NUMBER < 0x30000000L + #include +#endif using namespace governikus; -Q_DECLARE_LOGGING_CATEGORY(card) +Q_DECLARE_LOGGING_CATEGORY(card_simulator) Q_DECLARE_LOGGING_CATEGORY(secure) @@ -33,11 +38,16 @@ SimulatorCard::SimulatorCard(const SimulatorFileSystem& pFileSystem) : Card() , mConnected(false) , mFileSystem(pFileSystem) - , mAuxiliaryData() , mSecureMessaging() , mNewSecureMessaging() - , mCaKeyId(0) - , mRiKeyId(0) + , mSelectedProtocol() + , mChainingStep(0) + , mPaceKeyId(0) + , mPaceChat() + , mPaceNonce() + , mPaceTerminalKey() + , mCardKey() + , mTaAuxData() { } @@ -76,7 +86,7 @@ ResponseApduResult SimulatorCard::transmit(const CommandApdu& pCmd) CommandApdu commandApdu = pCmd; ResponseApduResult result = {CardReturnCode::OK, ResponseApdu(StatusCode::SUCCESS)}; - qCDebug(card) << "Transmit command APDU:" << commandApdu; + qCDebug(card_simulator) << "Transmit command APDU:" << commandApdu; if (mSecureMessaging) { @@ -87,8 +97,9 @@ ResponseApduResult SimulatorCard::transmit(const CommandApdu& pCmd) } else { - qCDebug(card) << "Received unencrypted command APDU. Disable secure messaging"; + qCDebug(card_simulator) << "Received unencrypted command APDU. Disable secure messaging"; mSecureMessaging.reset(); + mPaceChat.reset(); } } @@ -105,7 +116,10 @@ ResponseApduResult SimulatorCard::transmit(const CommandApdu& pCmd) break; case Ins::MSE_SET: - result = executeMseSetAt(commandApdu); + if (pCmd.getP2() == CommandApdu::AUTHENTICATION_TEMPLATE) + { + result = executeMseSetAt(commandApdu); + } break; case Ins::GENERAL_AUTHENTICATE: @@ -126,16 +140,25 @@ ResponseApduResult SimulatorCard::transmit(const CommandApdu& pCmd) break; } + if (commandApdu.isCommandChaining()) + { + mChainingStep++; + } + else + { + mChainingStep = 0; + } + if (mSecureMessaging) { result.mResponseApdu = mSecureMessaging->encrypt(result.mResponseApdu); } - qCDebug(card) << "Transmit response APDU:" << result.mResponseApdu; + qCDebug(card_simulator) << "Transmit response APDU:" << result.mResponseApdu; if (mNewSecureMessaging) { - qCDebug(card) << "Start to use a new secure messaging channel"; + qCDebug(card_simulator) << "Start to use a new secure messaging channel"; mNewSecureMessaging.swap(mSecureMessaging); mNewSecureMessaging.reset(); } @@ -144,27 +167,32 @@ ResponseApduResult SimulatorCard::transmit(const CommandApdu& pCmd) } -EstablishPaceChannelOutput SimulatorCard::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds) +EstablishPaceChannelOutput SimulatorCard::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) { Q_UNUSED(pPasswordId) Q_UNUSED(pPreferredPinLength) - Q_UNUSED(pChat) Q_UNUSED(pCertificateDescription) - Q_UNUSED(pTimeoutSeconds) QThread::msleep(Env::getSingleton()->getDelay()); EstablishPaceChannelOutput output(CardReturnCode::OK); output.setPaceReturnCode(CardReturnCode::OK); output.setStatusMseSetAt(QByteArray::fromHex("9000")); output.setEfCardAccess(mFileSystem.getEfCardAccess()); - output.setCarCurr(QByteArray("DETESTeID00005")); - output.setIdIcc(QByteArray::fromHex("0102030405060708900A0B0C0D0E0F1011121314")); + if (!pChat.isEmpty() && !pCertificateDescription.isEmpty()) + { + mPaceChat = CHAT::decode(pChat); + output.setCarCurr(QByteArray("DETESTeID00005")); + output.setIdIcc(QByteArray::fromHex("0102030405060708900A0B0C0D0E0F1011121314")); + } return output; } CardReturnCode SimulatorCard::destroyPaceChannel() { + mSecureMessaging.reset(); + mPaceChat.reset(); + return CardReturnCode::OK; } @@ -181,8 +209,8 @@ ResponseApduResult SimulatorCard::setEidPin(quint8 pTimeoutSeconds) ResponseApduResult SimulatorCard::executeFileCommand(const CommandApdu& pCmd) { const FileCommand fileCommand(pCmd); - const auto offset = fileCommand.getOffset(); - const auto fileRef = fileCommand.getFileRef(); + const auto& offset = fileCommand.getOffset(); + const auto& fileRef = fileCommand.getFileRef(); ResponseApduResult result = {CardReturnCode::OK, ResponseApdu(StatusCode::SUCCESS)}; switch (pCmd.getINS()) @@ -233,28 +261,53 @@ ResponseApduResult SimulatorCard::executeFileCommand(const CommandApdu& pCmd) ResponseApduResult SimulatorCard::executeMseSetAt(const CommandApdu& pCmd) { - if (pCmd.getP2() == CommandApdu::AUTHENTICATION_TEMPLATE) + + if (pCmd.getData().isEmpty()) { - const CommandData cmdData(pCmd.getData()); + return {CardReturnCode::OK, ResponseApdu(StatusCode::WRONG_LENGTH)}; + } - if (pCmd.getP1() == CommandApdu::CHIP_AUTHENTICATION && pCmd.getP2() == CommandApdu::AUTHENTICATION_TEMPLATE) - { - const auto& cmr = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE); - if (cmr == Oid(KnownOid::ID_CA_ECDH_AES_CBC_CMAC_128).getData()) + const ASN1Struct cmdData(pCmd.getData()); + + mSelectedProtocol = Oid(cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE)); + + const SecurityProtocol protocol(mSelectedProtocol); + + switch (pCmd.getP1()) + { + case CommandApdu::PACE: + if (protocol.getProtocol() == ProtocolType::PACE) { - mCaKeyId = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::PRIVATE_KEY_REFERENCE).back(); + mPaceKeyId = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::PRIVATE_KEY_REFERENCE).back(); + const auto& chat = cmdData.getObject(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE); + if (!chat.isEmpty()) + { + mPaceChat = CHAT::decode(chat); + } + else + { + mPaceChat.reset(); + } } - if (cmr == Oid(KnownOid::ID_RI_ECDH_SHA_256).getData()) + break; + + case CommandApdu::CHIP_AUTHENTICATION: + if (protocol.getProtocol() == ProtocolType::CA || protocol.getProtocol() == ProtocolType::RI) { - mRiKeyId = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::PRIVATE_KEY_REFERENCE).back(); + mCardKey = mFileSystem.getKey(cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::PRIVATE_KEY_REFERENCE).back()); } - } + break; - if (pCmd.getP1() == CommandApdu::VERIFICATION) - { - const auto& aad = cmdData.getObject(V_ASN1_APPLICATION, CommandData::AUXILIARY_AUTHENTICATED_DATA); - mAuxiliaryData = AuthenticatedAuxiliaryData::decode(aad); - } + case CommandApdu::TERMINAL_AUTHENTICATION: + if (protocol.getProtocol() == ProtocolType::TA) + { + const auto& aad = cmdData.getObject(V_ASN1_APPLICATION, ASN1Struct::AUXILIARY_AUTHENTICATED_DATA); + mTaAuxData = AuthenticatedAuxiliaryData::decode(aad); + } + break; + + default: + return {CardReturnCode::OK, ResponseApdu(StatusCode::INVALID_PARAMETER)}; } return {CardReturnCode::OK, ResponseApdu(StatusCode::SUCCESS)}; @@ -263,10 +316,107 @@ ResponseApduResult SimulatorCard::executeMseSetAt(const CommandApdu& pCmd) ResponseApduResult SimulatorCard::executeGeneralAuthenticate(const CommandApdu& pCmd) { - const CommandData cmdData(pCmd.getData()); - const auto& caKey = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::CA_EPHEMERAL_PUBLIC_KEY); - if (!caKey.isEmpty()) + if (pCmd.getData().isEmpty()) + { + return {CardReturnCode::OK, ResponseApdu(StatusCode::WRONG_LENGTH)}; + } + + const ASN1Struct cmdData(pCmd.getData()); + + if (mSelectedProtocol == KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128) + { + const SecurityProtocol protocol(mSelectedProtocol); + QByteArray responseData; + + if (mChainingStep <= 2 && !pCmd.isCommandChaining()) + { + return {CardReturnCode::OK, ResponseApdu(StatusCode::UNSUPPORTED_CLA)}; + } + + switch (mChainingStep) + { + case 0: + { + mPaceNonce = Randomizer::getInstance().createUuid().toRfc4122(); + const auto& symmetricKey = KeyDerivationFunction(protocol).pi(QByteArray("123456")); + SymmetricCipher nonceDecrypter(protocol, symmetricKey); + const auto& encryptedNonce = nonceDecrypter.encrypt(mPaceNonce); + + auto asn1Nonce = newObject(); + Asn1OctetStringUtil::setValue(encryptedNonce, asn1Nonce->mEncryptedNonce); + responseData = encodeObject(asn1Nonce.data()); + break; + } + + case 1: + { + EcdhGenericMapping mapping(EcUtil::createCurve(PaceInfo::getMappedNid(mPaceKeyId))); + const auto& localMappingData = mapping.generateLocalMappingData(); + const auto& remoteMappingData = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::MAPPING_DATA); + mapping.generateEphemeralDomainParameters(remoteMappingData, mPaceNonce); + mCardKey = EcUtil::generateKey(mapping.getCurve()); + mPaceNonce.clear(); + + auto asn1Mapping = newObject(); + Asn1OctetStringUtil::setValue(localMappingData, asn1Mapping->mMappingData); + responseData = encodeObject(asn1Mapping.data()); + break; + } + + case 2: + { + mPaceTerminalKey = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::PACE_EPHEMERAL_PUBLIC_KEY); + + auto asn1KeyAgreement = newObject(); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + const auto& encodedPublicKey = EcUtil::getEncodedPublicKey(mCardKey); +#else + const auto& curve = EcUtil::create(EC_GROUP_dup(EC_KEY_get0_group(mCardKey.data()))); + const auto& encodedPublicKey = EcUtil::point2oct(curve, EC_KEY_get0_public_key(mCardKey.data())); +#endif + Asn1OctetStringUtil::setValue(encodedPublicKey, asn1KeyAgreement->mEphemeralPublicKey); + responseData = encodeObject(asn1KeyAgreement.data()); + break; + } + + case 3: + { + if (pCmd.isCommandChaining()) + { + mChainingStep = -1; + return {CardReturnCode::OK, ResponseApdu(StatusCode::LAST_CHAIN_CMD_EXPECTED)}; + } + + const auto& mutualAuthenticationTerminalData = generateAuthenticationToken(mPaceTerminalKey); + mCardKey.reset(); + mPaceTerminalKey.clear(); + + auto ga = newObject(); + Asn1OctetStringUtil::setValue(mutualAuthenticationTerminalData, ga->mAuthenticationToken); + if (mPaceChat) + { + ga->mCarCurr = ASN1_OCTET_STRING_new(); + Asn1OctetStringUtil::setValue(QByteArray("DETESTeID00005"), ga->mCarCurr); + } + responseData = encodeObject(ga.data()); + break; + } + + default: + Q_UNREACHABLE(); + } + + return {CardReturnCode::OK, ResponseApdu(responseData + QByteArray::fromHex("9000"))}; + } + + if (mSelectedProtocol == KnownOid::ID_CA_ECDH_AES_CBC_CMAC_128) { + const auto& caKey = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::CA_EPHEMERAL_PUBLIC_KEY); + if (caKey.isEmpty()) + { + return {CardReturnCode::OK, ResponseApdu(StatusCode::INVALID_DATAFIELD)}; + } + const QByteArray nonce = QByteArray::fromHex("0001020304050607"); const QByteArray& authenticationToken = generateAuthenticationToken(caKey, nonce); @@ -276,19 +426,25 @@ ResponseApduResult SimulatorCard::executeGeneralAuthenticate(const CommandApdu& return {CardReturnCode::OK, ResponseApdu(encodeObject(ga.data()) + QByteArray::fromHex("9000"))}; } - const auto& riKey = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::RI_EPHEMERAL_PUBLIC_KEY); - if (!riKey.isEmpty()) + if (mSelectedProtocol == KnownOid::ID_RI_ECDH_SHA_256) { - const auto& oid = cmdData.getData(V_ASN1_UNIVERSAL, CommandData::RI_EPHEMERAL_PUBLIC_KEY); - if (oid != Oid(KnownOid::ID_RI_ECDH_SHA_256).getData()) + const auto& rawOid = cmdData.getData(V_ASN1_UNIVERSAL, ASN1Struct::UNI_OBJECT_IDENTIFIER); + const auto& riKey = cmdData.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::EC_PUBLIC_POINT); + if (rawOid.isEmpty() || riKey.isEmpty()) + { + return {CardReturnCode::OK, ResponseApdu(StatusCode::INVALID_DATAFIELD)}; + } + + const Oid oid(rawOid); + if (oid != KnownOid::ID_RI_ECDH_SHA_256) { return {CardReturnCode::OK, ResponseApdu(StatusCode::NO_BINARY_FILE)}; } const QByteArray& restrictedId = generateRestrictedId(riKey); - const auto responseData = Asn1Util::encode(V_ASN1_CONTEXT_SPECIFIC, 1, restrictedId); - const auto response = Asn1Util::encode(V_ASN1_APPLICATION, 28, responseData, true); + const auto responseData = Asn1Util::encode(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::RI_FIRST_IDENTIFIER, restrictedId); + const auto response = Asn1Util::encode(V_ASN1_APPLICATION, ASN1Struct::DYNAMIC_AUTHENTICATION_DATA, responseData, true); return {CardReturnCode::OK, ResponseApdu(response + QByteArray::fromHex("9000"))}; } @@ -296,39 +452,77 @@ ResponseApduResult SimulatorCard::executeGeneralAuthenticate(const CommandApdu& } -QByteArray SimulatorCard::brainpoolP256r1Multiplication(const QByteArray& pPoint, const QByteArray& pScalar) const +QByteArray SimulatorCard::ecMultiplication(const QByteArray& pPoint) const { - auto curve = EcUtil::createCurve(NID_brainpoolP256r1); + if (mCardKey.isNull()) + { + qCCritical(card_simulator) << "Missing private key"; + return QByteArray(); + } - auto point = EcUtil::oct2point(curve, pPoint); - if (!point) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + const auto& terminalKey = EcUtil::create(EVP_PKEY_new()); + if (terminalKey.isNull() || EVP_PKEY_copy_parameters(terminalKey.data(), mCardKey.data()) == 0) + { + qCCritical(card_simulator) << "Initialization of the terminal key failed"; + return QByteArray(); + } + if (!EVP_PKEY_set1_encoded_public_key( + terminalKey.data(), + reinterpret_cast(pPoint.data()), + static_cast(pPoint.length()))) { - qCCritical(card) << "Interpreting the point failed"; + qCCritical(card_simulator) << "Interpreting the terminal key failed"; + return QByteArray(); } - QSharedPointer scalar = EcUtil::create(BN_new()); - if (!BN_bin2bn(reinterpret_cast(pScalar.data()), static_cast(pScalar.size()), scalar.data())) + const auto& ctx = EcUtil::create(EVP_PKEY_CTX_new_from_pkey(nullptr, mCardKey.data(), nullptr)); + size_t resultLen = 0; + if (EVP_PKEY_derive_init(ctx.data()) <= 0 + || EVP_PKEY_derive_set_peer(ctx.data(), terminalKey.data()) <= 0 + || EVP_PKEY_derive(ctx.data(), nullptr, &resultLen) <= 0) { - qCCritical(card) << "Interpreting the scalar failed"; + qCCritical(card_simulator) << "Initialization or calculation of the result failed"; + return QByteArray(); + } + + QByteArray result(static_cast(resultLen), '\0'); + if (EVP_PKEY_derive(ctx.data(), reinterpret_cast(result.data()), &resultLen) <= 0) + { + qCCritical(card_simulator) << "Calculation of the result failed"; + return QByteArray(); + } + + return result; + +#else + const auto& curve = EcUtil::create(EC_GROUP_dup(EC_KEY_get0_group(mCardKey.data()))); + auto point = EcUtil::oct2point(curve, pPoint); + if (!point) + { + qCCritical(card_simulator) << "Interpreting the point failed"; + return QByteArray(); } QSharedPointer result = EcUtil::create(EC_POINT_new(curve.data())); - if (!EC_POINT_mul(curve.data(), result.data(), nullptr, point.data(), scalar.data(), nullptr)) + const auto& privateKey = EcUtil::create(BN_dup(EC_KEY_get0_private_key(mCardKey.data()))); + if (!EC_POINT_mul(curve.data(), result.data(), nullptr, point.data(), privateKey.data(), nullptr)) { - qCCritical(card) << "Calculation of the result failed"; + qCCritical(card_simulator) << "Calculation of the result failed"; + return QByteArray(); } return EcUtil::point2oct(curve, result.data(), true); + +#endif } QByteArray SimulatorCard::generateAuthenticationToken(const QByteArray& pPublicKey, const QByteArray& pNonce) { - const Oid oid(KnownOid::ID_CA_ECDH_AES_CBC_CMAC_128); - - QByteArray sharedSecret = brainpoolP256r1Multiplication(pPublicKey, mFileSystem.getPrivateKey(mCaKeyId)); + QByteArray sharedSecret = ecMultiplication(pPublicKey); - const auto protocol = SecurityProtocol(oid); + const auto protocol = SecurityProtocol(mSelectedProtocol); KeyDerivationFunction kdf(protocol); QByteArray macKey = kdf.mac(sharedSecret, pNonce); @@ -336,31 +530,23 @@ QByteArray SimulatorCard::generateAuthenticationToken(const QByteArray& pPublicK mNewSecureMessaging.reset(new SecureMessaging(protocol, encKey, macKey)); - const QByteArray oID = Asn1Util::encode(V_ASN1_UNIVERSAL, 6, oid.getData()); - const QByteArray publicPoint = Asn1Util::encode(V_ASN1_CONTEXT_SPECIFIC, 6, pPublicKey); - const QByteArray& publicKey = Asn1Util::encode(V_ASN1_APPLICATION, 73, oID + publicPoint, true); - CipherMac cmac(protocol, macKey); - QByteArray mac = cmac.generate(publicKey); - - return mac; + return cmac.generate(EcdhKeyAgreement::encodeUncompressedPublicKey(mSelectedProtocol, pPublicKey)); } QByteArray SimulatorCard::generateRestrictedId(const QByteArray& pPublicKey) const { - // const Oid oid(KnownOid::ID_RI_ECDH_SHA_256); - - QByteArray sharedSecret = brainpoolP256r1Multiplication(pPublicKey, mFileSystem.getPrivateKey(mRiKeyId)); + QByteArray sharedSecret = ecMultiplication(pPublicKey); return QCryptographicHash::hash(sharedSecret, QCryptographicHash::Sha256); } -StatusCode SimulatorCard::verifyAuxiliaryData(const QByteArray& pCommandData) +StatusCode SimulatorCard::verifyAuxiliaryData(const QByteArray& pASN1Struct) { - const auto* unsignedCharPointer = reinterpret_cast(pCommandData.constData()); - ASN1_OBJECT* obj = d2i_ASN1_OBJECT(nullptr, &unsignedCharPointer, static_cast(pCommandData.size())); + const auto* unsignedCharPointer = reinterpret_cast(pASN1Struct.constData()); + ASN1_OBJECT* obj = d2i_ASN1_OBJECT(nullptr, &unsignedCharPointer, static_cast(pASN1Struct.size())); const auto guard = qScopeGuard([obj] {ASN1_OBJECT_free(obj);}); - return mFileSystem.verify(Oid(obj), mAuxiliaryData); + return mFileSystem.verify(Oid(obj), mTaAuxData); } diff --git a/src/card/simulator/SimulatorCard.h b/src/card/simulator/SimulatorCard.h index d1afd0d40..69cf8343a 100644 --- a/src/card/simulator/SimulatorCard.h +++ b/src/card/simulator/SimulatorCard.h @@ -1,9 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Implementation of Simulator. + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -11,9 +7,13 @@ #include "Card.h" #include "SimulatorFileSystem.h" #include "asn1/AuthenticatedAuxiliaryData.h" +#include "asn1/Chat.h" +#include "asn1/Oid.h" #include "pace/SecureMessaging.h" #include +#include + namespace governikus { @@ -27,11 +27,20 @@ class SimulatorCard private: bool mConnected; SimulatorFileSystem mFileSystem; - QSharedPointer mAuxiliaryData; std::unique_ptr mSecureMessaging; std::unique_ptr mNewSecureMessaging; - int mCaKeyId; - int mRiKeyId; + Oid mSelectedProtocol; + int mChainingStep; + int mPaceKeyId; + QSharedPointer mPaceChat; + QByteArray mPaceNonce; + QByteArray mPaceTerminalKey; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + QSharedPointer mCardKey; +#else + QSharedPointer mCardKey; +#endif + QSharedPointer mTaAuxData; public: explicit SimulatorCard(const SimulatorFileSystem& pFileSystem); @@ -42,7 +51,7 @@ class SimulatorCard ResponseApduResult transmit(const CommandApdu& pCmd) override; - EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds) override; + EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) override; CardReturnCode destroyPaceChannel() override; @@ -52,10 +61,10 @@ class SimulatorCard ResponseApduResult executeFileCommand(const CommandApdu& pCmd); ResponseApduResult executeMseSetAt(const CommandApdu& pCmd); ResponseApduResult executeGeneralAuthenticate(const CommandApdu& pCmd); - QByteArray brainpoolP256r1Multiplication(const QByteArray& pPoint, const QByteArray& pScalar) const; - QByteArray generateAuthenticationToken(const QByteArray& pPublicKey, const QByteArray& pNonce); + QByteArray ecMultiplication(const QByteArray& pPoint) const; + QByteArray generateAuthenticationToken(const QByteArray& pPublicKey, const QByteArray& pNonce = QByteArray()); QByteArray generateRestrictedId(const QByteArray& pPublicKey) const; - StatusCode verifyAuxiliaryData(const QByteArray& pCommandData); + StatusCode verifyAuxiliaryData(const QByteArray& pASN1Struct); }; } // namespace governikus diff --git a/src/card/simulator/SimulatorFileSystem.cpp b/src/card/simulator/SimulatorFileSystem.cpp index 2c95e7526..122ca4ff5 100644 --- a/src/card/simulator/SimulatorFileSystem.cpp +++ b/src/card/simulator/SimulatorFileSystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SimulatorFileSystem.h" @@ -9,6 +9,7 @@ #include "apdu/ResponseApdu.h" #include "asn1/ASN1TemplateUtil.h" #include "asn1/ASN1Util.h" +#include "pace/ec/EcUtil.h" #include #include @@ -20,14 +21,47 @@ using namespace governikus; -Q_DECLARE_LOGGING_CATEGORY(card) +Q_DECLARE_LOGGING_CATEGORY(card_simulator) void SimulatorFileSystem::initMandatoryData() { - mKeys.insert(1, QByteArray::fromHex("0353859C2EC67780BA39015DE8C682AF2326D43DE9CE1E07737087BD1E17CB22")); - mKeys.insert(2, QByteArray::fromHex("9AD0AD7F4DFAAA06988339FC31D3A111F4C7964AC7F377373A2454327C43E2FF")); - mKeys.insert(41, QByteArray::fromHex("A07EB62E891DAA84643E0AFCC1AF006891B669B8F51E379477DBEAB8C987A610")); + mKeys.insert(1, QByteArray::fromHex( + "308202050201003081EC06072A8648CE3D02013081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E" + "660A909D838D726E3BF623D52620282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126" + "DC5C6CE94A4B44F330B5D9042026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6044104" + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9" + "C27745132DED8E545C1D54C72F046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E8297" + "4856A70201010482010F3082010B02010104200353859C2EC67780BA39015DE8C682AF2326D43DE9CE1E07737087BD1E" + "17CB22A081E33081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D526" + "20282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D90420" + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B60441048BD2AEB9CB7E57CB2C4B482FFC" + "81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F" + "046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7020101")); + mKeys.insert(2, QByteArray::fromHex( + "308202050201003081EC06072A8648CE3D02013081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E" + "660A909D838D726E3BF623D52620282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126" + "DC5C6CE94A4B44F330B5D9042026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6044104" + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9" + "C27745132DED8E545C1D54C72F046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E8297" + "4856A70201010482010F3082010B02010104209AD0AD7F4DFAAA06988339FC31D3A111F4C7964AC7F377373A2454327C" + "43E2FFA081E33081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D526" + "20282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D90420" + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B60441048BD2AEB9CB7E57CB2C4B482FFC" + "81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F" + "046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7020101")); + mKeys.insert(41, QByteArray::fromHex( + "308202050201003081EC06072A8648CE3D02013081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E" + "660A909D838D726E3BF623D52620282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126" + "DC5C6CE94A4B44F330B5D9042026DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6044104" + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9" + "C27745132DED8E545C1D54C72F046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E8297" + "4856A70201010482010F3082010B0201010420A07EB62E891DAA84643E0AFCC1AF006891B669B8F51E379477DBEAB8C9" + "87A610A081E33081E0020101302C06072A8648CE3D0101022100A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D526" + "20282013481D1F6E5377304404207D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D90420" + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B60441048BD2AEB9CB7E57CB2C4B482FFC" + "81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F" + "046997022100A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7020101")); createFile(FileRef::efDir().getIdentifier(), FileRef::efDir().getShortIdentifier(), QByteArray::fromHex( "61324F0FE828BD080FA000000167455349474E500F434941207A752044462E655369676E5100730C4F0AA00000016745" @@ -96,6 +130,30 @@ void SimulatorFileSystem::initMandatoryData() } +void SimulatorFileSystem::parseKey(const QJsonObject& pKey) +{ + const auto& keyId = pKey[QLatin1String("id")].toInt(0); + auto privateKey = pKey[QLatin1String("content")].toString(); + if (privateKey.isNull()) // Migration: With 2.2.0 the name and format of the private key was changed + { + if (const auto& rawKey = pKey[QLatin1String("private")].toString(); !rawKey.isNull()) + { + privateKey = QStringView(u"308188020100301406072a8648ce3d020106092b2403030208010107046d306b02010104" + "20%1a1440342000483dd43a94436965ab3048c66d2932e200055b5d3448cdaebd5f3814d" + "1ba6fc213dccd45fd48e18303d6625f5831e9a9efb6747481209d440588c046f2d188b5b").arg(rawKey); + qCWarning(card_simulator) << "'private' is deprecated and was replaced by 'content'"; + } + } + if (keyId == 0 || privateKey.isNull()) + { + qCWarning(card_simulator) << "Skipping key entry. Expected JSON object with 'id' and 'content', got" << pKey; + return; + } + + mKeys.insert(keyId, QByteArray::fromHex(privateKey.toUtf8())); +} + + SimulatorFileSystem::SimulatorFileSystem() : mSelectedFile() , mKeys() @@ -157,7 +215,7 @@ SimulatorFileSystem::SimulatorFileSystem(const QJsonObject& pData) { if (!value.isObject()) { - qCWarning(card) << "Skipping file entry. Expected JSON object, got" << value; + qCWarning(card_simulator) << "Skipping file entry. Expected JSON object, got" << value; continue; } @@ -167,7 +225,7 @@ SimulatorFileSystem::SimulatorFileSystem(const QJsonObject& pData) const auto& content = file[QLatin1String("content")].toString(); if (fileId.isNull() || shortFileId.isNull() || content.isNull()) { - qCWarning(card) << "Skipping file entry. Expected JSON object with 'fileId', 'shortFileId' and 'content', got" << file; + qCWarning(card_simulator) << "Skipping file entry. Expected JSON object with 'fileId', 'shortFileId' and 'content', got" << file; continue; } @@ -181,20 +239,11 @@ SimulatorFileSystem::SimulatorFileSystem(const QJsonObject& pData) { if (!value.isObject()) { - qCWarning(card) << "Skipping key entry. Expected JSON object, got" << value; + qCWarning(card_simulator) << "Skipping key entry. Expected JSON object, got" << value; continue; } - const auto& key = value.toObject(); - const auto& keyId = key[QLatin1String("id")].toInt(0); - const auto& privateKey = key[QLatin1String("private")].toString(); - if (keyId == 0 || privateKey.isNull()) - { - qCWarning(card) << "Skipping key entry. Expected JSON object with 'id' and 'private', got" << key; - continue; - } - - mKeys.insert(keyId, QByteArray::fromHex(privateKey.toUtf8())); + parseKey(value.toObject()); } } @@ -278,9 +327,33 @@ QByteArray SimulatorFileSystem::getEfCardAccess() const } -QByteArray SimulatorFileSystem::getPrivateKey(int pKeyId) const +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +QSharedPointer SimulatorFileSystem::getKey(int pKeyId) const +#else +QSharedPointer SimulatorFileSystem::getKey(int pKeyId) const +#endif { - return mKeys[pKeyId]; + if (!mKeys.contains(pKeyId)) + { + return nullptr; + } + + const auto& key = mKeys[pKeyId]; + const auto* dataPointer = reinterpret_cast(key.constData()); + const auto& privateKey = EcUtil::create(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &dataPointer, static_cast(key.length()))); + if (privateKey.isNull()) + { + qCCritical(card_simulator) << "Interpreting private key" << pKeyId << "failed:" << getOpenSslError(); + return nullptr; + } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + return privateKey; + +#else + return EcUtil::create(EVP_PKEY_get1_EC_KEY(privateKey.data())); + +#endif } @@ -291,7 +364,7 @@ StatusCode SimulatorFileSystem::verify(const Oid& pOid, const QSharedPointer #include #include +#include namespace governikus @@ -30,6 +27,7 @@ class SimulatorFileSystem QMap mFileIds; void initMandatoryData(); + void parseKey(const QJsonObject& pKey); public: SimulatorFileSystem(); @@ -40,7 +38,11 @@ class SimulatorFileSystem [[nodiscard]] StatusCode write(qsizetype pOffset, const QByteArray& pData); [[nodiscard]] QByteArray getEfCardAccess() const; - [[nodiscard]] QByteArray getPrivateKey(int pKeyId) const; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + [[nodiscard]] QSharedPointer getKey(int pKeyId) const; +#else + [[nodiscard]] QSharedPointer getKey(int pKeyId) const; +#endif [[nodiscard]] StatusCode verify(const Oid& pOid, const QSharedPointer& pAuxiliaryData) const; diff --git a/src/card/simulator/SimulatorReader.cpp b/src/card/simulator/SimulatorReader.cpp index 95fc8a343..e5e553437 100644 --- a/src/card/simulator/SimulatorReader.cpp +++ b/src/card/simulator/SimulatorReader.cpp @@ -1,19 +1,24 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SimulatorReader.h" +#include "AppSettings.h" #include "Env.h" #include "VolatileSettings.h" + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(card_simulator) + + SimulatorReader::SimulatorReader() - : ConnectableReader(ReaderManagerPlugInType::SIMULATOR, QStringLiteral("Simulator")) + : ConnectableReader(ReaderManagerPluginType::SIMULATOR, QStringLiteral("Simulator")) { - setInfoBasicReader(false); + setInfoBasicReader(Env::getSingleton()->getSimulatorSettings().isBasicReader()); } @@ -27,7 +32,7 @@ void SimulatorReader::insertCard(const QVariant& pData) { if (getReaderInfo().hasCard()) { - qCDebug(card) << "Already inserted"; + qCDebug(card_simulator) << "Already inserted"; return; } @@ -37,13 +42,14 @@ void SimulatorReader::insertCard(const QVariant& pData) mCard.reset(new SimulatorCard(filesystem)); fetchCardInfo(); + qCInfo(card_simulator) << "Card inserted:" << getReaderInfo().getCardInfo(); Q_EMIT fireCardInserted(getReaderInfo()); } void SimulatorReader::connectReader() { - qCDebug(card) << "targetDetected, type: Simulator"; + qCDebug(card_simulator) << "targetDetected, type: Simulator"; setInfoCardInfo(CardInfo(CardType::EID_CARD)); shelveCard(); @@ -63,10 +69,12 @@ void SimulatorReader::disconnectReader(const QString& pError) if (mCard) { - qCDebug(card) << "targetLost, type: Simulator"; + qCDebug(card_simulator) << "targetLost, type: Simulator"; mCard.reset(); removeCardInfo(); + + qCInfo(card_simulator) << "Card removed"; Q_EMIT fireCardRemoved(getReaderInfo()); } } diff --git a/src/card/simulator/SimulatorReader.h b/src/card/simulator/SimulatorReader.h index f5786e94d..b24e0c238 100644 --- a/src/card/simulator/SimulatorReader.h +++ b/src/card/simulator/SimulatorReader.h @@ -1,9 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Implementation of Reader for Simulator. + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/card/simulator/SimulatorReaderManagerPlugIn.cpp b/src/card/simulator/SimulatorReaderManagerPlugIn.cpp deleted file mode 100644 index dfaf3eb79..000000000 --- a/src/card/simulator/SimulatorReaderManagerPlugIn.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "SimulatorReaderManagerPlugIn.h" - -#include "AppSettings.h" -#include "VolatileSettings.h" - - -using namespace governikus; - - -SimulatorReaderManagerPlugIn::SimulatorReaderManagerPlugIn() - : ReaderManagerPlugIn(ReaderManagerPlugInType::SIMULATOR, true) - , mSimulatorReader() -{ - connect(&Env::getSingleton()->getGeneralSettings(), &GeneralSettings::fireDeveloperOptionsChanged, this, &SimulatorReaderManagerPlugIn::onSettingsChanged); - connect(Env::getSingleton(), &VolatileSettings::fireUsedAsSdkChanged, this, &SimulatorReaderManagerPlugIn::onSettingsChanged); -} - - -void SimulatorReaderManagerPlugIn::init() -{ - ReaderManagerPlugIn::init(); - - onSettingsChanged(); -} - - -QList SimulatorReaderManagerPlugIn::getReaders() const -{ - if (getInfo().isEnabled() && mSimulatorReader) - { - return {mSimulatorReader.data()}; - } - return {}; -} - - -void SimulatorReaderManagerPlugIn::startScan(bool pAutoConnect) -{ - if (getInfo().isEnabled()) - { - mSimulatorReader.reset(new SimulatorReader()); - - connect(mSimulatorReader.data(), &SimulatorReader::fireReaderPropertiesUpdated, this, &SimulatorReaderManagerPlugIn::fireReaderPropertiesUpdated); - connect(mSimulatorReader.data(), &SimulatorReader::fireCardInserted, this, &SimulatorReaderManagerPlugIn::fireCardInserted); - connect(mSimulatorReader.data(), &SimulatorReader::fireCardRemoved, this, &SimulatorReaderManagerPlugIn::fireCardRemoved); - qCDebug(card) << "fireReaderAdded" << mSimulatorReader->getName(); - Q_EMIT fireReaderAdded(mSimulatorReader->getReaderInfo()); - - mSimulatorReader->connectReader(); - ReaderManagerPlugIn::startScan(pAutoConnect); - } -} - - -void SimulatorReaderManagerPlugIn::stopScan(const QString& pError) -{ - if (mSimulatorReader) - { - mSimulatorReader->disconnectReader(pError); - - auto info = mSimulatorReader->getReaderInfo(); - mSimulatorReader.reset(); - Q_EMIT fireReaderRemoved(info); - } - ReaderManagerPlugIn::stopScan(pError); -} - - -void SimulatorReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant& pData) -{ - Q_UNUSED(pReaderName) - - if (!getInfo().isScanRunning()) - { - return; - } - - mSimulatorReader->insertCard(pData); -} - - -void SimulatorReaderManagerPlugIn::onSettingsChanged() -{ - const bool enabled = Env::getSingleton()->getGeneralSettings().isSimulatorEnabled() || Env::getSingleton()->isUsedAsSDK(); - if (getInfo().isEnabled() == enabled) - { - return; - } - - qCDebug(card) << "SimulatorStateChanged:" << enabled; - setPlugInEnabled(enabled); - if (!enabled && mSimulatorReader) - { - mSimulatorReader->disconnect(this); - const auto& readerInfo = mSimulatorReader->getReaderInfo(); - mSimulatorReader.reset(); - Q_EMIT fireReaderRemoved(readerInfo); - } -} diff --git a/src/card/simulator/SimulatorReaderManagerPlugin.cpp b/src/card/simulator/SimulatorReaderManagerPlugin.cpp new file mode 100644 index 000000000..22e3f01aa --- /dev/null +++ b/src/card/simulator/SimulatorReaderManagerPlugin.cpp @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "SimulatorReaderManagerPlugin.h" + +#include "AppSettings.h" +#include "VolatileSettings.h" + + +using namespace governikus; + + +Q_DECLARE_LOGGING_CATEGORY(card_simulator) + + +SimulatorReaderManagerPlugin::SimulatorReaderManagerPlugin() + : ReaderManagerPlugin(ReaderManagerPluginType::SIMULATOR, true) + , mSimulatorReader() +{ + connect(&Env::getSingleton()->getSimulatorSettings(), &SimulatorSettings::fireEnabledChanged, this, &SimulatorReaderManagerPlugin::onSettingsChanged); + connect(Env::getSingleton(), &VolatileSettings::fireUsedAsSdkChanged, this, &SimulatorReaderManagerPlugin::onSettingsChanged); +} + + +void SimulatorReaderManagerPlugin::init() +{ + ReaderManagerPlugin::init(); + + onSettingsChanged(); +} + + +QList SimulatorReaderManagerPlugin::getReaders() const +{ + if (getInfo().isEnabled() && mSimulatorReader) + { + return {mSimulatorReader.data()}; + } + return {}; +} + + +void SimulatorReaderManagerPlugin::startScan(bool pAutoConnect) +{ + if (getInfo().isEnabled()) + { + mSimulatorReader.reset(new SimulatorReader()); + + connect(mSimulatorReader.data(), &SimulatorReader::fireReaderPropertiesUpdated, this, &SimulatorReaderManagerPlugin::fireReaderPropertiesUpdated); + connect(mSimulatorReader.data(), &SimulatorReader::fireCardInserted, this, &SimulatorReaderManagerPlugin::fireCardInserted); + connect(mSimulatorReader.data(), &SimulatorReader::fireCardRemoved, this, &SimulatorReaderManagerPlugin::fireCardRemoved); + qCDebug(card_simulator) << "fireReaderAdded" << mSimulatorReader->getName(); + Q_EMIT fireReaderAdded(mSimulatorReader->getReaderInfo()); + + mSimulatorReader->connectReader(); + ReaderManagerPlugin::startScan(pAutoConnect); + setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); + } +} + + +void SimulatorReaderManagerPlugin::stopScan(const QString& pError) +{ + if (mSimulatorReader) + { + mSimulatorReader->disconnectReader(pError); + + auto info = mSimulatorReader->getReaderInfo(); + mSimulatorReader.reset(); + Q_EMIT fireReaderRemoved(info); + } + ReaderManagerPlugin::stopScan(pError); +} + + +void SimulatorReaderManagerPlugin::insert(const QString& pReaderName, const QVariant& pData) +{ + Q_UNUSED(pReaderName) + + if (!getInfo().isScanRunning()) + { + return; + } + + mSimulatorReader->insertCard(pData); +} + + +void SimulatorReaderManagerPlugin::onSettingsChanged() +{ + const bool enabled = Env::getSingleton()->getSimulatorSettings().isEnabled() || Env::getSingleton()->isUsedAsSDK(); + if (getInfo().isEnabled() == enabled) + { + return; + } + + qCDebug(card_simulator) << "SimulatorStateChanged:" << enabled; + setPluginEnabled(enabled); + if (!enabled && mSimulatorReader) + { + mSimulatorReader->disconnect(this); + const auto& readerInfo = mSimulatorReader->getReaderInfo(); + mSimulatorReader.reset(); + Q_EMIT fireReaderRemoved(readerInfo); + } +} diff --git a/src/card/simulator/SimulatorReaderManagerPlugIn.h b/src/card/simulator/SimulatorReaderManagerPlugin.h similarity index 59% rename from src/card/simulator/SimulatorReaderManagerPlugIn.h rename to src/card/simulator/SimulatorReaderManagerPlugin.h index 62138a6eb..a0273f6fd 100644 --- a/src/card/simulator/SimulatorReaderManagerPlugIn.h +++ b/src/card/simulator/SimulatorReaderManagerPlugin.h @@ -1,14 +1,10 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Implementation of ReaderManagerPlugIn for Simulator. + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "ReaderManagerPlugIn.h" +#include "ReaderManagerPlugin.h" #include "SimulatorReader.h" #include @@ -17,18 +13,18 @@ namespace governikus { -class SimulatorReaderManagerPlugIn - : public ReaderManagerPlugIn +class SimulatorReaderManagerPlugin + : public ReaderManagerPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) private: QScopedPointer mSimulatorReader; public: - SimulatorReaderManagerPlugIn(); + SimulatorReaderManagerPlugin(); [[nodiscard]] QList getReaders() const override; diff --git a/src/card/simulator/metadata.json b/src/card/simulator/metadata.json index 5582a82d1..9fa4a546d 100644 --- a/src/card/simulator/metadata.json +++ b/src/card/simulator/metadata.json @@ -1,4 +1,4 @@ { - "name" : "SimulatorReaderManagerPlugIn", + "name" : "SimulatorReaderManagerPlugin", "dependencies" : [] } diff --git a/src/card/smart/SmartCard.cpp b/src/card/smart/SmartCard.cpp index 1e3981746..aba66ed3f 100644 --- a/src/card/smart/SmartCard.cpp +++ b/src/card/smart/SmartCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartCard.h" diff --git a/src/card/smart/SmartCard.h b/src/card/smart/SmartCard.h index 2abb6100e..6cdbb7aad 100644 --- a/src/card/smart/SmartCard.h +++ b/src/card/smart/SmartCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/smart/SmartManager.cpp b/src/card/smart/SmartManager.cpp index 4a077bd66..198e5bffe 100644 --- a/src/card/smart/SmartManager.cpp +++ b/src/card/smart/SmartManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartManager.h" @@ -273,7 +273,7 @@ InitializeResult SmartManager::initializePersonalization(const QString& pChallen } -QByteArrayList SmartManager::performPersonalization(const QVector& pInputApdus) const +QByteArrayList SmartManager::performPersonalization(const QList& pInputApdus) const { if (!isValid()) { diff --git a/src/card/smart/SmartManager.h b/src/card/smart/SmartManager.h index 1a917e2a4..da0942e1a 100644 --- a/src/card/smart/SmartManager.h +++ b/src/card/smart/SmartManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,9 +15,9 @@ #include "pinpad/EstablishPaceChannelOutput.h" #include +#include #include #include -#include #include #include @@ -69,7 +69,7 @@ class SmartManager bool deletePersonalization() const; [[nodiscard]] EidServiceResult installSmart(const ProgressHandler& pHandler = ProgressHandler()) const; InitializeResult initializePersonalization(const QString& pChallenge, const QString& pPin) const; - QByteArrayList performPersonalization(const QVector& pInputApdus) const; + QByteArrayList performPersonalization(const QList& pInputApdus) const; [[nodiscard]] PersonalizationResult finalizePersonalization(int pStatus) const; EstablishPaceChannelOutput prepareIdentification(const QByteArray& pChat) const; [[nodiscard]] ResponseApduResult challenge() const; diff --git a/src/card/smart/SmartReader.cpp b/src/card/smart/SmartReader.cpp index 663ffb504..3e19b5957 100644 --- a/src/card/smart/SmartReader.cpp +++ b/src/card/smart/SmartReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartReader.h" @@ -16,7 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(card_smart) SmartReader::SmartReader(const QString& pName) - : ConnectableReader(ReaderManagerPlugInType::SMART, pName) + : ConnectableReader(ReaderManagerPluginType::SMART, pName) , mCard() { } @@ -61,6 +61,7 @@ void SmartReader::disconnectReader(const QString& pError) if (cardInserted) { + qCInfo(card_smart) << "Card removed"; Q_EMIT fireCardRemoved(getReaderInfo()); return; } diff --git a/src/card/smart/SmartReader.h b/src/card/smart/SmartReader.h index 1966ebaee..7afb5ba1f 100644 --- a/src/card/smart/SmartReader.h +++ b/src/card/smart/SmartReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/card/smart/SmartReaderManagerPlugIn.cpp b/src/card/smart/SmartReaderManagerPlugin.cpp similarity index 67% rename from src/card/smart/SmartReaderManagerPlugIn.cpp rename to src/card/smart/SmartReaderManagerPlugin.cpp index 7799fddba..2c2e71f02 100644 --- a/src/card/smart/SmartReaderManagerPlugIn.cpp +++ b/src/card/smart/SmartReaderManagerPlugin.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ -#include "SmartReaderManagerPlugIn.h" +#include "SmartReaderManagerPlugin.h" #include "AppSettings.h" #include "SmartManager.h" @@ -23,7 +23,7 @@ static QString READER_NAME() } -void SmartReaderManagerPlugIn::publishReader(const ReaderInfo& pInfo) +void SmartReaderManagerPlugin::publishReader(const ReaderInfo& pInfo) { if (mReaderAdded) { @@ -36,7 +36,7 @@ void SmartReaderManagerPlugIn::publishReader(const ReaderInfo& pInfo) } -void SmartReaderManagerPlugIn::onSmartAvailableChanged(bool pSmartAvailable) +void SmartReaderManagerPlugin::onSmartAvailableChanged(bool pSmartAvailable) { if (pSmartAvailable) { @@ -48,16 +48,16 @@ void SmartReaderManagerPlugIn::onSmartAvailableChanged(bool pSmartAvailable) } -SmartReaderManagerPlugIn::SmartReaderManagerPlugIn() - : ReaderManagerPlugIn(ReaderManagerPlugInType::SMART) +SmartReaderManagerPlugin::SmartReaderManagerPlugin() + : ReaderManagerPlugin(ReaderManagerPluginType::SMART) , mReaderAdded(false) , mSmartReader(nullptr) { - connect(&Env::getSingleton()->getGeneralSettings(), &GeneralSettings::fireSmartAvailableChanged, this, &SmartReaderManagerPlugIn::onSmartAvailableChanged); + connect(&Env::getSingleton()->getGeneralSettings(), &GeneralSettings::fireSmartAvailableChanged, this, &SmartReaderManagerPlugin::onSmartAvailableChanged); } -QList SmartReaderManagerPlugIn::getReaders() const +QList SmartReaderManagerPlugin::getReaders() const { if (mSmartReader) { @@ -68,9 +68,9 @@ QList SmartReaderManagerPlugIn::getReaders() const } -void SmartReaderManagerPlugIn::init() +void SmartReaderManagerPlugin::init() { - ReaderManagerPlugIn::init(); + ReaderManagerPlugin::init(); const auto& smartManager = SmartManager::get(); if (!Env::getSingleton()->isUsedAsSDK()) @@ -90,18 +90,18 @@ void SmartReaderManagerPlugIn::init() return; } - setPlugInAvailable(true); + setPluginAvailable(true); mSmartReader.reset(new SmartReader(READER_NAME())); - connect(mSmartReader.data(), &SmartReader::fireReaderPropertiesUpdated, this, &SmartReaderManagerPlugIn::fireReaderPropertiesUpdated); - connect(mSmartReader.data(), &SmartReader::fireCardInfoChanged, this, &SmartReaderManagerPlugIn::fireCardInfoChanged); - connect(mSmartReader.data(), &SmartReader::fireCardInserted, this, &SmartReaderManagerPlugIn::fireCardInserted); - connect(mSmartReader.data(), &SmartReader::fireCardRemoved, this, &SmartReaderManagerPlugIn::fireCardRemoved); + connect(mSmartReader.data(), &SmartReader::fireReaderPropertiesUpdated, this, &SmartReaderManagerPlugin::fireReaderPropertiesUpdated); + connect(mSmartReader.data(), &SmartReader::fireCardInfoChanged, this, &SmartReaderManagerPlugin::fireCardInfoChanged); + connect(mSmartReader.data(), &SmartReader::fireCardInserted, this, &SmartReaderManagerPlugin::fireCardInserted); + connect(mSmartReader.data(), &SmartReader::fireCardRemoved, this, &SmartReaderManagerPlugin::fireCardRemoved); qCDebug(card_smart) << "Add reader" << mSmartReader->getName(); publishReader(mSmartReader->getReaderInfo()); } -void SmartReaderManagerPlugIn::shutdown() +void SmartReaderManagerPlugin::shutdown() { if (!getInfo().isAvailable()) { @@ -110,11 +110,11 @@ void SmartReaderManagerPlugIn::shutdown() mSmartReader.reset(); Q_EMIT fireReaderPropertiesUpdated(ReaderInfo(READER_NAME())); - setPlugInAvailable(false); + setPluginAvailable(false); } -void SmartReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant& pData) +void SmartReaderManagerPlugin::insert(const QString& pReaderName, const QVariant& pData) { if (!getInfo().isAvailable()) { @@ -138,21 +138,21 @@ void SmartReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant } -void SmartReaderManagerPlugIn::startScan(bool pAutoConnect) +void SmartReaderManagerPlugin::startScan(bool pAutoConnect) { if (getInfo().isAvailable()) { mSmartReader->connectReader(); - ReaderManagerPlugIn::startScan(pAutoConnect); + ReaderManagerPlugin::startScan(pAutoConnect); } } -void SmartReaderManagerPlugIn::stopScan(const QString& pError) +void SmartReaderManagerPlugin::stopScan(const QString& pError) { if (getInfo().isAvailable()) { mSmartReader->disconnectReader(pError); - ReaderManagerPlugIn::stopScan(pError); + ReaderManagerPlugin::stopScan(pError); } } diff --git a/src/card/smart/SmartReaderManagerPlugIn.h b/src/card/smart/SmartReaderManagerPlugin.h similarity index 65% rename from src/card/smart/SmartReaderManagerPlugIn.h rename to src/card/smart/SmartReaderManagerPlugin.h index 450195fa2..e6c45796b 100644 --- a/src/card/smart/SmartReaderManagerPlugIn.h +++ b/src/card/smart/SmartReaderManagerPlugin.h @@ -1,14 +1,14 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Implementation of ReaderManagerPlugIn for Smart-eID card. + * \brief Implementation of ReaderManagerPlugin for Smart-eID card. */ #pragma once -#include "ReaderManagerPlugIn.h" +#include "ReaderManagerPlugin.h" #include "SmartReader.h" #include @@ -17,12 +17,12 @@ namespace governikus { -class SmartReaderManagerPlugIn - : public ReaderManagerPlugIn +class SmartReaderManagerPlugin + : public ReaderManagerPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) private: bool mReaderAdded; @@ -34,7 +34,7 @@ class SmartReaderManagerPlugIn void onSmartAvailableChanged(bool pSmartAvailable); public: - SmartReaderManagerPlugIn(); + SmartReaderManagerPlugin(); [[nodiscard]] QList getReaders() const override; diff --git a/src/card/smart/metadata.json b/src/card/smart/metadata.json index dcea9d41b..666e443fd 100644 --- a/src/card/smart/metadata.json +++ b/src/card/smart/metadata.json @@ -1,4 +1,4 @@ { - "name" : "SmartReaderManagerPlugIn", + "name" : "SmartReaderManagerPlugin", "dependencies" : [] } diff --git a/src/configuration/CallCost.cpp b/src/configuration/CallCost.cpp index fc7c62ffd..94d42fe7c 100644 --- a/src/configuration/CallCost.cpp +++ b/src/configuration/CallCost.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "CallCost.h" diff --git a/src/configuration/CallCost.h b/src/configuration/CallCost.h index 4055c2e49..ca59bb724 100644 --- a/src/configuration/CallCost.h +++ b/src/configuration/CallCost.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/configuration/LanguageString.cpp b/src/configuration/LanguageString.cpp index 78f9a566c..78903694b 100644 --- a/src/configuration/LanguageString.cpp +++ b/src/configuration/LanguageString.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "LanguageString.h" @@ -10,6 +10,12 @@ using namespace governikus; +LanguageString::LanguageString() + : LanguageString(QString()) +{ +} + + LanguageString::LanguageString(const QJsonValue& pJson) { if (!pJson.isObject()) diff --git a/src/configuration/LanguageString.h b/src/configuration/LanguageString.h index 43203cdb5..e23f32ce8 100644 --- a/src/configuration/LanguageString.h +++ b/src/configuration/LanguageString.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -24,6 +24,7 @@ class LanguageString [[nodiscard]] QString toString(const QLocale& pLocale) const; public: + LanguageString(); explicit LanguageString(const QJsonValue& pJson); explicit LanguageString(const QMap& pInput); LanguageString(const QString& pString, const QLocale& pLocale = LanguageLoader::getInstance().getUsedLocale()); diff --git a/src/configuration/ProviderConfiguration.cpp b/src/configuration/ProviderConfiguration.cpp index d923f1b87..aab4d186d 100644 --- a/src/configuration/ProviderConfiguration.cpp +++ b/src/configuration/ProviderConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ProviderConfiguration.h" @@ -84,7 +84,7 @@ void ProviderConfiguration::update() } -const QVector& ProviderConfiguration::getProviderConfigurationInfos() const +const QList& ProviderConfiguration::getProviderConfigurationInfos() const { return mProviderConfigurationInfos; } diff --git a/src/configuration/ProviderConfiguration.h b/src/configuration/ProviderConfiguration.h index 195359c2c..7edcc6adf 100644 --- a/src/configuration/ProviderConfiguration.h +++ b/src/configuration/ProviderConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,10 +13,10 @@ #include "ProviderConfigurationInfo.h" #include "UpdatableFile.h" +#include #include #include #include -#include namespace governikus { @@ -29,7 +29,7 @@ class ProviderConfiguration private: const QSharedPointer mUpdatableFile; - QVector mProviderConfigurationInfos; + QList mProviderConfigurationInfos; QMap mCallCosts; ProviderConfiguration(); @@ -41,7 +41,7 @@ class ProviderConfiguration public: void update(); - [[nodiscard]] const QVector& getProviderConfigurationInfos() const; + [[nodiscard]] const QList& getProviderConfigurationInfos() const; [[nodiscard]] CallCost getCallCost(const ProviderConfigurationInfo& pProvider) const; [[nodiscard]] ProviderConfigurationInfo getProviderInfo(const QString& pInternalId) const; diff --git a/src/configuration/ProviderConfigurationInfo.cpp b/src/configuration/ProviderConfigurationInfo.cpp index 590f77904..ff372df0a 100644 --- a/src/configuration/ProviderConfigurationInfo.cpp +++ b/src/configuration/ProviderConfigurationInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ProviderConfigurationInfo.h" @@ -19,27 +19,13 @@ QString ProviderConfigurationInfo::getDefaultFile(const QString& pSuffix) const #else const QString platform; #endif - const QString category = d->mCategory.isEmpty() ? QStringLiteral("general") : d->mCategory; + const QString category = d->mParams.mCategory.isEmpty() ? QStringLiteral("general") : d->mParams.mCategory; return QStringLiteral(":/images/provider/%1%2%3.svg").arg(platform, category, pSuffix); } -ProviderConfigurationInfo::ProviderConfigurationInfo(const LanguageString& pShortName, - const LanguageString& pLongName, - const LanguageString& pLongDescription, - const QString& pAddress, - const QString& pHomepage, - const QString& pCategory, - const QString& pPhone, - const QString& pEmail, - const QString& pPostalAddress, - const QString& pIcon, - const QString& pImage, - const QStringList& pSubjectUrls, - const QString& pSubjectUrlInfo, - const QString& pInternalId) - : d(new InternalInfo(pShortName, pLongName, pLongDescription, pAddress, pHomepage, - pCategory, pPhone, pEmail, pPostalAddress, pIcon, pImage, pSubjectUrls, pSubjectUrlInfo, pInternalId)) +ProviderConfigurationInfo::ProviderConfigurationInfo(const ProviderConfigurationInfoParams& pParams) + : d(new InternalInfo(pParams)) { } @@ -88,97 +74,97 @@ bool ProviderConfigurationInfo::matchWithSubjectUrl(const QString& pSubjectUrl) const LanguageString& ProviderConfigurationInfo::getShortName() const { - return !d->mShortName.toString().isNull() ? d->mShortName : getLongName(); + return !d->mParams.mShortName.toString().isNull() ? d->mParams.mShortName : getLongName(); } const LanguageString& ProviderConfigurationInfo::getLongName() const { - return d->mLongName; + return d->mParams.mLongName; } const LanguageString& ProviderConfigurationInfo::getLongDescription() const { - return d->mLongDescription; + return d->mParams.mLongDescription; } const QString& ProviderConfigurationInfo::getAddress() const { - return d->mAddress; + return d->mParams.mAddress; } QString ProviderConfigurationInfo::getAddressDomain() const { - return QUrl::fromUserInput(d->mAddress).host(); + return QUrl::fromUserInput(d->mParams.mAddress).host(); } const QString& ProviderConfigurationInfo::getHomepage() const { - return d->mHomepage; + return d->mParams.mHomepage; } QString ProviderConfigurationInfo::getHomepageBase() const { - return QUrl::fromUserInput(d->mHomepage).host(); + return QUrl::fromUserInput(d->mParams.mHomepage).host(); } const QString& ProviderConfigurationInfo::getCategory() const { - return d->mCategory; + return d->mParams.mCategory; } const QString& ProviderConfigurationInfo::getPhone() const { - return d->mPhone; + return d->mParams.mPhone; } const QString& ProviderConfigurationInfo::getEMail() const { - return d->mEmail; + return d->mParams.mEmail; } const QString& ProviderConfigurationInfo::getPostalAddress() const { - return d->mPostalAddress; + return d->mParams.mPostalAddress; } QSharedPointer ProviderConfigurationInfo::getIcon() const { const QString defaultFile = getDefaultFile(QStringLiteral("_button")); - return Env::getSingleton()->getFile(QStringLiteral("provider"), d->mIcon, defaultFile); + return Env::getSingleton()->getFile(QStringLiteral("provider"), d->mParams.mIcon, defaultFile); } QSharedPointer ProviderConfigurationInfo::getImage() const { const QString defaultFile = getDefaultFile(QStringLiteral("_bg")); - return Env::getSingleton()->getFile(QStringLiteral("provider"), d->mImage, defaultFile); + return Env::getSingleton()->getFile(QStringLiteral("provider"), d->mParams.mImage, defaultFile); } const QStringList& ProviderConfigurationInfo::getSubjectUrls() const { - return d->mSubjectUrls; + return d->mParams.mSubjectUrls; } const QString& ProviderConfigurationInfo::getSubjectUrlInfo() const { - return d->mSubjectUrlInfo; + return d->mParams.mSubjectUrlInfo; } const QString& ProviderConfigurationInfo::getInternalId() const { - return d->mInternalId; + return d->mParams.mInternalId; } diff --git a/src/configuration/ProviderConfigurationInfo.h b/src/configuration/ProviderConfigurationInfo.h index c7d74973f..362d51e62 100644 --- a/src/configuration/ProviderConfigurationInfo.h +++ b/src/configuration/ProviderConfigurationInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,6 +21,44 @@ namespace governikus { +struct ProviderConfigurationInfoParams +{ + const LanguageString mShortName; + const LanguageString mLongName; + const LanguageString mLongDescription; + const QString mAddress; + const QString mHomepage; + const QString mCategory; + const QString mPhone; + const QString mEmail; + const QString mPostalAddress; + const QString mIcon; + const QString mImage; + const QStringList mSubjectUrls; + const QString mSubjectUrlInfo; + const QString mInternalId; + + bool operator ==(const ProviderConfigurationInfoParams& pOther) const + { + return mShortName == pOther.mShortName && + mLongName == pOther.mLongName && + mLongDescription == pOther.mLongDescription && + mAddress == pOther.mAddress && + mHomepage == pOther.mHomepage && + mCategory == pOther.mCategory && + mPhone == pOther.mPhone && + mEmail == pOther.mEmail && + mPostalAddress == pOther.mPostalAddress && + mIcon == pOther.mIcon && + mImage == pOther.mImage && + mSubjectUrls == pOther.mSubjectUrls && + mSubjectUrlInfo == pOther.mSubjectUrlInfo && + mInternalId == pOther.mInternalId; + } + + +}; + class ProviderConfigurationInfo { private: @@ -28,69 +66,17 @@ class ProviderConfigurationInfo : public QSharedData { public: - const LanguageString mShortName; - const LanguageString mLongName; - const LanguageString mLongDescription; - const QString mAddress; - const QString mHomepage; - const QString mCategory; - const QString mPhone; - const QString mEmail; - const QString mPostalAddress; - const QString mIcon; - const QString mImage; - const QStringList mSubjectUrls; - const QString mSubjectUrlInfo; - const QString mInternalId; - - InternalInfo(const LanguageString& pShortName, - const LanguageString& pLongName, - const LanguageString& pLongDescription, - const QString& pAddress, - const QString& pHomepage, - const QString& pCategory, - const QString& pPhone, - const QString& pEmail, - const QString& pPostalAddress, - const QString& pIcon, - const QString& pImage, - const QStringList& pSubjectUrls, - const QString& pSubjectUrlInfo, - const QString& pInternalId) - : mShortName(pShortName) - , mLongName(pLongName) - , mLongDescription(pLongDescription) - , mAddress(pAddress) - , mHomepage(pHomepage) - , mCategory(pCategory) - , mPhone(pPhone) - , mEmail(pEmail) - , mPostalAddress(pPostalAddress) - , mIcon(pIcon) - , mImage(pImage) - , mSubjectUrls(pSubjectUrls) - , mSubjectUrlInfo(pSubjectUrlInfo) - , mInternalId(pInternalId) + const ProviderConfigurationInfoParams mParams; + + explicit InternalInfo(const ProviderConfigurationInfoParams& pInfos) + : mParams(pInfos) { } bool operator ==(const InternalInfo& pOther) const { - return mShortName == pOther.mShortName && - mLongName == pOther.mLongName && - mLongDescription == pOther.mLongDescription && - mAddress == pOther.mAddress && - mHomepage == pOther.mHomepage && - mCategory == pOther.mCategory && - mPhone == pOther.mPhone && - mEmail == pOther.mEmail && - mPostalAddress == pOther.mPostalAddress && - mIcon == pOther.mIcon && - mImage == pOther.mImage && - mSubjectUrls == pOther.mSubjectUrls && - mSubjectUrlInfo == pOther.mSubjectUrlInfo && - mInternalId == pOther.mInternalId; + return mParams == pOther.mParams; } @@ -101,20 +87,7 @@ class ProviderConfigurationInfo [[nodiscard]] QString getDefaultFile(const QString& pSuffix) const; public: - ProviderConfigurationInfo(const LanguageString& pShortName = QString(), - const LanguageString& pLongName = QString(), - const LanguageString& pLongDescription = QString(), - const QString& pAddress = QString(), - const QString& pHomepage = QString(), - const QString& pCategory = QString(), - const QString& pPhone = QString(), - const QString& pEmail = QString(), - const QString& pPostalAddress = QString(), - const QString& pIcon = QString(), - const QString& pImage = QString(), - const QStringList& pSubjectUrls = QStringList(), - const QString& pSubjectUrlInfo = QString(), - const QString& pInternalId = QString()); + explicit ProviderConfigurationInfo(const ProviderConfigurationInfoParams& pParams = {}); virtual ~ProviderConfigurationInfo(); bool operator ==(const ProviderConfigurationInfo& pOther) const; diff --git a/src/configuration/ProviderConfigurationParser.cpp b/src/configuration/ProviderConfigurationParser.cpp index 3c0a20b7c..d9f59a819 100644 --- a/src/configuration/ProviderConfigurationParser.cpp +++ b/src/configuration/ProviderConfigurationParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ProviderConfigurationParser.h" @@ -17,14 +17,14 @@ Q_DECLARE_LOGGING_CATEGORY(update) using namespace governikus; -QVector ProviderConfigurationParser::parseProvider(const QByteArray& pData, const QOperatingSystemVersion& pCurrentOS) +QList ProviderConfigurationParser::parseProvider(const QByteArray& pData, const QOperatingSystemVersion& pCurrentOS) { QJsonParseError jsonError {}; const auto& json = QJsonDocument::fromJson(pData, &jsonError); if (jsonError.error != QJsonParseError::NoError) { qCCritical(update) << "Cannot parse providers:" << jsonError.errorString(); - return QVector(); + return QList(); } const bool eidIsRequired = @@ -33,7 +33,7 @@ QVector ProviderConfigurationParser::parseProvider(co const QJsonObject doc = json.object(); const QJsonArray& array = doc[QLatin1String("provider")].toArray(); - QVector providers; + QList providers; providers.reserve(array.size()); for (const QJsonValueConstRef entry : array) { @@ -44,21 +44,21 @@ QVector ProviderConfigurationParser::parseProvider(co continue; } - providers << ProviderConfigurationInfo( - LanguageString(prov[QLatin1String("shortName")]), - LanguageString(prov[QLatin1String("longName")]), - LanguageString(prov[QLatin1String("longDescription")]), - prov[QLatin1String("address")].toString(), - prov[QLatin1String("homepage")].toString(), - prov[QLatin1String("category")].toString(), - prov[QLatin1String("phone")].toString(), - prov[QLatin1String("email")].toString(), - prov[QLatin1String("postalAddress")].toString(), - prov[QLatin1String("icon")].toString(), - prov[QLatin1String("image")].toString(), - prov[QLatin1String("subjectUrls")].toVariant().toStringList(), - prov[QLatin1String("subjectUrlInfo")].toString(), - prov[QLatin1String("internalId")].toString()); + providers << ProviderConfigurationInfo({ + LanguageString(prov[QLatin1String("shortName")]), + LanguageString(prov[QLatin1String("longName")]), + LanguageString(prov[QLatin1String("longDescription")]), + prov[QLatin1String("address")].toString(), + prov[QLatin1String("homepage")].toString(), + prov[QLatin1String("category")].toString(), + prov[QLatin1String("phone")].toString(), + prov[QLatin1String("email")].toString(), + prov[QLatin1String("postalAddress")].toString(), + prov[QLatin1String("icon")].toString(), + prov[QLatin1String("image")].toString(), + prov[QLatin1String("subjectUrls")].toVariant().toStringList(), + prov[QLatin1String("subjectUrlInfo")].toString(), + prov[QLatin1String("internalId")].toString()}); } return providers; @@ -93,7 +93,7 @@ QMap ProviderConfigurationParser::parseCallCosts(const QByteA } -QVector ProviderConfigurationParser::parseProvider(const QByteArray& pData) +QList ProviderConfigurationParser::parseProvider(const QByteArray& pData) { return parseProvider(pData, QOperatingSystemVersion::current()); } diff --git a/src/configuration/ProviderConfigurationParser.h b/src/configuration/ProviderConfigurationParser.h index 0d0b0d17b..6afa66e35 100644 --- a/src/configuration/ProviderConfigurationParser.h +++ b/src/configuration/ProviderConfigurationParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,14 +24,14 @@ class ProviderConfigurationParser friend class ::test_ProviderConfigurationParser; private: - static QVector parseProvider(const QByteArray& pData, const QOperatingSystemVersion& pCurrentOS); + static QList parseProvider(const QByteArray& pData, const QOperatingSystemVersion& pCurrentOS); ProviderConfigurationParser() = delete; ~ProviderConfigurationParser() = delete; public: static QMap parseCallCosts(const QByteArray& pData); - static QVector parseProvider(const QByteArray& pData); + static QList parseProvider(const QByteArray& pData); }; diff --git a/src/configuration/ReaderConfiguration.cpp b/src/configuration/ReaderConfiguration.cpp index 63ccabfcc..b3688a0da 100644 --- a/src/configuration/ReaderConfiguration.cpp +++ b/src/configuration/ReaderConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderConfiguration.h" @@ -49,7 +49,6 @@ void ReaderConfiguration::onFileUpdated() for (const ReaderConfigurationInfo& info : std::as_const(mReaderConfigurationInfos)) { info.getIcon()->markDirty(); - info.getIconWithNPA()->markDirty(); } Q_EMIT fireUpdated(); @@ -67,31 +66,19 @@ ReaderConfiguration::ReaderConfiguration() } -QString ReaderConfiguration::getNoReaderFoundIconPath() -{ - return QStringLiteral(":/images/reader/default_no_reader.png"); -} - - -QString ReaderConfiguration::getMultipleReaderIconPath() -{ - return QStringLiteral(":/images/reader/default_more_reader.png"); -} - - void ReaderConfiguration::update() { mUpdatableFile->update(); } -const QVector& ReaderConfiguration::getReaderConfigurationInfos() const +const QList& ReaderConfiguration::getReaderConfigurationInfos() const { return mReaderConfigurationInfos; } -QVector ReaderConfiguration::getSupportedReaderConfigurationInfos() const +QList ReaderConfiguration::getSupportedReaderConfigurationInfos() const { return filter([](const ReaderConfigurationInfo& i){ return !i.getUrl().isEmpty(); @@ -99,7 +86,7 @@ QVector ReaderConfiguration::getSupportedReaderConfigur } -QVector ReaderConfiguration::getVirtualReaderConfigurationInfos() const +QList ReaderConfiguration::getVirtualReaderConfigurationInfos() const { return filter([](const ReaderConfigurationInfo& i){ return i.getVendorId() == 0x0; diff --git a/src/configuration/ReaderConfiguration.h b/src/configuration/ReaderConfiguration.h index bb7cdeee8..00002b6b7 100644 --- a/src/configuration/ReaderConfiguration.h +++ b/src/configuration/ReaderConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,9 +15,9 @@ #include "UsbId.h" #include +#include #include #include -#include namespace governikus @@ -33,7 +33,7 @@ class ReaderConfiguration private: const QSharedPointer mUpdatableFile; - QVector mReaderConfigurationInfos; + QList mReaderConfigurationInfos; ReaderConfiguration(); ~ReaderConfiguration() override = default; @@ -43,13 +43,10 @@ class ReaderConfiguration void onFileUpdated(); public: - [[nodiscard]] static QString getNoReaderFoundIconPath(); - [[nodiscard]] static QString getMultipleReaderIconPath(); - void update(); - [[nodiscard]] const QVector& getReaderConfigurationInfos() const; - [[nodiscard]] QVector getSupportedReaderConfigurationInfos() const; - [[nodiscard]] QVector getVirtualReaderConfigurationInfos() const; + [[nodiscard]] const QList& getReaderConfigurationInfos() const; + [[nodiscard]] QList getSupportedReaderConfigurationInfos() const; + [[nodiscard]] QList getVirtualReaderConfigurationInfos() const; [[nodiscard]] ReaderConfigurationInfo getReaderConfigurationInfoById(const UsbId& pId) const; diff --git a/src/configuration/ReaderConfigurationInfo.cpp b/src/configuration/ReaderConfigurationInfo.cpp index b049483b8..157d45b47 100644 --- a/src/configuration/ReaderConfigurationInfo.cpp +++ b/src/configuration/ReaderConfigurationInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderConfigurationInfo.h" @@ -17,14 +17,14 @@ ReaderConfigurationInfo::ReaderConfigurationInfo() ReaderConfigurationInfo::ReaderConfigurationInfo(const QString& pReaderName) - : d(new InternalInfo(false, 0, {}, pReaderName, QString(), QString(), QStringLiteral("default_reader.png"), QStringLiteral("default_reader_mit_ausweis.png"))) + : d(new InternalInfo(false, 0, {}, pReaderName, QString(), QString(), QStringLiteral("default_reader.png"))) { } ReaderConfigurationInfo::ReaderConfigurationInfo(uint pVendorId, const QSet& pProductIds, - const QString& pName, const QString& pUrl, const QString& pPattern, const QString& pIcon, const QString& pIconWithNPA) - : d(new InternalInfo(true, pVendorId, pProductIds, pName, pUrl, pPattern, pIcon, pIconWithNPA)) + const QString& pName, const QString& pUrl, const QString& pPattern, const QString& pIcon) + : d(new InternalInfo(true, pVendorId, pProductIds, pName, pUrl, pPattern, pIcon)) { } @@ -68,7 +68,7 @@ const QString& ReaderConfigurationInfo::getUrl() const if (QCoreApplication::applicationName() == QLatin1String("Test_configuration_ReaderConfiguration")) { // Make the reader available on all platforms - static const QString url = QStringLiteral("https://www.governikus.de/"); + static const auto url = QStringLiteral("https://www.governikus.de/"); return url; } #endif @@ -85,11 +85,5 @@ const QString& ReaderConfigurationInfo::getPattern() const QSharedPointer ReaderConfigurationInfo::getIcon() const { - return Env::getSingleton()->getFile(QStringLiteral("reader"), d->mIcon, QStringLiteral(":/images/reader/default_reader.png")); -} - - -QSharedPointer ReaderConfigurationInfo::getIconWithNPA() const -{ - return Env::getSingleton()->getFile(QStringLiteral("reader"), d->mIconWithNPA, QStringLiteral(":/images/reader/default_reader_mit_ausweis.png")); + return Env::getSingleton()->getFile(QStringLiteral("reader"), d->mIcon, QStringLiteral(":/images/desktop/default_reader.png")); } diff --git a/src/configuration/ReaderConfigurationInfo.h b/src/configuration/ReaderConfigurationInfo.h index 28de934cf..10b14ca25 100644 --- a/src/configuration/ReaderConfigurationInfo.h +++ b/src/configuration/ReaderConfigurationInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -33,11 +33,10 @@ class ReaderConfigurationInfo const QString mUrl; const QString mPattern; const QString mIcon; - const QString mIconWithNPA; InternalInfo(bool pKnown, uint pVendorId, const QSet& pProductIds, const QString& pName, const QString& pUrl, - const QString& pPattern, const QString& pIcon, const QString& pIconWithNPA) + const QString& pPattern, const QString& pIcon) : mKnown(pKnown) , mVendorId(pVendorId) , mProductIds(pProductIds) @@ -45,7 +44,6 @@ class ReaderConfigurationInfo , mUrl(pUrl) , mPattern(pPattern) , mIcon(pIcon) - , mIconWithNPA(pIconWithNPA) { } @@ -58,8 +56,7 @@ class ReaderConfigurationInfo mName != pOther.mName || mUrl != pOther.mUrl || mPattern != pOther.mPattern || - mIcon != pOther.mIcon || - mIconWithNPA != pOther.mIconWithNPA); + mIcon != pOther.mIcon); } @@ -72,7 +69,7 @@ class ReaderConfigurationInfo explicit ReaderConfigurationInfo(const QString& pReaderName); ReaderConfigurationInfo(uint pVendorId, const QSet& pProductIds, const QString& pName, const QString& pUrl, const QString& pPattern, - const QString& pIcon, const QString& pIconWithNPA); + const QString& pIcon); virtual ~ReaderConfigurationInfo(); @@ -85,7 +82,6 @@ class ReaderConfigurationInfo [[nodiscard]] const QString& getUrl() const; [[nodiscard]] const QString& getPattern() const; [[nodiscard]] QSharedPointer getIcon() const; - [[nodiscard]] QSharedPointer getIconWithNPA() const; }; diff --git a/src/configuration/ReaderConfigurationParser.cpp b/src/configuration/ReaderConfigurationParser.cpp index 3eadf9e6d..3f6f3ab09 100644 --- a/src/configuration/ReaderConfigurationParser.cpp +++ b/src/configuration/ReaderConfigurationParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderConfigurationParser.h" @@ -98,22 +98,18 @@ bool ReaderConfigurationParser::EntryParser::matchPlatform(const QJsonArray& pPl return QOperatingSystemVersion(pCurrentVersion.type(), number.majorVersion(), minor, micro); }; - for (const QJsonValueConstRef entry : pPlatforms) - { - const auto& obj = entry.toObject(); - if (obj.value(QLatin1String("os")).toString() == currentOS) - { - const auto& min = obj.value(QLatin1String("min")).toString(); - const auto& max = obj.value(QLatin1String("max")).toString(); - - if (pCurrentVersion >= parseSystemVersion(min) && pCurrentVersion <= parseSystemVersion(max)) - { - return true; - } - } - } + return std::any_of(pPlatforms.constBegin(), pPlatforms.constEnd(), + [currentOS, pCurrentVersion, parseSystemVersion](const QJsonValueConstRef pEntry){ + const auto& obj = pEntry.toObject(); + if (obj.value(QLatin1String("os")).toString() == currentOS) + { + const auto& min = obj.value(QLatin1String("min")).toString(); + const auto& max = obj.value(QLatin1String("max")).toString(); + return pCurrentVersion >= parseSystemVersion(min) && pCurrentVersion <= parseSystemVersion(max); + } - return false; + return false; + }); } @@ -195,9 +191,8 @@ ReaderConfigurationInfo ReaderConfigurationParser::EntryParser::parse() const const QString& pattern = object.value(QLatin1String("Pattern")).toString(); const QString& icon = object.value(QLatin1String("Icon")).toString(); - const QString& iconWithNPA = object.value(QLatin1String("IconWithNPA")).toString(); - return ReaderConfigurationInfo(vendorId, productIds, name, url, pattern, icon, iconWithNPA); + return ReaderConfigurationInfo(vendorId, productIds, name, url, pattern, icon); } @@ -209,7 +204,7 @@ ReaderConfigurationInfo ReaderConfigurationParser::EntryParser::fail(const QStri } -QVector ReaderConfigurationParser::parse(const QByteArray& pData) +QList ReaderConfigurationParser::parse(const QByteArray& pData) { QJsonParseError error {}; QJsonDocument doc = QJsonDocument::fromJson(pData, &error); @@ -237,7 +232,7 @@ QVector ReaderConfigurationParser::parse(const QByteArr } const QJsonArray& devicesArray = devicesValue.toArray(); - QVector infos; + QList infos; for (const QJsonValueConstRef entry : devicesArray) { auto info = EntryParser(entry).parse(); @@ -263,14 +258,14 @@ QVector ReaderConfigurationParser::parse(const QByteArr } -QVector ReaderConfigurationParser::fail(const QString& pLogMessage) +QList ReaderConfigurationParser::fail(const QString& pLogMessage) { qCWarning(card_drivers) << pLogMessage; - return QVector(); + return QList(); } -bool ReaderConfigurationParser::hasUniqueId(const ReaderConfigurationInfo& pInfo, const QVector& pInfos) +bool ReaderConfigurationParser::hasUniqueId(const ReaderConfigurationInfo& pInfo, const QList& pInfos) { const uint vendorId = pInfo.getVendorId(); const QSet productIds = pInfo.getProductIds(); diff --git a/src/configuration/ReaderConfigurationParser.h b/src/configuration/ReaderConfigurationParser.h index 373df836c..823056b4f 100644 --- a/src/configuration/ReaderConfigurationParser.h +++ b/src/configuration/ReaderConfigurationParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -44,8 +44,8 @@ class ReaderConfigurationParser [[nodiscard]] ReaderConfigurationInfo parse() const; }; - static QVector fail(const QString& logMessage); - static bool hasUniqueId(const ReaderConfigurationInfo& pInfo, const QVector& pInfos); + static QList fail(const QString& logMessage); + static bool hasUniqueId(const ReaderConfigurationInfo& pInfo, const QList& pInfos); ReaderConfigurationParser() = delete; ~ReaderConfigurationParser() = delete; @@ -55,7 +55,7 @@ class ReaderConfigurationParser * Parses the configuration data and returns ReaderConfiguration. * In case of any errors, the QSharedPointer is empty. */ - static QVector parse(const QByteArray& pData); + static QList parse(const QByteArray& pData); }; diff --git a/src/configuration/ReleaseInformation.cpp b/src/configuration/ReleaseInformation.cpp index 411f88fcc..63d5b693a 100644 --- a/src/configuration/ReleaseInformation.cpp +++ b/src/configuration/ReleaseInformation.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "ReleaseInformation.h" @@ -40,17 +40,22 @@ QSharedPointer ReleaseInformation::getFile(const QString& pFile) } -QVector> ReleaseInformation::getReleaseNotes(const VersionNumber& pVersion, bool pConsiderOnlyThisVersion) +QList> ReleaseInformation::getReleaseNotes(const VersionNumber& pVersion, bool pConsiderOnlyThisVersion) { const auto versionNumber = pVersion.getVersionNumber(); + if (versionNumber.microVersion() >= 100) + { + const auto betaVersion = QVersionNumber(versionNumber.majorVersion(), versionNumber.minorVersion(), 100); + return {getFile(QStringLiteral("%1.txt").arg(betaVersion.toString()))}; + } + if (pConsiderOnlyThisVersion) { return {getFile(QStringLiteral("%1.txt").arg(versionNumber.toString()))}; } - QVector> releaseNotes; - + QList> releaseNotes; for (int i = versionNumber.microVersion(); i >= 0; --i) { const auto previousVersion = QVersionNumber(versionNumber.majorVersion(), versionNumber.minorVersion(), i); @@ -75,6 +80,11 @@ void ReleaseInformation::update() bool ReleaseInformation::requiresInitialUpdate() const { + if (mVersion.isBetaVersion()) + { + return true; + } + for (const auto& releaseNotesFile : mReleaseNotes) { if (releaseNotesFile->lookupPath().isEmpty()) diff --git a/src/configuration/ReleaseInformation.h b/src/configuration/ReleaseInformation.h index fd2671070..a0f934bf7 100644 --- a/src/configuration/ReleaseInformation.h +++ b/src/configuration/ReleaseInformation.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,10 +11,10 @@ #include "UpdatableFile.h" #include "VersionNumber.h" +#include #include #include #include -#include namespace governikus { @@ -25,13 +25,13 @@ class ReleaseInformation Q_OBJECT private: - const QVector> mReleaseNotes; + const QList> mReleaseNotes; const QSharedPointer mAnnouncements; const QSharedPointer mIssues; const VersionNumber mVersion; static QSharedPointer getFile(const QString& pFile); - static QVector> getReleaseNotes(const VersionNumber& pVersion, bool pConsiderOnlyThisVersion); + static QList> getReleaseNotes(const VersionNumber& pVersion, bool pConsiderOnlyThisVersion); Q_SIGNALS: void fireInformationChanged(); diff --git a/src/configuration/ReleaseInformationConfiguration.cpp b/src/configuration/ReleaseInformationConfiguration.cpp index 09405eb9b..7f1c80c6c 100644 --- a/src/configuration/ReleaseInformationConfiguration.cpp +++ b/src/configuration/ReleaseInformationConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "ReleaseInformationConfiguration.h" diff --git a/src/configuration/ReleaseInformationConfiguration.h b/src/configuration/ReleaseInformationConfiguration.h index 3ac5bfa51..c771c97a4 100644 --- a/src/configuration/ReleaseInformationConfiguration.h +++ b/src/configuration/ReleaseInformationConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/core/controller/AppController.cpp b/src/core/controller/AppController.cpp index dac5b1329..67996f36a 100644 --- a/src/core/controller/AppController.cpp +++ b/src/core/controller/AppController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AppController.h" @@ -12,15 +12,14 @@ #include "ReaderManager.h" #include "ResourceLoader.h" #include "SecureStorage.h" -#include "UILoader.h" -#include "UIPlugIn.h" +#include "UiLoader.h" +#include "UiPlugin.h" #include "VolatileSettings.h" #include "controller/ChangePinController.h" #include #include #include -#include #include #include @@ -97,6 +96,12 @@ bool AppController::eventFilter(QObject* pObj, QEvent* pEvent) } #endif + if (pEvent->type() == QEvent::Quit) + { + doShutdown(); + return true; + } + if (pEvent->type() == QEvent::ApplicationActivated) { Q_EMIT fireApplicationActivated(); @@ -132,8 +137,8 @@ void AppController::start() } #endif - auto* uiLoader = Env::getSingleton(); - connect(uiLoader, &UILoader::fireLoadedPlugin, this, &AppController::onUiPlugin); + auto* uiLoader = Env::getSingleton(); + connect(uiLoader, &UiLoader::fireLoadedPlugin, this, &AppController::onUiPlugin); if (!uiLoader->load() || !uiLoader->hasActiveUI()) { qCCritical(init) << "Cannot start without active UI"; @@ -150,7 +155,7 @@ void AppController::start() { // Start the ReaderManager *after* initializing the UIs. Otherwise the TrayIcon // will be created even when we're just showing an error message and shutdown after that. - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); connect(this, &AppController::fireShutdown, readerManager, &ReaderManager::shutdown, Qt::QueuedConnection); connect(readerManager, &ReaderManager::fireInitialized, this, &AppController::fireStarted, Qt::QueuedConnection); readerManager->init(); @@ -334,10 +339,10 @@ void AppController::completeShutdown() QCoreApplication::exit(mExitCode); }; - auto* uiLoader = Env::getSingleton(); + auto* uiLoader = Env::getSingleton(); if (uiLoader->isLoaded()) { - connect(uiLoader, &UILoader::fireRemovedAllPlugins, this, exitApp, Qt::QueuedConnection); + connect(uiLoader, &UiLoader::fireRemovedAllPlugins, this, exitApp, Qt::QueuedConnection); uiLoader->shutdown(); } else @@ -385,7 +390,7 @@ void AppController::waitForNetworkConnections(const std::function& pExit } -void AppController::onUiDominationRequested(const UIPlugIn* pUi, const QString& pInformation) +void AppController::onUiDominationRequested(const UiPlugin* pUi, const QString& pInformation) { bool accepted = false; if (mUiDomination == nullptr && canStartNewWorkflow()) @@ -403,6 +408,7 @@ void AppController::onUiDominationRelease() { if (mUiDomination) { + qDebug() << mUiDomination->metaObject()->className() << "released ui domination"; mUiDomination = nullptr; Q_EMIT fireUiDominationReleased(); } @@ -416,32 +422,32 @@ void AppController::onRestartApplicationRequested() } -void AppController::onUiPlugin(const UIPlugIn* pPlugin) +void AppController::onUiPlugin(const UiPlugin* pPlugin) { qCDebug(init) << "Register UI:" << pPlugin->metaObject()->className(); - connect(this, &AppController::fireShutdown, pPlugin, &UIPlugIn::doShutdown, Qt::QueuedConnection); - connect(this, &AppController::fireWorkflowStarted, pPlugin, &UIPlugIn::onWorkflowStarted); - connect(this, &AppController::fireWorkflowFinished, pPlugin, &UIPlugIn::onWorkflowFinished); - connect(this, &AppController::fireWorkflowUnhandled, pPlugin, &UIPlugIn::onWorkflowUnhandled); - connect(this, &AppController::fireInitialized, pPlugin, &UIPlugIn::onApplicationInitialized); - connect(this, &AppController::fireStarted, pPlugin, &UIPlugIn::onApplicationStarted); - connect(this, &AppController::fireShowUi, pPlugin, &UIPlugIn::onShowUi); - connect(this, &AppController::fireHideUi, pPlugin, &UIPlugIn::onHideUi); - connect(this, &AppController::fireTranslationChanged, pPlugin, &UIPlugIn::onTranslationChanged); - connect(this, &AppController::fireShowUserInformation, pPlugin, &UIPlugIn::onShowUserInformation); - connect(this, &AppController::fireApplicationActivated, pPlugin, &UIPlugIn::fireApplicationActivated); - connect(this, &AppController::fireUiDomination, pPlugin, &UIPlugIn::onUiDomination); - connect(this, &AppController::fireUiDominationReleased, pPlugin, &UIPlugIn::onUiDominationReleased); - connect(this, &AppController::fireProxyAuthenticationRequired, pPlugin, &UIPlugIn::onProxyAuthenticationRequired); - - connect(pPlugin, &UIPlugIn::fireWorkflowRequested, this, &AppController::onWorkflowRequested, Qt::QueuedConnection); - connect(pPlugin, &UIPlugIn::fireShowUiRequested, this, &AppController::fireShowUi, Qt::QueuedConnection); - connect(pPlugin, &UIPlugIn::fireShowUserInformationRequested, this, &AppController::fireShowUserInformation); - connect(pPlugin, &UIPlugIn::fireRestartApplicationRequested, this, &AppController::onRestartApplicationRequested, Qt::QueuedConnection); - connect(pPlugin, &UIPlugIn::fireQuitApplicationRequest, this, &AppController::doShutdown); - connect(pPlugin, &UIPlugIn::fireCloseReminderFinished, this, &AppController::onCloseReminderFinished); - connect(pPlugin, &UIPlugIn::fireUiDominationRequest, this, &AppController::onUiDominationRequested); - connect(pPlugin, &UIPlugIn::fireUiDominationRelease, this, &AppController::onUiDominationRelease); + connect(this, &AppController::fireShutdown, pPlugin, &UiPlugin::doShutdown, Qt::QueuedConnection); + connect(this, &AppController::fireWorkflowStarted, pPlugin, &UiPlugin::onWorkflowStarted); + connect(this, &AppController::fireWorkflowFinished, pPlugin, &UiPlugin::onWorkflowFinished); + connect(this, &AppController::fireWorkflowUnhandled, pPlugin, &UiPlugin::onWorkflowUnhandled); + connect(this, &AppController::fireInitialized, pPlugin, &UiPlugin::onApplicationInitialized); + connect(this, &AppController::fireStarted, pPlugin, &UiPlugin::onApplicationStarted); + connect(this, &AppController::fireShowUi, pPlugin, &UiPlugin::onShowUi); + connect(this, &AppController::fireHideUi, pPlugin, &UiPlugin::onHideUi); + connect(this, &AppController::fireTranslationChanged, pPlugin, &UiPlugin::onTranslationChanged); + connect(this, &AppController::fireShowUserInformation, pPlugin, &UiPlugin::onShowUserInformation); + connect(this, &AppController::fireApplicationActivated, pPlugin, &UiPlugin::fireApplicationActivated); + connect(this, &AppController::fireUiDomination, pPlugin, &UiPlugin::onUiDomination); + connect(this, &AppController::fireUiDominationReleased, pPlugin, &UiPlugin::onUiDominationReleased); + connect(this, &AppController::fireProxyAuthenticationRequired, pPlugin, &UiPlugin::onProxyAuthenticationRequired); + + connect(pPlugin, &UiPlugin::fireWorkflowRequested, this, &AppController::onWorkflowRequested, Qt::QueuedConnection); + connect(pPlugin, &UiPlugin::fireShowUiRequested, this, &AppController::fireShowUi, Qt::QueuedConnection); + connect(pPlugin, &UiPlugin::fireShowUserInformationRequested, this, &AppController::fireShowUserInformation); + connect(pPlugin, &UiPlugin::fireRestartApplicationRequested, this, &AppController::onRestartApplicationRequested, Qt::QueuedConnection); + connect(pPlugin, &UiPlugin::fireQuitApplicationRequest, this, &AppController::doShutdown); + connect(pPlugin, &UiPlugin::fireCloseReminderFinished, this, &AppController::onCloseReminderFinished); + connect(pPlugin, &UiPlugin::fireUiDominationRequest, this, &AppController::onUiDominationRequested); + connect(pPlugin, &UiPlugin::fireUiDominationRelease, this, &AppController::onUiDominationRelease); } @@ -493,6 +499,13 @@ bool AppController::nativeEventFilter(const QByteArray& pEventType, void* pMessa if (msg->message == WM_QUERYENDSESSION) { qCDebug(system) << "WM_QUERYENDSESSION received"; + *pResult = TRUE; + return true; + } + if (msg->message == WM_ENDSESSION) + { + qCDebug(system) << "WM_ENDSESSION received"; + *pResult = 0; doShutdown(); return true; } diff --git a/src/core/controller/AppController.h b/src/core/controller/AppController.h index 6c5a6f561..65bf19ee6 100644 --- a/src/core/controller/AppController.h +++ b/src/core/controller/AppController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,7 +9,7 @@ #pragma once #include "EnumHelper.h" -#include "UIPlugIn.h" +#include "UiPlugin.h" #include "WorkflowRequest.h" #include @@ -39,7 +39,7 @@ class AppController final QSharedPointer mActiveWorkflow; QSharedPointer mWaitingRequest; bool mShutdownRunning; - const UIPlugIn* mUiDomination; + const UiPlugin* mUiDomination; bool mRestartApplication; int mExitCode; @@ -70,17 +70,17 @@ class AppController final void fireTranslationChanged(); void fireProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator); void fireApplicationActivated(); - void fireUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted); + void fireUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted); void fireUiDominationReleased(); private Q_SLOTS: void doShutdown(int pExitCode = EXIT_SUCCESS); - void onUiPlugin(const UIPlugIn* pPlugin); + void onUiPlugin(const UiPlugin* pPlugin); void onWorkflowFinished(); void onWorkflowRequested(const QSharedPointer& pRequest); void onCloseReminderFinished(bool pDontRemindAgain); void onLanguageChanged(); - void onUiDominationRequested(const UIPlugIn* pUi, const QString& pInformation); + void onUiDominationRequested(const UiPlugin* pUi, const QString& pInformation); void onUiDominationRelease(); void onRestartApplicationRequested(); diff --git a/src/diagnosis/CMakeLists.txt b/src/diagnosis/CMakeLists.txt index fb854195a..61efa6966 100644 --- a/src/diagnosis/CMakeLists.txt +++ b/src/diagnosis/CMakeLists.txt @@ -6,4 +6,5 @@ if(DESKTOP AND TARGET ${Qt}::Qml) ADD_PLATFORM_LIBRARY(AusweisAppDiagnosis) target_link_libraries(AusweisAppDiagnosis ${Qt}::Qml AusweisAppCard) -endif() \ No newline at end of file + qt_extract_metatypes(AusweisAppDiagnosis) # QTBUG-123574 +endif() diff --git a/src/diagnosis/ContentItem.h b/src/diagnosis/ContentItem.h index 0bdf80f7c..21729af6f 100644 --- a/src/diagnosis/ContentItem.h +++ b/src/diagnosis/ContentItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/diagnosis/DiagnosisAntivirusDetection.cpp b/src/diagnosis/DiagnosisAntivirusDetection.cpp index 4883c22a2..755ca2958 100644 --- a/src/diagnosis/DiagnosisAntivirusDetection.cpp +++ b/src/diagnosis/DiagnosisAntivirusDetection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisAntivirusDetection.h" @@ -89,7 +89,7 @@ void DiagnosisAntivirusDetection::onError(QProcess::ProcessError pError) #endif -const QVector>& DiagnosisAntivirusDetection::getAntivirusInformations() const +const QList>& DiagnosisAntivirusDetection::getAntivirusInformations() const { return mAntivirInfos; } diff --git a/src/diagnosis/DiagnosisAntivirusDetection.h b/src/diagnosis/DiagnosisAntivirusDetection.h index 3070927ba..0482d1af2 100644 --- a/src/diagnosis/DiagnosisAntivirusDetection.h +++ b/src/diagnosis/DiagnosisAntivirusDetection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -61,7 +61,7 @@ class DiagnosisAntivirusDetection #if defined(Q_OS_WIN) QSharedPointer mProcess; #endif - QVector> mAntivirInfos; + QList> mAntivirInfos; void parseAntivirInfos(const QString& pAntivirInfos); private Q_SLOTS: @@ -77,7 +77,7 @@ class DiagnosisAntivirusDetection public: DiagnosisAntivirusDetection(); void startInformationProcess(); - [[nodiscard]] const QVector>& getAntivirusInformations() const; + [[nodiscard]] const QList>& getAntivirusInformations() const; }; } // namespace governikus diff --git a/src/diagnosis/DiagnosisConnectionTest.cpp b/src/diagnosis/DiagnosisConnectionTest.cpp index 93d7e61e9..791010327 100644 --- a/src/diagnosis/DiagnosisConnectionTest.cpp +++ b/src/diagnosis/DiagnosisConnectionTest.cpp @@ -1,10 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisConnectionTest.h" +#include "NetworkManager.h" #include "SecureStorage.h" +#include "TlsChecker.h" using namespace governikus; @@ -15,6 +17,7 @@ DiagnosisConnectionTest::DiagnosisConnectionTest() , mProxyPort() , mProxyType() , mProxyCapabilities() + , mErrorOfConnectionTestWithProxy() , mConnectionTestWithProxySuccessful(false) , mConnectionTestWithoutProxySuccessful(false) , mPingTestOnProxySuccessful(false) @@ -22,8 +25,8 @@ DiagnosisConnectionTest::DiagnosisConnectionTest() , mConnectionTestWithProxyDone(false) , mConnectionTestWithoutProxyDone(false) , mPingSocketToProxy() - , mTcpSocketWithProxy() , mTcpSocketWithoutProxy() + , mReplyWithProxy() { } @@ -48,17 +51,15 @@ void DiagnosisConnectionTest::onProxyPingTestError(QAbstractSocket::SocketError void DiagnosisConnectionTest::onSocketConnectionTestWithProxyDone() { - mConnectionTestWithProxySuccessful = true; - mTcpSocketWithProxy.disconnectFromHost(); - mConnectionTestWithProxyDone = true; - checkIfAllProcessesDone(); -} - - -void DiagnosisConnectionTest::onSocketConnectionTestWithProxyError(QAbstractSocket::SocketError pSocketError) -{ - qDebug() << "Could not connect to test server with proxy:" << pSocketError; mConnectionTestWithProxySuccessful = false; + if (mReplyWithProxy) + { + mConnectionTestWithProxySuccessful = (mReplyWithProxy->error() == QNetworkReply::NetworkError::NoError); + mErrorOfConnectionTestWithProxy = mReplyWithProxy->errorString(); + mReplyWithProxy->close(); + mReplyWithProxy.reset(); + } + mConnectionTestWithProxyDone = true; checkIfAllProcessesDone(); } @@ -159,7 +160,7 @@ void DiagnosisConnectionTest::startConnectionTest() mConnectionTestWithProxyDone = false; mConnectionTestWithoutProxyDone = false; - const QUrl& testUrl = QUrl(Env::getSingleton()->getUpdateServerBaseUrl()); + const QUrl& testUrl = QUrl(Env::getSingleton()->getAppcastUpdateUrl()); const auto& proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(testUrl)); const auto& proxy = proxies.constFirst(); if (proxies.size() > 1) @@ -190,11 +191,15 @@ void DiagnosisConnectionTest::startConnectionTest() connect(&mPingSocketToProxy, &QAbstractSocket::errorOccurred, this, &DiagnosisConnectionTest::onProxyPingTestError); mPingSocketToProxy.connectToHost(proxy.hostName(), proxy.port()); - mTcpSocketWithProxy.reset(); - mTcpSocketWithProxy.setProxy(proxy); - connect(&mTcpSocketWithProxy, &QAbstractSocket::connected, this, &DiagnosisConnectionTest::onSocketConnectionTestWithProxyDone); - connect(&mTcpSocketWithProxy, &QAbstractSocket::errorOccurred, this, &DiagnosisConnectionTest::onSocketConnectionTestWithProxyError); - mTcpSocketWithProxy.connectToHost(testUrl.host(), 443); + QNetworkRequest request(testUrl); + mReplyWithProxy = Env::getSingleton()->get(request); + connect(mReplyWithProxy.data(), &QNetworkReply::finished, this, &DiagnosisConnectionTest::onSocketConnectionTestWithProxyDone); + connect(mReplyWithProxy.data(), &QNetworkReply::sslErrors, this, [this](const QList& pErrors) { + if (mReplyWithProxy && TlsChecker::containsFatalError(mReplyWithProxy, pErrors)) + { + mReplyWithProxy->abort(); + } + }); } mTcpSocketWithoutProxy.reset(); diff --git a/src/diagnosis/DiagnosisConnectionTest.h b/src/diagnosis/DiagnosisConnectionTest.h index 725ff34c6..4038e8bd4 100644 --- a/src/diagnosis/DiagnosisConnectionTest.h +++ b/src/diagnosis/DiagnosisConnectionTest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #pragma once #include +#include #include #include @@ -36,6 +37,7 @@ class DiagnosisConnectionTest QString mProxyType; QString mProxyCapabilities; + QString mErrorOfConnectionTestWithProxy; bool mConnectionTestWithProxySuccessful; bool mConnectionTestWithoutProxySuccessful; @@ -46,8 +48,8 @@ class DiagnosisConnectionTest bool mConnectionTestWithoutProxyDone; QTcpSocket mPingSocketToProxy; - QTcpSocket mTcpSocketWithProxy; QTcpSocket mTcpSocketWithoutProxy; + QSharedPointer mReplyWithProxy; void checkIfAllProcessesDone(); static QString getProxyTypeAsQString(QNetworkProxy::ProxyType pType); @@ -57,7 +59,6 @@ class DiagnosisConnectionTest void onProxyPingTestDone(); void onProxyPingTestError(QAbstractSocket::SocketError pSocketError); void onSocketConnectionTestWithProxyDone(); - void onSocketConnectionTestWithProxyError(QAbstractSocket::SocketError pSocketError); void onSocketConnectionTestWithoutProxyDone(); void onSocketConnectionTestWithoutProxyError(QAbstractSocket::SocketError pSocketError); @@ -101,6 +102,12 @@ class DiagnosisConnectionTest } + [[nodiscard]] const QString& getErrorOfConnectionTestWithProxy() const + { + return mErrorOfConnectionTestWithProxy; + } + + [[nodiscard]] bool getConnectionTestWithoutProxySuccessful() const { return mConnectionTestWithoutProxySuccessful; diff --git a/src/diagnosis/DiagnosisFirewallDetection.cpp b/src/diagnosis/DiagnosisFirewallDetection.cpp index 2da408ee3..2fd740129 100644 --- a/src/diagnosis/DiagnosisFirewallDetection.cpp +++ b/src/diagnosis/DiagnosisFirewallDetection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisFirewallDetection.h" diff --git a/src/diagnosis/DiagnosisFirewallDetection.h b/src/diagnosis/DiagnosisFirewallDetection.h index c1402a99a..80fbc337f 100644 --- a/src/diagnosis/DiagnosisFirewallDetection.h +++ b/src/diagnosis/DiagnosisFirewallDetection.h @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once +#include #include #include -#include #if defined(Q_OS_WIN) #include @@ -81,8 +81,8 @@ class DiagnosisFirewallDetection bool mFirstFirewallRuleEnabled; bool mSecondFirewallRuleExists; bool mSecondFirewallRuleEnabled; - QVector> mDetectedFirewalls; - QVector> mFirewallProfiles; + QList> mDetectedFirewalls; + QList> mFirewallProfiles; bool mFirstRuleDone; bool mSecondRuleDone; @@ -140,13 +140,13 @@ class DiagnosisFirewallDetection } - [[nodiscard]] const QVector>& getFirewallProfiles() const + [[nodiscard]] const QList>& getFirewallProfiles() const { return mFirewallProfiles; } - [[nodiscard]] const QVector>& getDetectedFirewalls() const + [[nodiscard]] const QList>& getDetectedFirewalls() const { return mDetectedFirewalls; } diff --git a/src/diagnosis/DiagnosisModel.cpp b/src/diagnosis/DiagnosisModel.cpp index 802b242b8..a544eee98 100644 --- a/src/diagnosis/DiagnosisModel.cpp +++ b/src/diagnosis/DiagnosisModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisModel.h" @@ -47,16 +47,16 @@ DiagnosisModel::DiagnosisModel() , mFirewallSection() { mSections[Section::GENERAL].reset(new SectionModel()); - QQmlEngine::setObjectOwnership(mSections[Section::GENERAL].data(), QQmlEngine::CppOwnership); + QQmlEngine::setObjectOwnership(mSections.value(Section::GENERAL).data(), QQmlEngine::CppOwnership); mSections[Section::READER].reset(new SectionModel()); - QQmlEngine::setObjectOwnership(mSections[Section::READER].data(), QQmlEngine::CppOwnership); + QQmlEngine::setObjectOwnership(mSections.value(Section::READER).data(), QQmlEngine::CppOwnership); mSections[Section::NETWORK].reset(new SectionModel()); - QQmlEngine::setObjectOwnership(mSections[Section::NETWORK].data(), QQmlEngine::CppOwnership); + QQmlEngine::setObjectOwnership(mSections.value(Section::NETWORK).data(), QQmlEngine::CppOwnership); mSections[Section::SECURITY].reset(new SectionModel()); - QQmlEngine::setObjectOwnership(mSections[Section::SECURITY].data(), QQmlEngine::CppOwnership); + QQmlEngine::setObjectOwnership(mSections.value(Section::SECURITY).data(), QQmlEngine::CppOwnership); initContent(); @@ -506,6 +506,8 @@ void DiagnosisModel::onConnectionTestDone() { //: LABEL DESKTOP proxyInfo << tr("Connection test with proxy: Failed"); + //: LABEL DESKTOP + proxyInfo << tr("Encountered error: %1").arg(mConnectionTest.getErrorOfConnectionTestWithProxy()); } } else @@ -599,7 +601,7 @@ void DiagnosisModel::onFirewallInformationReady() if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) { //: LABEL DESKTOP - mFirewallSection << ContentItem(QString(), tr("Third party firewalls cannot be detected on Windows 7.")); + mFirewallSection << ContentItem(QString(), tr("3rd party firewalls cannot be detected on Windows 7.")); } else { @@ -607,7 +609,7 @@ void DiagnosisModel::onFirewallInformationReady() { #endif //: LABEL DESKTOP - mFirewallSection << ContentItem(QString(), tr("No third party firewalls detected")); + mFirewallSection << ContentItem(QString(), tr("No 3rd party firewalls detected")); } } else @@ -625,7 +627,7 @@ void DiagnosisModel::onFirewallInformationReady() firewallInfos << tr("Up to date: %1").arg(uptodate); } //: LABEL DESKTOP - mFirewallSection << ContentItem(tr("Firewalls from third party vendors"), firewallInfos.join(QLatin1Char('\n'))); + mFirewallSection << ContentItem(tr("Firewalls from 3rd party vendors"), firewallInfos.join(QLatin1Char('\n'))); } QStringList windowsFirewallSettings; diff --git a/src/diagnosis/DiagnosisModel.h b/src/diagnosis/DiagnosisModel.h index 9a0752dd6..fdfe6c06e 100644 --- a/src/diagnosis/DiagnosisModel.h +++ b/src/diagnosis/DiagnosisModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -13,12 +13,13 @@ #include "controller/DiagnosisController.h" #include +#include #include #include #include #include #include -#include +#include class test_DiagnosisModel; @@ -31,6 +32,7 @@ class DiagnosisModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT friend class ::test_DiagnosisModel; @@ -54,26 +56,26 @@ class DiagnosisModel QSharedPointer mContext; DiagnosisController mDiagnosisController; - QVector mAusweisAppSection; - QVector mTimestampSection; + QList mAusweisAppSection; + QList mTimestampSection; bool mRemoteDeviceSectionRunning; - QVector mRemoteDeviceSection; + QList mRemoteDeviceSection; bool mCardReaderSectionRunning; - QVector mCardReaderSection; + QList mCardReaderSection; bool mPcscSectionRunning; - QVector mPcscSection; + QList mPcscSection; DiagnosisConnectionTest mConnectionTest; - QVector mNetworkConnectionSection; - QVector mNetworkInterfaceSection; + QList mNetworkConnectionSection; + QList mNetworkInterfaceSection; bool mAntivirusSectionRunning; DiagnosisAntivirusDetection mAntivirusDetection; - QVector mAntivirusSection; + QList mAntivirusSection; bool mFirewallSectionRunning; DiagnosisFirewallDetection mFirewallDetection; - QVector mFirewallSection; + QList mFirewallSection; [[nodiscard]] QString getSectionName(Section pSection) const; void initGeneralSections(); diff --git a/src/diagnosis/SectionModel.cpp b/src/diagnosis/SectionModel.cpp index 0fc67249f..9fab1b8f2 100644 --- a/src/diagnosis/SectionModel.cpp +++ b/src/diagnosis/SectionModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "SectionModel.h" @@ -80,7 +80,7 @@ void SectionModel::removeAllItems() } -void SectionModel::addContent(const QVector& pContent) +void SectionModel::addContent(const QList& pContent) { if (pContent.empty()) { diff --git a/src/diagnosis/SectionModel.h b/src/diagnosis/SectionModel.h index f617b90d3..8646228c9 100644 --- a/src/diagnosis/SectionModel.h +++ b/src/diagnosis/SectionModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -7,10 +7,10 @@ #include "ContentItem.h" #include +#include #include #include #include -#include class test_DiagnosisModel; @@ -32,7 +32,7 @@ class SectionModel ContentRole }; - QVector mContentItems; + QList mContentItems; public: explicit SectionModel(QObject* pParent = nullptr); @@ -42,7 +42,7 @@ class SectionModel [[nodiscard]] QHash roleNames() const override; void removeAllItems(); - void addContent(const QVector& pContent); + void addContent(const QList& pContent); [[nodiscard]] QStringList getAsPlaintext(const QString& pPrependString = QString()) const; }; diff --git a/src/diagnosis/context/DiagnosisContext.cpp b/src/diagnosis/context/DiagnosisContext.cpp index aff7e1da1..6d5b68f10 100644 --- a/src/diagnosis/context/DiagnosisContext.cpp +++ b/src/diagnosis/context/DiagnosisContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisContext.h" @@ -21,8 +21,8 @@ DiagnosisContext::DiagnosisContext() } -void DiagnosisContext::setPcscInfo(const QString& pVersion, const QVector& pComponents, - const QVector& pDrivers) +void DiagnosisContext::setPcscInfo(const QString& pVersion, const QList& pComponents, + const QList& pDrivers) { mPcscVersion = pVersion; mPcscComponents = pComponents; @@ -32,7 +32,7 @@ void DiagnosisContext::setPcscInfo(const QString& pVersion, const QVector& mInfos) +void DiagnosisContext::setReaderInfos(const QList& mInfos) { mReaderInfos = mInfos; @@ -40,7 +40,7 @@ void DiagnosisContext::setReaderInfos(const QVector& mInfos) } -void DiagnosisContext::setReaderInfosNoDriver(const QVector& pInfos) +void DiagnosisContext::setReaderInfosNoDriver(const QList& pInfos) { mReaderInfosNoDriver = pInfos; diff --git a/src/diagnosis/context/DiagnosisContext.h b/src/diagnosis/context/DiagnosisContext.h index edf56e5d1..671cecaa8 100644 --- a/src/diagnosis/context/DiagnosisContext.h +++ b/src/diagnosis/context/DiagnosisContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,10 +11,10 @@ #include "ReaderInfo.h" #include +#include #include #include #include -#include namespace governikus { @@ -29,10 +29,10 @@ class DiagnosisContext private: QString mPcscVersion; - QVector mPcscComponents; - QVector mPcscDrivers; - QVector mReaderInfos; - QVector mReaderInfosNoDriver; + QList mPcscComponents; + QList mPcscDrivers; + QList mReaderInfos; + QList mReaderInfosNoDriver; QDateTime mTimestamp; QList mNetworkInterfaces; @@ -45,36 +45,36 @@ class DiagnosisContext } - [[nodiscard]] const QVector& getPcscComponents() const + [[nodiscard]] const QList& getPcscComponents() const { return mPcscComponents; } - [[nodiscard]] const QVector& getPcscDrivers() const + [[nodiscard]] const QList& getPcscDrivers() const { return mPcscDrivers; } - void setPcscInfo(const QString& pVersion, const QVector& pComponents, const QVector& pDrivers); + void setPcscInfo(const QString& pVersion, const QList& pComponents, const QList& pDrivers); - [[nodiscard]] const QVector& getReaderInfos() const + [[nodiscard]] const QList& getReaderInfos() const { return mReaderInfos; } - void setReaderInfos(const QVector& mInfos); + void setReaderInfos(const QList& mInfos); - [[nodiscard]] const QVector& getReaderInfosNoDriver() const + [[nodiscard]] const QList& getReaderInfosNoDriver() const { return mReaderInfosNoDriver; } - void setReaderInfosNoDriver(const QVector& pInfos); + void setReaderInfosNoDriver(const QList& pInfos); [[nodiscard]] const QDateTime& getTimestamp() const { diff --git a/src/diagnosis/controller/DiagnosisController.cpp b/src/diagnosis/controller/DiagnosisController.cpp index 03e2afede..f568f4003 100644 --- a/src/diagnosis/controller/DiagnosisController.cpp +++ b/src/diagnosis/controller/DiagnosisController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DiagnosisController.h" @@ -25,7 +25,7 @@ DiagnosisController::DiagnosisController(const QSharedPointer& connect(Env::getSingleton(), &ReaderDetector::fireReaderChangeDetected, this, &DiagnosisController::onReaderEvent); - const auto& readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::fireReaderAdded, this, &DiagnosisController::onReaderEvent); connect(readerManager, &ReaderManager::fireReaderRemoved, this, &DiagnosisController::onReaderEvent); connect(readerManager, &ReaderManager::fireCardInserted, this, &DiagnosisController::onReaderEvent); @@ -37,14 +37,14 @@ DiagnosisController::DiagnosisController(const QSharedPointer& DiagnosisController::~DiagnosisController() { qCDebug(diagnosis) << "Stopping PCSC scan."; - Env::getSingleton()->stopScan(ReaderManagerPlugInType::PCSC); + Env::getSingleton()->stopScan(ReaderManagerPluginType::PCSC); } void DiagnosisController::run() { qCDebug(diagnosis) << "Starting PCSC scan."; - Env::getSingleton()->startScan(ReaderManagerPlugInType::PCSC); + Env::getSingleton()->startScan(ReaderManagerPluginType::PCSC); mWatcherPcscInfo.setFuture(QtConcurrent::run(&DiagnosisController::retrievePcscInfo)); collectInterfaceInformation(); @@ -68,10 +68,10 @@ void DiagnosisController::collectInterfaceInformation() DiagnosisController::PcscInfo DiagnosisController::retrievePcscInfo() { PcscInfo result; - const auto& pcscInfo = Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::PCSC); + const auto& pcscInfo = Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::PCSC); if (pcscInfo.isAvailable()) { - const QVariant version = pcscInfo.getValue(ReaderManagerPlugInInfo::Key::PCSC_LITE_VERSION); + const QVariant version = pcscInfo.getValue(ReaderManagerPluginInfo::Key::PCSC_LITE_VERSION); if (version.isValid()) { result.mPcscVersion = tr("pcsclite %1").arg(version.toString()); @@ -99,22 +99,21 @@ DiagnosisController::PcscInfo DiagnosisController::retrievePcscInfo() void DiagnosisController::onReaderEvent() { const auto& readersWithDriver = Env::getSingleton()->getReaderInfos(); - QVector readersWithDriverInfos; + QList readersWithDriverInfos; for (const auto& reader : readersWithDriver) { readersWithDriverInfos << reader.getReaderConfigurationInfo(); } auto attachedDevices = Env::getSingleton()->getAttachedSupportedDevices(); - const auto& driverIsInstalled = - [readersWithDriverInfos](const ReaderConfigurationInfo& readerInfo) - { - return readersWithDriverInfos.contains(readerInfo); - }; - - attachedDevices.erase( - std::remove_if(attachedDevices.begin(), attachedDevices.end(), driverIsInstalled), - attachedDevices.end()); + QMutableListIterator iter(attachedDevices); + while (iter.hasNext()) + { + if (readersWithDriverInfos.contains(iter.next())) + { + iter.remove(); + } + } mContext->setReaderInfosNoDriver(attachedDevices); diff --git a/src/diagnosis/controller/DiagnosisController.h b/src/diagnosis/controller/DiagnosisController.h index abeb3c8f7..eae05d785 100644 --- a/src/diagnosis/controller/DiagnosisController.h +++ b/src/diagnosis/controller/DiagnosisController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -26,8 +26,8 @@ class DiagnosisController struct PcscInfo { QString mPcscVersion; - QVector mPcscComponents; - QVector mPcscDrivers; + QList mPcscComponents; + QList mPcscDrivers; }; QSharedPointer mContext; @@ -36,8 +36,8 @@ class DiagnosisController void collectInterfaceInformation(); static PcscInfo retrievePcscInfo(); - static void getPcscInfo(QVector& pComponents, - QVector& pDrivers); + static void getPcscInfo(QList& pComponents, + QList& pDrivers); public: explicit DiagnosisController(const QSharedPointer& pContext, QObject* pParent = nullptr); diff --git a/src/diagnosis/controller/DiagnosisController_generic.cpp b/src/diagnosis/controller/DiagnosisController_generic.cpp index cfd3a3221..13aba3861 100644 --- a/src/diagnosis/controller/DiagnosisController_generic.cpp +++ b/src/diagnosis/controller/DiagnosisController_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,8 +13,8 @@ using namespace governikus; -void DiagnosisController::getPcscInfo(QVector& pComponents, - QVector& pDrivers) +void DiagnosisController::getPcscInfo(QList& pComponents, + QList& pDrivers) { Q_UNUSED(pComponents) Q_UNUSED(pDrivers) diff --git a/src/diagnosis/controller/DiagnosisController_osx.mm b/src/diagnosis/controller/DiagnosisController_osx.mm index da693253b..98471a3cd 100644 --- a/src/diagnosis/controller/DiagnosisController_osx.mm +++ b/src/diagnosis/controller/DiagnosisController_osx.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -135,8 +135,8 @@ static QString runProcessAndReadAllOutput(const QString& pProgramm, const QStrin } -void DiagnosisController::getPcscInfo(QVector& /*pComponents*/, - QVector& pDrivers) +void DiagnosisController::getPcscInfo(QList& /*pComponents*/, + QList& pDrivers) { QString driverDirectory = QStringLiteral("/usr/libexec/SmartCardServices/drivers"); QString driverDirectoryLocal = QStringLiteral("/usr/local/libexec/SmartCardServices/drivers"); diff --git a/src/diagnosis/controller/DiagnosisController_win.cpp b/src/diagnosis/controller/DiagnosisController_win.cpp index e2b3e7021..1cb38912f 100644 --- a/src/diagnosis/controller/DiagnosisController_win.cpp +++ b/src/diagnosis/controller/DiagnosisController_win.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -79,7 +79,7 @@ static QString getWindowsFileVersionString(LPVOID pVersionData, const char* cons } -static void addWindowsComponentInfo(QVector& pComponents, const QString& pFileName) +static void addWindowsComponentInfo(QList& pComponents, const QString& pFileName) { std::wstring fileName = pFileName.toStdWString(); @@ -243,8 +243,8 @@ static QString getWindowsServiceDriverFileName(const QString& pServiceName) #endif -void DiagnosisController::getPcscInfo(QVector& pComponents, - QVector& pDrivers) +void DiagnosisController::getPcscInfo(QList& pComponents, + QList& pDrivers) { #ifndef Q_OS_WINRT addWindowsComponentInfo(pComponents, toAbsoluteWindowsDirectoryPath(QStringLiteral("System32\\WinSCard.dll"))); diff --git a/src/file_provider/Downloader.cpp b/src/file_provider/Downloader.cpp index cbcaa9d91..d9c74bf96 100644 --- a/src/file_provider/Downloader.cpp +++ b/src/file_provider/Downloader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "Downloader.h" @@ -22,7 +22,7 @@ using namespace governikus; static const char* const cABORTED = "aborted_download"; -void Downloader::scheduleDownload(QSharedPointer pDownloadRequest) +void Downloader::scheduleDownload(const QNetworkRequest& pDownloadRequest) { mPendingRequests.enqueue(pDownloadRequest); @@ -44,7 +44,8 @@ void Downloader::startDownloadIfPending() return; } - mCurrentReply = Env::getSingleton()->getAsUpdater(*mPendingRequests.dequeue()); + auto request = mPendingRequests.dequeue(); + mCurrentReply = Env::getSingleton()->getAsUpdater(request); connect(mCurrentReply.data(), &QNetworkReply::metaDataChanged, this, &Downloader::onMetadataChanged); connect(mCurrentReply.data(), &QNetworkReply::finished, this, &Downloader::onNetworkReplyFinished); @@ -102,34 +103,32 @@ void Downloader::onNetworkReplyFinished() if (const auto& readData = mCurrentReply->readAll(); !hasError && readData.size() > 0) { Q_EMIT fireDownloadSuccess(url, lastModified, readData); + return; } - else - { - qCCritical(fileprovider).nospace() << "Received no data." << mCurrentReply->errorString() << " [" << textForLog << "]"; - Q_EMIT fireDownloadFailed(url, NetworkManager::toStatus(mCurrentReply).getStatusCode()); - } - break; + + qCCritical(fileprovider).nospace() << "Received no data." << mCurrentReply->errorString() << " [" << textForLog << "]"; + Q_EMIT fireDownloadFailed(url, NetworkManager::toStatus(mCurrentReply).getStatusCode()); + return; } case HTTP_STATUS_NOT_MODIFIED: Q_EMIT fireDownloadUnnecessary(url); - break; + return; case HTTP_STATUS_NOT_FOUND: Q_EMIT fireDownloadFailed(url, GlobalStatus::Code::Downloader_File_Not_Found); - break; + return; default: if (hasError) { qCCritical(fileprovider).nospace() << mCurrentReply->errorString() << " [" << textForLog << "]"; Q_EMIT fireDownloadFailed(url, NetworkManager::toStatus(mCurrentReply).getStatusCode()); + return; } - else - { - qCCritical(fileprovider).nospace() << "Invalid HTTP status code for [" << textForLog << "]"; - Q_EMIT fireDownloadFailed(url, GlobalStatus::Code::Network_Other_Error); - } + + qCCritical(fileprovider).nospace() << "Invalid HTTP status code for [" << textForLog << "]"; + Q_EMIT fireDownloadFailed(url, GlobalStatus::Code::Network_Other_Error); } } @@ -170,11 +169,11 @@ bool Downloader::abort(const QUrl& pUpdateUrl) aborted = true; } - QMutableListIterator> iterator(mPendingRequests); + QMutableListIterator iterator(mPendingRequests); while (iterator.hasNext()) { const auto item = iterator.next(); - if (item->url() == pUpdateUrl) + if (item.url() == pUpdateUrl) { qCDebug(fileprovider) << "Remove pending request"; @@ -192,10 +191,10 @@ void Downloader::download(const QUrl& pUpdateUrl, const QDateTime& pCurrentTimes { QMetaObject::invokeMethod(this, [this, pUpdateUrl, pCurrentTimestamp] { qCDebug(fileprovider) << "Download:" << pUpdateUrl; - auto request = QSharedPointer::create(pUpdateUrl); + QNetworkRequest request(pUpdateUrl); if (pCurrentTimestamp.isValid()) { - request->setHeader(QNetworkRequest::IfModifiedSinceHeader, pCurrentTimestamp); + request.setHeader(QNetworkRequest::IfModifiedSinceHeader, pCurrentTimestamp); } scheduleDownload(request); }); diff --git a/src/file_provider/Downloader.h b/src/file_provider/Downloader.h index af45a5e66..fd9e9609f 100644 --- a/src/file_provider/Downloader.h +++ b/src/file_provider/Downloader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -29,9 +29,9 @@ class Downloader private: QSharedPointer mCurrentReply; - QQueue> mPendingRequests; + QQueue mPendingRequests; - void scheduleDownload(QSharedPointer pDownloadRequest); + void scheduleDownload(const QNetworkRequest& pDownloadRequest); void startDownloadIfPending(); protected: diff --git a/src/file_provider/FileProvider.cpp b/src/file_provider/FileProvider.cpp index 6f2af2a76..197139e4f 100644 --- a/src/file_provider/FileProvider.cpp +++ b/src/file_provider/FileProvider.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "FileProvider.h" diff --git a/src/file_provider/FileProvider.h b/src/file_provider/FileProvider.h index f90e445e4..15b7f9785 100644 --- a/src/file_provider/FileProvider.h +++ b/src/file_provider/FileProvider.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/file_provider/UpdatableFile.cpp b/src/file_provider/UpdatableFile.cpp index 86f0b0f58..6f90eea41 100644 --- a/src/file_provider/UpdatableFile.cpp +++ b/src/file_provider/UpdatableFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "UpdatableFile.h" @@ -56,8 +56,8 @@ const QString& UpdatableFile::getSectionCachePath() const QString UpdatableFile::qrcPath() const { - const QString prefix = QStringLiteral("updatable-files"); - const QString path = QStringLiteral(":/") + prefix + Sep + mSection + Sep + mName; + const auto prefix = QStringLiteral("updatable-files"); + const auto path = QStringLiteral(":/") + prefix + Sep + mSection + Sep + mName; return QFile::exists(path) ? path : QString(); } diff --git a/src/file_provider/UpdatableFile.h b/src/file_provider/UpdatableFile.h index 303dc684c..4740a80dd 100644 --- a/src/file_provider/UpdatableFile.h +++ b/src/file_provider/UpdatableFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/global/BuildHelper.cpp b/src/global/BuildHelper.cpp index d3b506f3e..9b913cf98 100644 --- a/src/global/BuildHelper.cpp +++ b/src/global/BuildHelper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "BuildHelper.h" @@ -149,9 +149,9 @@ QByteArrayList BuildHelper::getAppCertificates(const QString& pPackageName) #endif -QVector> BuildHelper::getInformationHeader() +QList> BuildHelper::getInformationHeader() { - QVector> data; + QList> data; const auto& add = [&data](const char* pKey, const QString& pStr) { data << qMakePair(QLatin1String(pKey), pStr); @@ -251,10 +251,9 @@ void BuildHelper::processInformationHeader(const std::function +#include #include #include -#include #ifdef Q_OS_ANDROID #include @@ -43,7 +43,7 @@ class BuildHelper [[nodiscard]] static bool fetchUserInteractive(); public: - static QVector> getInformationHeader(); + static QList> getInformationHeader(); static void processInformationHeader(const std::function& pFunc, bool pTranslate = true); [[nodiscard]] static CertificateType getCertificateType(); diff --git a/src/global/CMakeLists.txt b/src/global/CMakeLists.txt index 94ebcd851..e59103a42 100644 --- a/src/global/CMakeLists.txt +++ b/src/global/CMakeLists.txt @@ -6,3 +6,4 @@ ADD_PLATFORM_LIBRARY(AusweisAppGlobal) target_link_libraries(AusweisAppGlobal ${Qt}::Core OpenSSL::Crypto ${OSX_SECURITY}) +qt_extract_metatypes(AusweisAppGlobal) # QTBUG-123574 diff --git a/src/global/CardReturnCode.cpp b/src/global/CardReturnCode.cpp index 66cde0382..abb336512 100644 --- a/src/global/CardReturnCode.cpp +++ b/src/global/CardReturnCode.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardReturnCode.h" @@ -15,6 +15,7 @@ GlobalStatus CardReturnCodeUtil::toGlobalStatus(CardReturnCode pCode) { case CardReturnCode::OK: case CardReturnCode::OK_PUK: + case CardReturnCode::OK_CAN: return GlobalStatus::Code::No_Error; case CardReturnCode::UNDEFINED: @@ -22,7 +23,7 @@ GlobalStatus CardReturnCodeUtil::toGlobalStatus(CardReturnCode pCode) return GlobalStatus::Code::Unknown_Error; case CardReturnCode::CARD_NOT_FOUND: - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: return GlobalStatus::Code::Card_Not_Found; case CardReturnCode::COMMAND_FAILED: @@ -92,7 +93,7 @@ bool CardReturnCodeUtil::equalsWrongPacePassword(CardReturnCode pCode) return true; case CardReturnCode::UNDEFINED: - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: case CardReturnCode::CARD_NOT_FOUND: case CardReturnCode::UNKNOWN: case CardReturnCode::COMMAND_FAILED: @@ -101,6 +102,7 @@ bool CardReturnCodeUtil::equalsWrongPacePassword(CardReturnCode pCode) case CardReturnCode::UNEXPECTED_TRANSMIT_STATUS: case CardReturnCode::OK: case CardReturnCode::OK_PUK: + case CardReturnCode::OK_CAN: case CardReturnCode::CANCELLATION_BY_USER: case CardReturnCode::PUK_INOPERATIVE: case CardReturnCode::INPUT_TIME_OUT: diff --git a/src/global/CardReturnCode.h b/src/global/CardReturnCode.h index 691f830a7..7c2bf44b5 100644 --- a/src/global/CardReturnCode.h +++ b/src/global/CardReturnCode.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,11 +14,12 @@ namespace governikus { -defineEnumType(CardReturnCode, +defineEnumTypeQmlExposed(CardReturnCode, UNDEFINED, OK, OK_PUK, - RETRY_ALLOWED, + OK_CAN, + RESPONSE_EMPTY, CARD_NOT_FOUND, UNKNOWN, INPUT_TIME_OUT, diff --git a/src/global/DeviceInfo.cpp b/src/global/DeviceInfo.cpp index 4ff71f66e..8e5c2de58 100644 --- a/src/global/DeviceInfo.cpp +++ b/src/global/DeviceInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "DeviceInfo.h" diff --git a/src/global/DeviceInfo.h b/src/global/DeviceInfo.h index e6193f268..5f1a77fb8 100644 --- a/src/global/DeviceInfo.h +++ b/src/global/DeviceInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/global/ECardApiResult.cpp b/src/global/ECardApiResult.cpp index e1e99921d..f5ad1033e 100644 --- a/src/global/ECardApiResult.cpp +++ b/src/global/ECardApiResult.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ECardApiResult.h" diff --git a/src/global/ECardApiResult.h b/src/global/ECardApiResult.h index 3586647e8..60553c16b 100644 --- a/src/global/ECardApiResult.h +++ b/src/global/ECardApiResult.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,7 +21,7 @@ class test_ECardApiResult; -class test_UrlUtil; +class test_StateRedirectBrowser; namespace governikus @@ -35,7 +35,7 @@ class ECardApiResult friend class IfdMessageResponse; friend class StartPaosResponse; friend class ::test_ECardApiResult; - friend class ::test_UrlUtil; + friend class ::test_StateRedirectBrowser; public: enum class Major @@ -161,8 +161,8 @@ class ECardApiResult [[nodiscard]] const QString& getMessageLang() const; [[nodiscard]] const std::optional& getFailureCode() const; - static QString getMajorString(Major pMajor); - static QString getMinorString(Minor pMinor); + [[nodiscard]] static QString getMajorString(Major pMajor); + [[nodiscard]] static QString getMinorString(Minor pMinor); [[nodiscard]] QString getMajorString() const; [[nodiscard]] QString getMinorString() const; diff --git a/src/global/EnumHelper.h b/src/global/EnumHelper.h index 384bd75e1..07503cffe 100644 --- a/src/global/EnumHelper.h +++ b/src/global/EnumHelper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,19 +8,10 @@ #pragma once -#include "Initializer.h" - #include #include #include -namespace governikus -{ -#define defineQHash(enumName)\ - inline size_t qHash(enumName pKey, size_t pSeed)\ - {\ - return ::qHash(static_cast>(pKey), pSeed);\ - } #define defineEnumOperators(enumName)\ inline QDebug operator<<(QDebug pDbg, enumName pType)\ @@ -29,7 +20,18 @@ namespace governikus return pDbg.noquote() << Enum::getName(pType);\ }\ \ - inline QString& operator+=(QString & pStr, enumName pType)\ + inline QDebug operator<<(QDebug pDbg, const QList& pList)\ + {\ + QDebugStateSaver saver(pDbg);\ + QByteArrayList list;\ + for (const auto& entry : pList)\ + {\ + list << Enum::getName(entry).data();\ + }\ + return pDbg.noquote().nospace() << '(' << list.join(QByteArrayView(", ")) << ')';\ + }\ +\ + inline QString& operator+=(QString& pStr, enumName pType)\ {\ pStr += Enum::getName(pType);\ return pStr;\ @@ -53,42 +55,45 @@ namespace governikus {\ return !(pType == pName);\ }\ - defineQHash(enumName) +\ + inline size_t qHash(enumName pKey, size_t pSeed)\ + {\ + return ::qHash(static_cast>(pKey), pSeed);\ + } -#define defineTypedEnumType(enumName, enumType, ...)\ - class Enum##enumName\ +#define defineTypedEnumTypeProperty(enumName, enumType, enumProperty, ...)\ + namespace Enum##enumName\ {\ - Q_GADGET\ -\ - Q_DISABLE_COPY(Enum##enumName)\ + Q_NAMESPACE\ + enumProperty\ \ - private:\ - Enum##enumName();\ -\ - public:\ - enum class enumName : enumType\ - {\ - __VA_ARGS__\ - };\ -\ - Q_ENUM(enumName)\ + enum class enumName : enumType\ + {\ + __VA_ARGS__\ };\ \ - using enumName = Enum##enumName::enumName;\ - namespace governikusEnum##enumName\ - {\ - INIT_FUNCTION([]\ - {\ - qRegisterMetaType(#enumName);\ - })\ + Q_ENUM_NS(enumName)\ +\ + defineEnumOperators(enumName)\ }\ \ - defineEnumOperators(enumName) + using namespace Enum##enumName; +#define defineTypedEnumType(enumName, enumType, ...) defineTypedEnumTypeProperty(enumName, enumType, , __VA_ARGS__) #define defineEnumType(enumName, ...) defineTypedEnumType(enumName, int, __VA_ARGS__) +/* *INDENT-OFF* */ +#define ENUM_HELPER_OP ( +#define ENUM_HELPER_CP ) +#define ENUM_HELPER_CO , +/* *INDENT-ON* */ +#define defineEnumTypeQmlExposed(enumName, ...) defineTypedEnumTypeProperty(enumName, int, Q_CLASSINFO ENUM_HELPER_OP "QML.Element" ENUM_HELPER_CO #enumName ENUM_HELPER_CP, __VA_ARGS__) + + +namespace governikus +{ template class Enum { @@ -133,9 +138,9 @@ template class Enum } - [[nodiscard]] static QVector getList() + [[nodiscard]] static QList getList() { - QVector list; + QList list; const QMetaEnum metaEnum = getQtEnumMetaEnum(); list.reserve(metaEnum.keyCount()); diff --git a/src/global/Env.cpp b/src/global/Env.cpp index 6afa4caab..0f4743f48 100644 --- a/src/global/Env.cpp +++ b/src/global/Env.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "Env.h" diff --git a/src/global/Env.h b/src/global/Env.h index deb9e605b..d0a487322 100644 --- a/src/global/Env.h +++ b/src/global/Env.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -27,7 +27,7 @@ #include #ifndef QT_NO_DEBUG - #include + #include #endif class test_Env; @@ -100,13 +100,13 @@ class Env }; using Wrapper = QSharedPointer; - QVector mInstancesCreator; + QList mInstancesCreator; QMap mInstancesSingleton; mutable QReadWriteLock mLock; #endif QPointer mSingletonHandler; - QVector> mSingletonCreator; + QList> mSingletonCreator; QMap> mSharedInstances; mutable QReadWriteLock mSharedInstancesLock; @@ -376,7 +376,7 @@ class Env auto& holder = getInstance(); const QWriteLocker locker(&holder.mLock); - QMutableVectorIterator iter(holder.mInstancesCreator); + QMutableListIterator iter(holder.mInstancesCreator); while (iter.hasNext()) { iter.next(); diff --git a/src/global/FailureCode.cpp b/src/global/FailureCode.cpp index 168a25351..8780e7120 100644 --- a/src/global/FailureCode.cpp +++ b/src/global/FailureCode.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "FailureCode.h" diff --git a/src/global/FailureCode.h b/src/global/FailureCode.h index 0c376a5bf..f1f62e1ea 100644 --- a/src/global/FailureCode.h +++ b/src/global/FailureCode.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -57,6 +57,7 @@ class FailureCode Prepace_Pace_Smart_Eid_Invalidated, Establish_Pace_Channel_Basic_Reader_No_Pin, Establish_Pace_Channel_Puk_Inoperative, + Establish_Pace_Channel_Unknown_Password_Id, Establish_Pace_Channel_User_Cancelled, Maintain_Card_Connection_Pace_Unrecoverable, Did_Authenticate_Eac1_Card_Command_Failed, @@ -110,6 +111,7 @@ class FailureCode Change_Pin_Unexpected_Transmit_Status, Change_Pin_Card_New_Pin_Mismatch, Change_Pin_Card_User_Cancelled, + Change_Pin_Unrecoverable, Start_Ifd_Service_Failed, Prepare_Pace_Ifd_Unknown, Establish_Pace_Ifd_Unknown, @@ -175,7 +177,9 @@ class FailureCode Http_Status_Code, Certificate_Status, Ssl_Errors, - Paos_Type + Paos_Type, + Ephemeral_Server_Key_Algorithm, + Ephemeral_Server_Key_Length }; Q_ENUM(Info) diff --git a/src/global/FileDestination.h b/src/global/FileDestination.h index e425a3f9a..b4eb16b31 100644 --- a/src/global/FileDestination.h +++ b/src/global/FileDestination.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/global/FuncUtils.h b/src/global/FuncUtils.h index 4048fb6e0..141c44dec 100644 --- a/src/global/FuncUtils.h +++ b/src/global/FuncUtils.h @@ -1,9 +1,9 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Template functions that allow to map and filter over QVectors. + * \brief Template functions that allow to map and filter over QLists. */ #pragma once @@ -11,7 +11,7 @@ #include #include -#include +#include namespace governikus { @@ -39,12 +39,12 @@ std::enable_if_t, QList> map(const std::function([](const Reader& r){ return r.getCard() != nullptr; }, readers) * - * where readers has type QVector + * where readers has type QList */ template -std::enable_if_t, QVector> filter(const std::function& pFunc, const QVector& pItems) +std::enable_if_t, QList> filter(const std::function& pFunc, const QList& pItems) { - QVector result; + QList result; for (const T& item : pItems) { if (pFunc(item)) diff --git a/src/global/GlobalStatus.cpp b/src/global/GlobalStatus.cpp index 624e7d557..eb9453641 100644 --- a/src/global/GlobalStatus.cpp +++ b/src/global/GlobalStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "GlobalStatus.h" @@ -373,7 +373,7 @@ QString GlobalStatus::toErrorDescriptionInternal() const case Code::Card_Puk_Blocked: //: ERROR ALL_PLATFORMS The card declined the PUK since it was entered wrongfully 10 times. - return tr("The entered PUK has already been used ten times and can no longer be used to unblock the PIN."); + return tr("The entered PUK has already been used 10 times and can no longer be used to unblock the PIN."); case Code::Card_NewPin_Mismatch: //: ERROR ALL_PLATFORMS The card reader signalled that the new PIN was not confirmed correctly. @@ -389,7 +389,7 @@ QString GlobalStatus::toErrorDescriptionInternal() const case Code::Card_Smart_Invalid: //: ERROR ALL_PLATFORMS The existing Smart-eID was invalidated. - return tr("The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN three times. You may personalize a new Smart-eID to resolve the issue."); + return tr("The Smart-eID is no longer ready for use. This might have been caused by entering the wrong Smart-eID PIN 3 times. You may personalize a new Smart-eID to resolve the issue."); case Code::RemoteReader_CloseCode_AbnormalClose: //: ERROR ALL_PLATFORMS The connection to the smartphone card reader (SaK) was lost. @@ -413,7 +413,7 @@ QString GlobalStatus::toErrorDescriptionInternal() const case Code::IfdConnector_RemoteHostRefusedConnection: //: ERROR ALL_PLATFORMS The requested connection to the smartphone card reader (SaK) was rejected by the device. - return tr("The smartphone to be paired has rejected the connection. Please check the pairing code. If no pairing code is shown activate the pairing mode."); + return tr("The smartphone to be paired has rejected the connection. Please check the pairing code."); case Code::Downloader_File_Not_Found: //: ERROR ALL_PLATFORMS Download of the file failed with HTTP error code 404. diff --git a/src/global/GlobalStatus.h b/src/global/GlobalStatus.h index 6dbce327e..db76fb6d7 100644 --- a/src/global/GlobalStatus.h +++ b/src/global/GlobalStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -22,6 +22,8 @@ class GlobalStatus { Q_GADGET Q_DECLARE_TR_FUNCTIONS(governikus::GlobalStatus) + Q_CLASSINFO("QML.Element", "auto") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") public: enum class Code diff --git a/src/global/Initializer.h b/src/global/Initializer.h index 0f4193349..5561e517c 100644 --- a/src/global/Initializer.h +++ b/src/global/Initializer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/global/LanguageLoader.cpp b/src/global/LanguageLoader.cpp index 451dafcc5..a1202d41a 100644 --- a/src/global/LanguageLoader.cpp +++ b/src/global/LanguageLoader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "LanguageLoader.h" @@ -27,11 +27,11 @@ LanguageLoader::LanguageLoader() , mTranslatorList() , mComponentList( { - QStringLiteral("ausweisapp2"), QStringLiteral("qtbase") + QStringLiteral("ausweisapp"), QStringLiteral("qtbase") }) , mUsedLocale(mFallbackLanguage) { - QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [] { + QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, QCoreApplication::instance(), [] { // Avoid "this" as lambda capture to get more pointer safety. if (LanguageLoader::getInstance().isLoaded()) { @@ -101,7 +101,7 @@ QList LanguageLoader::getAvailableLocales() const QDir path(mPath); path.setFilter(QDir::Files); - const QRegularExpression regex(QStringLiteral("^ausweisapp2_([a-z]{2}(_[A-Z]{2})?)\\.qm$")); + const QRegularExpression regex(QStringLiteral("^ausweisapp_([a-z]{2}(_[A-Z]{2})?)\\.qm$")); const auto entryList = path.entryInfoList(); for (const auto& info : entryList) { diff --git a/src/global/LanguageLoader.h b/src/global/LanguageLoader.h index 78bf41a21..f6f928cfb 100644 --- a/src/global/LanguageLoader.h +++ b/src/global/LanguageLoader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -8,10 +8,10 @@ #pragma once +#include #include #include #include -#include class test_LanguageLoader; class test_ProviderParser; @@ -31,7 +31,7 @@ class LanguageLoader static QLocale mDefaultLanguage; QString mPath; - QVector> mTranslatorList; + QList> mTranslatorList; const QStringList mComponentList; QLocale mUsedLocale; diff --git a/src/global/LogCategories.cpp b/src/global/LogCategories.cpp index 808509317..3e4c3881b 100644 --- a/src/global/LogCategories.cpp +++ b/src/global/LogCategories.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -15,6 +15,7 @@ Q_LOGGING_CATEGORY(card_pcsc, "card_pcsc") Q_LOGGING_CATEGORY(card_nfc, "card_nfc") Q_LOGGING_CATEGORY(card_remote, "card_remote") Q_LOGGING_CATEGORY(card_smart, "card_smart") +Q_LOGGING_CATEGORY(card_simulator, "card_simulator") Q_LOGGING_CATEGORY(ifd, "ifd") Q_LOGGING_CATEGORY(card_drivers, "card_drivers") Q_LOGGING_CATEGORY(statemachine, "statemachine") diff --git a/src/global/LogHandler.cpp b/src/global/LogHandler.cpp index db3fab0c9..263cf6cf7 100644 --- a/src/global/LogHandler.cpp +++ b/src/global/LogHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "LogHandler.h" @@ -423,7 +423,7 @@ void LogHandler::handleLogWindow(QtMsgType pType, const char* pCategory, const Q } -bool LogHandler::copy(const QString& pDest) +bool LogHandler::copy(const QString& pDest) const { const QMutexLocker mutexLocker(&mMutex); diff --git a/src/global/LogHandler.h b/src/global/LogHandler.h index 265834802..0563c862a 100644 --- a/src/global/LogHandler.h +++ b/src/global/LogHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -98,7 +98,7 @@ class LogHandler bool mAutoRemove; bool mUseLogFile; const QByteArray mFilePrefix; - QMutex mMutex; + mutable QMutex mMutex; inline void copyMessageLogContext(const QMessageLogContext& pSource, QMessageLogContext& pDestination, @@ -138,7 +138,7 @@ class LogHandler [[nodiscard]] const LogEventHandler* getEventHandler() const; void setAutoRemove(bool pRemove); - bool copy(const QString& pDest); + bool copy(const QString& pDest) const; [[nodiscard]] bool copyOther(const QString& pSource, const QString& pDest) const; void resetBacklog(); QByteArray getBacklog(bool pAll = false); diff --git a/src/global/LogPrivacy.cpp b/src/global/LogPrivacy.cpp new file mode 100644 index 000000000..deb39b280 --- /dev/null +++ b/src/global/LogPrivacy.cpp @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "LogPrivacy.h" + +#include + +using namespace governikus; + +Q_DECLARE_LOGGING_CATEGORY(secure) + +QDebug privacy::logApdu(QDebug pDbg, const QByteArray& pApdu) +{ + QDebugStateSaver saver(pDbg); + + constexpr auto START = 5; + constexpr auto END = 2; + if (secure().isDebugEnabled() || pApdu.size() < (START + END)) + { + pDbg << pApdu.toHex(); + } + else + { + pDbg.noquote().nospace() << '"' + << pApdu.first(START).toHex() + << '~' + << pApdu.last(END).toHex() + << "\" (" + << pApdu.size() + << ')'; + } + + return pDbg; +} diff --git a/src/global/LogPrivacy.h b/src/global/LogPrivacy.h new file mode 100644 index 000000000..b1b47b521 --- /dev/null +++ b/src/global/LogPrivacy.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include +#include + +#pragma once + +namespace governikus::privacy +{ +QDebug logApdu(QDebug pDbg, const QByteArray& pApdu); +} // namespace governikus::privacy diff --git a/src/global/Randomizer.cpp b/src/global/Randomizer.cpp index 8952c25c1..e2082750d 100644 --- a/src/global/Randomizer.cpp +++ b/src/global/Randomizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "Randomizer.h" diff --git a/src/global/Randomizer.h b/src/global/Randomizer.h index 038515218..efb0034d3 100644 --- a/src/global/Randomizer.h +++ b/src/global/Randomizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/global/ResourceLoader.cpp b/src/global/ResourceLoader.cpp index d6e87d648..f510bdb42 100644 --- a/src/global/ResourceLoader.cpp +++ b/src/global/ResourceLoader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ResourceLoader.h" @@ -12,6 +12,10 @@ #include #include +#ifndef QT_NO_DEBUG + #include +#endif + using namespace governikus; defineSingleton(ResourceLoader) @@ -44,6 +48,18 @@ void ResourceLoader::init() mLoadedResources << path; } } + +#ifndef QT_NO_DEBUG + const auto& show = qEnvironmentVariable("SHOW_RESOURCES").toLower(); + if (show == QLatin1String("true") || show == QLatin1String("on") || show == QLatin1String("1")) + { + QDirIterator iter(QStringLiteral(":"), QDirIterator::Subdirectories); + while (iter.hasNext()) + { + qDebug() << iter.next(); + } + } +#endif } diff --git a/src/global/ResourceLoader.h b/src/global/ResourceLoader.h index 50fd2c3d2..659074580 100644 --- a/src/global/ResourceLoader.h +++ b/src/global/ResourceLoader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/global/SingletonHelper.h b/src/global/SingletonHelper.h index 86708e626..ed1e57c25 100644 --- a/src/global/SingletonHelper.h +++ b/src/global/SingletonHelper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/global/UsbId.cpp b/src/global/UsbId.cpp index 0374ff079..d82b9521e 100644 --- a/src/global/UsbId.cpp +++ b/src/global/UsbId.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "UsbId.h" diff --git a/src/global/UsbId.h b/src/global/UsbId.h index 45904e1cc..3d56b4ac0 100644 --- a/src/global/UsbId.h +++ b/src/global/UsbId.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/global/VersionInfo.cpp b/src/global/VersionInfo.cpp index 9da3c144c..de3234ff3 100644 --- a/src/global/VersionInfo.cpp +++ b/src/global/VersionInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "VersionInfo.h" @@ -7,8 +7,8 @@ #include #include #include +#include #include -#include using namespace governikus; diff --git a/src/global/VersionInfo.h b/src/global/VersionInfo.h index 93920e2c3..25139d7f7 100644 --- a/src/global/VersionInfo.h +++ b/src/global/VersionInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/global/VersionNumber.cpp b/src/global/VersionNumber.cpp index ab2fa0265..65b257dcf 100644 --- a/src/global/VersionNumber.cpp +++ b/src/global/VersionNumber.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "VersionNumber.h" diff --git a/src/global/VersionNumber.h b/src/global/VersionNumber.h index 4ccd77d8f..8f22f5142 100644 --- a/src/global/VersionNumber.h +++ b/src/global/VersionNumber.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/ConnectRequest.cpp b/src/ifd/base/ConnectRequest.cpp index 4a47ea4fd..82ef8d26a 100644 --- a/src/ifd/base/ConnectRequest.cpp +++ b/src/ifd/base/ConnectRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ConnectRequest.h" @@ -38,8 +38,7 @@ ConnectRequest::ConnectRequest(const IfdDescriptor& pIfdDescriptor, else { auto& remoteServiceSettings = Env::getSingleton()->getRemoteServiceSettings(); - const bool invalidLength = !TlsChecker::hasValidCertificateKeyLength(remoteServiceSettings.getCertificate()); - if (!remoteServiceSettings.checkAndGenerateKey(invalidLength)) + if (!remoteServiceSettings.checkAndGenerateKey(Env::getSingleton()->getIfdCreateSize())) { qCCritical(ifd) << "Cannot get required key/certificate for tls"; return; @@ -90,7 +89,7 @@ void ConnectRequest::setTlsConfiguration() const } config.setPrivateKey(remoteServiceSettings.getKey()); - config.setLocalCertificate(remoteServiceSettings.getCertificate()); + config.setLocalCertificateChain(remoteServiceSettings.getCertificates()); config.setPeerVerifyMode(QSslSocket::VerifyPeer); } @@ -107,18 +106,30 @@ void ConnectRequest::onConnected() bool isRemotePairing = false; bool abortConnection = false; + + const auto& minimalKeySizes = [](QSsl::KeyAlgorithm pKeyAlgorithm){ + return Env::getSingleton()->getMinimumIfdKeySize(pKeyAlgorithm); + }; + if (mIfdDescriptor.isLocalIfd()) { - abortConnection |= !TlsChecker::hasValidEphemeralKeyLength(cfg.ephemeralServerKey()); + abortConnection |= !TlsChecker::hasValidEphemeralKeyLength(cfg.ephemeralServerKey(), minimalKeySizes); } else { - const auto& secureStorage = Env::getSingleton(); + const auto* secureStorage = Env::getSingleton(); const auto& pairingTlsConfig = secureStorage->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK); isRemotePairing = pairingTlsConfig.getCiphers().contains(cfg.sessionCipher()); - abortConnection |= !TlsChecker::hasValidCertificateKeyLength(cfg.peerCertificate()); - abortConnection |= (!isRemotePairing && !TlsChecker::hasValidEphemeralKeyLength(cfg.ephemeralServerKey())); + abortConnection |= !TlsChecker::hasValidCertificateKeyLength(cfg.peerCertificate(), minimalKeySizes); + abortConnection |= (!isRemotePairing && !TlsChecker::hasValidEphemeralKeyLength(cfg.ephemeralServerKey(), minimalKeySizes)); + } + + const auto rootCert = TlsChecker::getRootCertificate(cfg.peerCertificateChain()); + if (rootCert.isNull()) + { + qCCritical(ifd) << "No root certificate found!"; + abortConnection = true; } if (abortConnection) @@ -141,12 +152,12 @@ void ConnectRequest::onConnected() auto& settings = Env::getSingleton()->getRemoteServiceSettings(); if (isRemotePairing) { - qCDebug(ifd) << "Pairing completed | Add certificate:" << cfg.peerCertificate(); - settings.addTrustedCertificate(cfg.peerCertificate()); + qCDebug(ifd) << "Pairing completed | Add certificate:" << rootCert; + settings.addTrustedCertificate(rootCert); } else { - auto info = settings.getRemoteInfo(cfg.peerCertificate()); + auto info = settings.getRemoteInfo(rootCert); info.setLastConnected(QDateTime::currentDateTime()); settings.updateRemoteInfo(info); } @@ -157,7 +168,14 @@ void ConnectRequest::onConnected() void ConnectRequest::onError(QAbstractSocket::SocketError pError) { - qCWarning(ifd) << "Connection error:" << pError; + if (mSocket) + { + qCWarning(ifd) << "Connection error:" << pError << mSocket->errorString(); + } + else + { + qCWarning(ifd) << "Connection error:" << pError; + } mTimer.stop(); if (pError == QAbstractSocket::SocketError::RemoteHostClosedError @@ -201,6 +219,7 @@ void ConnectRequest::onSslErrors(const QList& pErrors) if (pairingCiphers.contains(config.sessionCipher())) { allowedErrors << QSslError::SelfSignedCertificate; + allowedErrors << QSslError::SelfSignedCertificateInChain; } bool ignoreErrors = true; diff --git a/src/ifd/base/ConnectRequest.h b/src/ifd/base/ConnectRequest.h index dbc89c1cf..da9959217 100644 --- a/src/ifd/base/ConnectRequest.h +++ b/src/ifd/base/ConnectRequest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/DataChannel.cpp b/src/ifd/base/DataChannel.cpp index c77afd6b4..a29a19a3c 100644 --- a/src/ifd/base/DataChannel.cpp +++ b/src/ifd/base/DataChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "DataChannel.h" diff --git a/src/ifd/base/DataChannel.h b/src/ifd/base/DataChannel.h index 39c91302d..2d38741bc 100644 --- a/src/ifd/base/DataChannel.h +++ b/src/ifd/base/DataChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/IfdCard.cpp b/src/ifd/base/IfdCard.cpp index 61c23a660..b6fc6df30 100644 --- a/src/ifd/base/IfdCard.cpp +++ b/src/ifd/base/IfdCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdCard.h" @@ -7,6 +7,8 @@ #include "VolatileSettings.h" #include "messages/IfdConnect.h" #include "messages/IfdConnectResponse.h" +#include "messages/IfdDestroyPaceChannel.h" +#include "messages/IfdDestroyPaceChannelResponse.h" #include "messages/IfdDisconnect.h" #include "messages/IfdDisconnectResponse.h" #include "messages/IfdEstablishPaceChannel.h" @@ -52,6 +54,7 @@ bool IfdCard::sendMessage(const QSharedPointer& pMessage, IfdM if (mWaitingForAnswer) { + qCDebug(card_remote) << "Expected answer (" << pExpectedAnswer << ") was not received within" << pTimeout << "ms."; mWaitingForAnswer = false; return false; } @@ -74,7 +77,10 @@ void IfdCard::onMessageReceived(IfdMessageType pMessageTpe, const QJsonObject& p mResponse = pJsonObject; mWaitingForAnswer = false; mWaitCondition.wakeOne(); + return; } + + qCWarning(card_remote) << "Ignoring unexpected message type:" << pMessageTpe; } @@ -124,47 +130,49 @@ IfdCard::~IfdCard() CardReturnCode IfdCard::establishConnection() { const auto& connectMsg = QSharedPointer::create(mReaderName); - if (sendMessage(connectMsg, IfdMessageType::IFDConnectResponse, 5000)) + if (!sendMessage(connectMsg, IfdMessageType::IFDConnectResponse, 5000)) { - const IfdConnectResponse response(mResponse); - if (!response.isIncomplete()) - { - if (!response.resultHasError()) - { - mConnected = true; - mSlotHandle = response.getSlotHandle(); - return CardReturnCode::OK; - } - qCWarning(card_remote) << response.getResultMinor(); - } + return CardReturnCode::INPUT_TIME_OUT; + } + const IfdConnectResponse response(mResponse); + if (response.isIncomplete()) + { + return CardReturnCode::COMMAND_FAILED; + } + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); return CardReturnCode::COMMAND_FAILED; } - return CardReturnCode::INPUT_TIME_OUT; + mConnected = true; + mSlotHandle = response.getSlotHandle(); + return CardReturnCode::OK; } CardReturnCode IfdCard::releaseConnection() { const auto& disconnectCmd = QSharedPointer::create(mSlotHandle); - if (sendMessage(disconnectCmd, IfdMessageType::IFDDisconnectResponse, 5000)) + if (!sendMessage(disconnectCmd, IfdMessageType::IFDDisconnectResponse, 5000)) { - const IfdDisconnectResponse response(mResponse); - if (!response.isIncomplete()) - { - if (!response.resultHasError()) - { - mConnected = false; - return CardReturnCode::OK; - } - qCWarning(card_remote) << response.getResultMinor(); - } + return CardReturnCode::INPUT_TIME_OUT; + } + const IfdDisconnectResponse response(mResponse); + if (response.isIncomplete()) + { + return CardReturnCode::COMMAND_FAILED; + } + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); return CardReturnCode::COMMAND_FAILED; } - return CardReturnCode::INPUT_TIME_OUT; + mConnected = false; + return CardReturnCode::OK; } @@ -180,65 +188,95 @@ void IfdCard::setProgressMessage(const QString& pMessage, int pProgress) } +void IfdCard::setErrorMessage(const QString& pMessage) +{ + mProgressMessage = generateErrorMessage(pMessage); +} + + ResponseApduResult IfdCard::transmit(const CommandApdu& pCommand) { qCDebug(card_remote) << "Transmit command APDU:" << pCommand; const QSharedPointer& transmitCmd = QSharedPointer::create(mSlotHandle, pCommand, mProgressMessage); - if (sendMessage(transmitCmd, IfdMessageType::IFDTransmitResponse, 5000)) + if (!sendMessage(transmitCmd, IfdMessageType::IFDTransmitResponse, 5000)) { - mProgressMessage.clear(); - - const IfdTransmitResponse response(mResponse); - if (!response.isIncomplete()) - { - if (!response.resultHasError()) - { - qCDebug(card_remote) << "Transmit response APDU:" << response.getResponseApdu().toHex(); - return {CardReturnCode::OK, ResponseApdu(response.getResponseApdu())}; - } - qCWarning(card_remote) << response.getResultMinor(); - } + return {CardReturnCode::INPUT_TIME_OUT}; + } + mProgressMessage.clear(); + const IfdTransmitResponse response(mResponse); + if (response.isIncomplete()) + { + return {CardReturnCode::COMMAND_FAILED}; + } + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); return {CardReturnCode::COMMAND_FAILED}; } - return {CardReturnCode::INPUT_TIME_OUT}; + const ResponseApdu responseApdu(response.getResponseApdu()); + qCDebug(card_remote) << "Transmit response APDU:" << responseApdu; + return {CardReturnCode::OK, responseApdu}; } -EstablishPaceChannelOutput IfdCard::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds) +EstablishPaceChannelOutput IfdCard::establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) { EstablishPaceChannel establishPaceChannel(pPasswordId, pChat, pCertificateDescription); - if (Env::getSingleton()->isUsedAsSDK()) { pPreferredPinLength = 0; } const QSharedPointer& message = QSharedPointer::create(mSlotHandle, establishPaceChannel, pPreferredPinLength); - if (sendMessage(message, IfdMessageType::IFDEstablishPACEChannelResponse, pTimeoutSeconds * 1000)) + if (!sendMessage(message, IfdMessageType::IFDEstablishPACEChannelResponse, DEFAULT_PINPAD_TIMEOUT * 1000)) { - const IfdEstablishPaceChannelResponse response(mResponse); - if (!response.isIncomplete()) - { - if (response.getResultMinor() == ECardApiResult::Minor::IFDL_Terminal_NoCard - || response.getResultMinor() == ECardApiResult::Minor::IFDL_InvalidSlotHandle) - { - return EstablishPaceChannelOutput(CardReturnCode::CARD_NOT_FOUND); - } - - if (!response.resultHasError()) - { - return response.getOutputData(); - } - qCWarning(card_remote) << response.getResultMinor(); - } + return EstablishPaceChannelOutput(CardReturnCode::INPUT_TIME_OUT); + } + const IfdEstablishPaceChannelResponse response(mResponse); + if (response.isIncomplete()) + { return EstablishPaceChannelOutput(CardReturnCode::COMMAND_FAILED); } + if (response.getResultMinor() == ECardApiResult::Minor::IFDL_Terminal_NoCard + || response.getResultMinor() == ECardApiResult::Minor::IFDL_InvalidSlotHandle) + { + return EstablishPaceChannelOutput(CardReturnCode::CARD_NOT_FOUND); + } + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); + return EstablishPaceChannelOutput(CardReturnCode::COMMAND_FAILED); + } + + return response.getOutputData(); + +} + + +CardReturnCode IfdCard::destroyPaceChannel() +{ + const auto& destroyCmd = QSharedPointer::create(mSlotHandle); + if (!sendMessage(destroyCmd, IfdMessageType::IFDDestroyPACEChannelResponse, 5000)) + { + return CardReturnCode::INPUT_TIME_OUT; + } - return EstablishPaceChannelOutput(CardReturnCode::INPUT_TIME_OUT); + const IfdDestroyPaceChannelResponse response(mResponse); + if (response.isIncomplete()) + { + return CardReturnCode::COMMAND_FAILED; + } + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); + return CardReturnCode::COMMAND_FAILED; + } + + return CardReturnCode::OK; } @@ -248,26 +286,23 @@ ResponseApduResult IfdCard::setEidPin(quint8 pTimeoutSeconds) const QByteArray inputData = pinModify.createCcid(); const QSharedPointer& message = QSharedPointer::create(mSlotHandle, inputData); - if (sendMessage(message, IfdMessageType::IFDModifyPINResponse, pTimeoutSeconds * 1000)) + if (!sendMessage(message, IfdMessageType::IFDModifyPINResponse, pTimeoutSeconds * 1000)) { - const IfdModifyPinResponse response(mResponse); - if (response.resultHasError()) - { - return {response.getReturnCode()}; - } - - if (!response.isIncomplete()) - { - const PinModifyOutput output(ResponseApdu(response.getOutputData())); - if (!response.resultHasError()) - { - return {CardReturnCode::OK, output.getResponseApdu()}; - } - qCWarning(card_remote) << response.getResultMinor(); - } + return {CardReturnCode::INPUT_TIME_OUT}; + } + const IfdModifyPinResponse response(mResponse); + if (response.isIncomplete()) + { return {CardReturnCode::COMMAND_FAILED}; } - return {CardReturnCode::INPUT_TIME_OUT}; + const PinModifyOutput output(ResponseApdu(response.getOutputData())); + if (response.resultHasError()) + { + qCWarning(card_remote) << response.getResultMinor(); + return {response.getReturnCode(), output.getResponseApdu()}; + } + + return {CardReturnCode::OK, output.getResponseApdu()}; } diff --git a/src/ifd/base/IfdCard.h b/src/ifd/base/IfdCard.h index 8b48e5471..d1f58a7d6 100644 --- a/src/ifd/base/IfdCard.h +++ b/src/ifd/base/IfdCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -57,10 +57,13 @@ class IfdCard CardReturnCode releaseConnection() override; bool isConnected() const override; void setProgressMessage(const QString& pMessage, int pProgress = -1) override; + void setErrorMessage(const QString& pMessage) override; ResponseApduResult transmit(const CommandApdu& pCmd) override; - EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription, quint8 pTimeoutSeconds = 60) override; + EstablishPaceChannelOutput establishPaceChannel(PacePasswordId pPasswordId, int pPreferredPinLength, const QByteArray& pChat, const QByteArray& pCertificateDescription) override; + + CardReturnCode destroyPaceChannel() override; ResponseApduResult setEidPin(quint8 pTimeoutSeconds) override; }; diff --git a/src/ifd/base/IfdClient.cpp b/src/ifd/base/IfdClient.cpp index c655be0b1..de1c1b4f9 100644 --- a/src/ifd/base/IfdClient.cpp +++ b/src/ifd/base/IfdClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdClient.h" @@ -8,15 +8,15 @@ using namespace governikus; -QVector> IfdClient::getAnnouncingRemoteDevices() const +QList> IfdClient::getAnnouncingRemoteDevices() const { - return QVector>(); + return QList>(); } void IfdClient::requestRemoteDevices() { - Q_EMIT fireRemoteDevicesInfo(QVector>()); + Q_EMIT fireRemoteDevicesInfo(QList>()); } diff --git a/src/ifd/base/IfdClient.h b/src/ifd/base/IfdClient.h index 19f4db493..6592dd6d8 100644 --- a/src/ifd/base/IfdClient.h +++ b/src/ifd/base/IfdClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -34,7 +34,8 @@ class IfdClient void fireEstablishConnectionDone(const QSharedPointer& pEntry, const GlobalStatus& pStatus); void fireNewDispatcher(const QSharedPointer& pDispatcher); - void fireRemoteDevicesInfo(const QVector>& pRemoteDevices); + void fireDispatcherChanged(const QSharedPointer& pDispatcher); + void fireRemoteDevicesInfo(const QList>& pRemoteDevices); void fireDispatcherDestroyed(GlobalStatus::Code pCloseCode, const QString& pId); void fireDetectionChanged(); void fireCertificateRemoved(const QString& pDeviceName); @@ -47,13 +48,13 @@ class IfdClient Q_INVOKABLE virtual void stopDetection() = 0; Q_INVOKABLE virtual bool isDetecting() = 0; - Q_INVOKABLE virtual void establishConnection(const QSharedPointer& pEntry, const QString& pPsk) = 0; + Q_INVOKABLE virtual void establishConnection(const QSharedPointer& pEntry, const QByteArray& pPsk) = 0; - [[nodiscard]] virtual QVector> getAnnouncingRemoteDevices() const; + [[nodiscard]] virtual QList> getAnnouncingRemoteDevices() const; [[nodiscard]] bool hasAnnouncingRemoteDevices() const; Q_INVOKABLE virtual void requestRemoteDevices(); [[nodiscard]] virtual QStringList getConnectedDeviceIDs() const; - virtual QVector getConnectedDeviceInfos() = 0; + virtual QList getConnectedDeviceInfos() = 0; }; diff --git a/src/ifd/base/IfdClientImpl.cpp b/src/ifd/base/IfdClientImpl.cpp index 64b2b224e..cb3ad31e0 100644 --- a/src/ifd/base/IfdClientImpl.cpp +++ b/src/ifd/base/IfdClientImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdClientImpl.h" @@ -64,7 +64,7 @@ void IfdClientImpl::shutdownConnectorThread() QSharedPointer IfdClientImpl::mapToAndTakeConnectorPending(const IfdDescriptor& pIfdDescriptor) { - QMutableVectorIterator> i(mIfdConnectorPending); + QMutableListIterator> i(mIfdConnectorPending); while (i.hasNext()) { QSharedPointer entry = i.next(); @@ -135,7 +135,7 @@ void IfdClientImpl::onDispatcherError(const IfdDescriptor& pIfdDescriptor, IfdEr } -void IfdClientImpl::establishConnection(const QSharedPointer& pEntry, const QString& pPsk) +void IfdClientImpl::establishConnection(const QSharedPointer& pEntry, const QByteArray& pPsk) { if (mIfdConnector.isNull()) { diff --git a/src/ifd/base/IfdClientImpl.h b/src/ifd/base/IfdClientImpl.h index 73a854749..441c711bf 100644 --- a/src/ifd/base/IfdClientImpl.h +++ b/src/ifd/base/IfdClientImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -23,7 +23,7 @@ class IfdClientImpl QMap mErrorCounter; QThread mIfdConnectorThread; QPointer mIfdConnector; - QVector> mIfdConnectorPending; + QList> mIfdConnectorPending; QStringList mConnectedDeviceIds; void bootstrapConnectorThread(); @@ -39,7 +39,7 @@ class IfdClientImpl IfdClientImpl(); ~IfdClientImpl() override; - Q_INVOKABLE void establishConnection(const QSharedPointer& pEntry, const QString& pPsk) override; + Q_INVOKABLE void establishConnection(const QSharedPointer& pEntry, const QByteArray& pPsk) override; QStringList getConnectedDeviceIDs() const override; diff --git a/src/ifd/base/IfdConnector.cpp b/src/ifd/base/IfdConnector.cpp index 79b5ec096..2754cde6b 100644 --- a/src/ifd/base/IfdConnector.cpp +++ b/src/ifd/base/IfdConnector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdConnector.h" diff --git a/src/ifd/base/IfdConnector.h b/src/ifd/base/IfdConnector.h index 7ba73e1fc..b66be1cfd 100644 --- a/src/ifd/base/IfdConnector.h +++ b/src/ifd/base/IfdConnector.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -36,7 +36,7 @@ class IfdConnector static GlobalStatus errorToGlobalStatus(IfdErrorCode pErrorCode); public Q_SLOTS: - virtual void onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QString& pPsk) = 0; + virtual void onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QByteArray& pPsk) = 0; Q_SIGNALS: void fireDispatcherCreated(const IfdDescriptor& pIfdDescriptor, const QSharedPointer& pClientDispatcher); diff --git a/src/ifd/base/IfdConnectorImpl.cpp b/src/ifd/base/IfdConnectorImpl.cpp index 03dd7f9eb..eed8b195b 100644 --- a/src/ifd/base/IfdConnectorImpl.cpp +++ b/src/ifd/base/IfdConnectorImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdConnectorImpl.h" @@ -30,7 +30,7 @@ using namespace governikus; void IfdConnectorImpl::removeRequest(const IfdDescriptor& pIfdDescriptor) { - QMutableVectorIterator> requestIterator(mPendingRequests); + QMutableListIterator> requestIterator(mPendingRequests); while (requestIterator.hasNext()) { const QSharedPointer item = requestIterator.next(); @@ -85,7 +85,7 @@ IfdConnectorImpl::IfdConnectorImpl(int pConnectTimeoutMs) } -void IfdConnectorImpl::onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QString& pPsk) +void IfdConnectorImpl::onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QByteArray& pPsk) { if (pIfdDescriptor.isNull() || pIfdDescriptor.getIfdName().isEmpty()) { @@ -99,7 +99,7 @@ void IfdConnectorImpl::onConnectRequest(const IfdDescriptor& pIfdDescriptor, con return; } - const QSharedPointer newRequest(new ConnectRequest(pIfdDescriptor, pPsk.toUtf8(), mConnectTimeoutMs), &QObject::deleteLater); + const QSharedPointer newRequest(new ConnectRequest(pIfdDescriptor, pPsk, mConnectTimeoutMs), &QObject::deleteLater); mPendingRequests += newRequest; connect(newRequest.data(), &ConnectRequest::fireConnectionCreated, this, &IfdConnectorImpl::onConnectionCreated); connect(newRequest.data(), &ConnectRequest::fireConnectionError, this, &IfdConnectorImpl::onConnectionError); diff --git a/src/ifd/base/IfdConnectorImpl.h b/src/ifd/base/IfdConnectorImpl.h index fa1456cd5..f6330b245 100644 --- a/src/ifd/base/IfdConnectorImpl.h +++ b/src/ifd/base/IfdConnectorImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,7 +24,7 @@ class IfdConnectorImpl private: const int mConnectTimeoutMs; - QVector> mPendingRequests; + QList> mPendingRequests; void removeRequest(const IfdDescriptor& pIfdDescriptor); @@ -37,7 +37,7 @@ class IfdConnectorImpl explicit IfdConnectorImpl(int pConnectTimeoutMs = 5000); ~IfdConnectorImpl() override = default; - void onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QString& pPsk) override; + void onConnectRequest(const IfdDescriptor& pIfdDescriptor, const QByteArray& pPsk) override; }; diff --git a/src/ifd/base/IfdDescriptor.cpp b/src/ifd/base/IfdDescriptor.cpp index 9ecc362d1..48249fb79 100644 --- a/src/ifd/base/IfdDescriptor.cpp +++ b/src/ifd/base/IfdDescriptor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdDescriptor.h" @@ -37,7 +37,7 @@ QUrl urlFromMsgAndHost(const Discovery& pDiscovery, IfdDescriptor::IfdDescriptorData::IfdDescriptorData(const QString& pIfdName, const QString& pIfdId, - const QVector& pApiVersions, + const QList& pApiVersions, const bool pIsPairingAnnounced, const QUrl& pRemoteUrl, bool pIsLocalIfd) @@ -81,7 +81,7 @@ IfdDescriptor::IfdDescriptor(const Discovery& pDiscovery, const QHostAddress& pH const QString& ifdName = pDiscovery.getIfdName(); const QString& ifdId = pDiscovery.getIfdId(); - const QVector& supportedApis = pDiscovery.getSupportedApis(); + const QList& supportedApis = pDiscovery.getSupportedApis(); const bool isPairing = pDiscovery.getPairing(); d = new IfdDescriptorData(ifdName, ifdId, supportedApis, isPairing, url, pLocalIfd); } @@ -103,9 +103,9 @@ const QString& IfdDescriptor::getIfdId() const } -const QVector& IfdDescriptor::getApiVersions() const +const QList& IfdDescriptor::getApiVersions() const { - static const QVector EMPTY_VECTOR; + static const QList EMPTY_VECTOR; return d.data() == nullptr ? EMPTY_VECTOR : d->mApiVersions; } diff --git a/src/ifd/base/IfdDescriptor.h b/src/ifd/base/IfdDescriptor.h index 9020c50d1..6cf3a88f5 100644 --- a/src/ifd/base/IfdDescriptor.h +++ b/src/ifd/base/IfdDescriptor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,9 +12,9 @@ #include "messages/Discovery.h" #include +#include #include #include -#include namespace governikus @@ -29,7 +29,7 @@ class IfdDescriptor public: IfdDescriptorData(const QString& pIfdName, const QString& pIfdId, - const QVector& pApiVersions, + const QList& pApiVersions, const bool pIsPairingAnnounced, const QUrl& pUrl, bool pIsLocalIfd); @@ -38,7 +38,7 @@ class IfdDescriptor const QString mIfdName; const QString mIfdId; - const QVector mApiVersions; + const QList mApiVersions; const bool mIsPairingAnnounced; const QUrl mUrl; const bool mIsLocalIfd; @@ -57,7 +57,7 @@ class IfdDescriptor [[nodiscard]] const QString& getIfdName() const; [[nodiscard]] const QString& getIfdId() const; - [[nodiscard]] const QVector& getApiVersions() const; + [[nodiscard]] const QList& getApiVersions() const; [[nodiscard]] bool isSupported() const; [[nodiscard]] bool isPairingAnnounced() const; [[nodiscard]] const QUrl& getUrl() const; diff --git a/src/ifd/base/IfdDispatcher.cpp b/src/ifd/base/IfdDispatcher.cpp index 2b041ceba..123d14bb3 100644 --- a/src/ifd/base/IfdDispatcher.cpp +++ b/src/ifd/base/IfdDispatcher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdDispatcher.h" diff --git a/src/ifd/base/IfdDispatcher.h b/src/ifd/base/IfdDispatcher.h index 40dfda30d..84c7f84d5 100644 --- a/src/ifd/base/IfdDispatcher.h +++ b/src/ifd/base/IfdDispatcher.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/IfdDispatcherClient.cpp b/src/ifd/base/IfdDispatcherClient.cpp index d72f78678..d2ce9cffd 100644 --- a/src/ifd/base/IfdDispatcherClient.cpp +++ b/src/ifd/base/IfdDispatcherClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdDispatcherClient.h" @@ -70,6 +70,6 @@ void IfdDispatcherClient::sendEstablishContext() qCDebug(ifd) << "Try to establish context with version" << ifdVersion; const RemoteServiceSettings& settings = Env::getSingleton()->getRemoteServiceSettings(); - const QSharedPointer& establishContext = QSharedPointer::create(ifdVersion, settings.getServerName()); + const QSharedPointer& establishContext = QSharedPointer::create(ifdVersion, settings.getDeviceName()); send(establishContext); } diff --git a/src/ifd/base/IfdDispatcherClient.h b/src/ifd/base/IfdDispatcherClient.h index d0a1a008e..727e6b18f 100644 --- a/src/ifd/base/IfdDispatcherClient.h +++ b/src/ifd/base/IfdDispatcherClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/IfdDispatcherServer.cpp b/src/ifd/base/IfdDispatcherServer.cpp index 76e25c1b2..bb7b54e8a 100644 --- a/src/ifd/base/IfdDispatcherServer.cpp +++ b/src/ifd/base/IfdDispatcherServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdDispatcherServer.h" @@ -63,7 +63,7 @@ void IfdDispatcherServer::createAndSendContext(const QJsonObject& pMessageObject qCDebug(ifd) << "Got request to establish context with version" << ifdVersion; const auto& settings = Env::getSingleton()->getRemoteServiceSettings(); - const QString& serverName = settings.getServerName(); + const QString& serverName = settings.getDeviceName(); if (fail != ECardApiResult::Minor::null) { qCDebug(ifd) << "Cannot create a new ContextHandle:" << fail; @@ -88,6 +88,7 @@ bool IfdDispatcherServer::processContext(IfdMessageType pMsgType, const QJsonObj IfdEstablishContext establishContext(pMsgObject); saveRemoteNameInSettings(establishContext.getUdName()); + Q_EMIT fireNameChanged(); createAndSendContext(pMsgObject); return true; } diff --git a/src/ifd/base/IfdDispatcherServer.h b/src/ifd/base/IfdDispatcherServer.h index ab3d598af..d6b3c52ec 100644 --- a/src/ifd/base/IfdDispatcherServer.h +++ b/src/ifd/base/IfdDispatcherServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -27,6 +27,7 @@ class IfdDispatcherServer Q_SIGNALS: void fireContextEstablished(); + void fireNameChanged(); }; } // namespace governikus diff --git a/src/ifd/base/IfdList.cpp b/src/ifd/base/IfdList.cpp index 0c54ffcfe..93e7e7801 100644 --- a/src/ifd/base/IfdList.cpp +++ b/src/ifd/base/IfdList.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "Env.h" @@ -27,7 +27,7 @@ template<> IfdList* createNewObject(int&& pCheckInterval, in } // namespace governikus -QVector> IfdList::getIfdList() const +QList> IfdList::getIfdList() const { - return QVector>(); + return QList>(); } diff --git a/src/ifd/base/IfdList.h b/src/ifd/base/IfdList.h index 23e68084e..38d480c0e 100644 --- a/src/ifd/base/IfdList.h +++ b/src/ifd/base/IfdList.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,7 +11,7 @@ #include "IfdDescriptor.h" #include "IfdListEntry.h" -#include +#include namespace governikus @@ -33,7 +33,7 @@ class IfdList virtual void update(const IfdDescriptor& pDescriptor) = 0; virtual void clear() = 0; - [[nodiscard]] virtual QVector> getIfdList() const; + [[nodiscard]] virtual QList> getIfdList() const; }; } // namespace governikus diff --git a/src/ifd/base/IfdListEntry.cpp b/src/ifd/base/IfdListEntry.cpp index e80731b68..4f5217028 100644 --- a/src/ifd/base/IfdListEntry.cpp +++ b/src/ifd/base/IfdListEntry.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdListEntry.h" @@ -13,7 +13,7 @@ using namespace governikus; INIT_FUNCTION([] { qRegisterMetaType>("QSharedPointer"); - qRegisterMetaType>>("QVector>"); + qRegisterMetaType>>("QList>"); }) @@ -42,7 +42,7 @@ bool IfdListEntry::cleanUpSeenTimestamps(int pReaderResponsiveTimeout) const auto visibilityOld = getPercentSeen(); const QTime threshold(QTime::currentTime().addMSecs(-pReaderResponsiveTimeout)); - QMutableVectorIterator i(mLastSeenHistory); + QMutableListIterator i(mLastSeenHistory); while (i.hasNext()) { if (i.next() < threshold) @@ -58,7 +58,7 @@ bool IfdListEntry::cleanUpSeenTimestamps(int pReaderResponsiveTimeout) int IfdListEntry::getPercentSeen(int pCheckInterval, int pTimeFrame) const { - const int count = static_cast(mLastSeenHistory.size()); + const auto count = static_cast(mLastSeenHistory.size()); const int expectedMax = pTimeFrame / pCheckInterval; const int percent = 100 * count / expectedMax; diff --git a/src/ifd/base/IfdListEntry.h b/src/ifd/base/IfdListEntry.h index 330c89fbb..31bf80b8a 100644 --- a/src/ifd/base/IfdListEntry.h +++ b/src/ifd/base/IfdListEntry.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,8 +10,8 @@ #include "IfdDescriptor.h" +#include #include -#include namespace governikus @@ -24,7 +24,7 @@ class IfdListEntry private: IfdDescriptor mIfdDescriptor; QTime mLastSeen; - QVector mLastSeenHistory; + QList mLastSeenHistory; public: explicit IfdListEntry(const IfdDescriptor& pIfdDescriptor); diff --git a/src/ifd/base/IfdListImpl.cpp b/src/ifd/base/IfdListImpl.cpp index 30d466e09..4d2851191 100644 --- a/src/ifd/base/IfdListImpl.cpp +++ b/src/ifd/base/IfdListImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdListImpl.h" @@ -63,7 +63,7 @@ void IfdListImpl::clear() } -QVector> IfdListImpl::getIfdList() const +QList> IfdListImpl::getIfdList() const { return mResponsiveList; } @@ -72,7 +72,7 @@ QVector> IfdListImpl::getIfdList() const void IfdListImpl::onProcessUnresponsiveRemoteReaders() { const QTime threshold(QTime::currentTime().addMSecs(-mReaderResponsiveTimeout)); - QMutableVectorIterator> i(mResponsiveList); + QMutableListIterator i(mResponsiveList); while (i.hasNext()) { const QSharedPointer entry = i.next(); diff --git a/src/ifd/base/IfdListImpl.h b/src/ifd/base/IfdListImpl.h index ca5fc3029..e613afc4e 100644 --- a/src/ifd/base/IfdListImpl.h +++ b/src/ifd/base/IfdListImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,7 +24,7 @@ class IfdListImpl private: QTimer mTimer; const int mReaderResponsiveTimeout; - QVector> mResponsiveList; + QList> mResponsiveList; private Q_SLOTS: void onProcessUnresponsiveRemoteReaders(); @@ -35,7 +35,7 @@ class IfdListImpl void update(const IfdDescriptor& pDescriptor) override; void clear() override; - [[nodiscard]] QVector> getIfdList() const override; + [[nodiscard]] QList> getIfdList() const override; }; } // namespace governikus diff --git a/src/ifd/base/IfdReader.cpp b/src/ifd/base/IfdReader.cpp index c8f6d8923..f20786e50 100644 --- a/src/ifd/base/IfdReader.cpp +++ b/src/ifd/base/IfdReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdReader.h" @@ -13,8 +13,8 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_remote) -IfdReader::IfdReader(ReaderManagerPlugInType pPlugInType, const QString& pReaderName, const QSharedPointer& pDispatcher, const IfdStatus& pIfdStatus) - : Reader(pPlugInType, pReaderName) +IfdReader::IfdReader(ReaderManagerPluginType pPluginType, const QString& pReaderName, const QSharedPointer& pDispatcher, const IfdStatus& pIfdStatus) + : Reader(pPluginType, pReaderName) , mCard(nullptr) , mDispatcher(pDispatcher) { @@ -65,7 +65,7 @@ void IfdReader::updateStatus(const IfdStatus& pIfdStatus) if (cardInserted) { - qCDebug(card_remote) << "Card removed"; + qCInfo(card_remote) << "Card removed"; Q_EMIT fireCardRemoved(getReaderInfo()); } else @@ -82,7 +82,7 @@ void IfdReader::updateStatus(const IfdStatus& pIfdStatus) mCard.reset(new IfdCard(mDispatcher, getName())); fetchCardInfo(); - qCDebug(card_remote) << "Card inserted"; + qCInfo(card_remote) << "Card inserted:" << getReaderInfo().getCardInfo(); Q_EMIT fireCardInserted(getReaderInfo()); } } diff --git a/src/ifd/base/IfdReader.h b/src/ifd/base/IfdReader.h index da826a2a9..60ba12578 100644 --- a/src/ifd/base/IfdReader.h +++ b/src/ifd/base/IfdReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -30,7 +30,7 @@ class IfdReader const QSharedPointer mDispatcher; public: - IfdReader(ReaderManagerPlugInType pPlugInType, const QString& pReaderName, const QSharedPointer& pDispatcher, const IfdStatus& pIfdStatus); + IfdReader(ReaderManagerPluginType pPluginType, const QString& pReaderName, const QSharedPointer& pDispatcher, const IfdStatus& pIfdStatus); ~IfdReader() override; [[nodiscard]] Card* getCard() const override; diff --git a/src/ifd/base/IfdReaderManagerPlugIn.cpp b/src/ifd/base/IfdReaderManagerPlugin.cpp similarity index 61% rename from src/ifd/base/IfdReaderManagerPlugIn.cpp rename to src/ifd/base/IfdReaderManagerPlugin.cpp index c886d8b72..873922eab 100644 --- a/src/ifd/base/IfdReaderManagerPlugIn.cpp +++ b/src/ifd/base/IfdReaderManagerPlugin.cpp @@ -1,13 +1,13 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ -#include "IfdReaderManagerPlugIn.h" +#include "IfdReaderManagerPlugin.h" +#include "AppSettings.h" #include "IfdReader.h" #include "messages/IfdError.h" #include "messages/IfdGetStatus.h" -#include "messages/IfdStatus.h" #include @@ -16,7 +16,7 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_remote) -void IfdReaderManagerPlugIn::removeDispatcher(const QString& pId) +void IfdReaderManagerPlugin::removeDispatcher(const QString& pId) { const auto& remoteReader = mReadersForDispatcher.values(pId); for (const auto& readerName : remoteReader) @@ -38,15 +38,15 @@ void IfdReaderManagerPlugIn::removeDispatcher(const QString& pId) } const auto* dispatcher = mDispatcherList.value(pId).data(); - disconnect(dispatcher, &IfdDispatcherClient::fireContextEstablished, this, &IfdReaderManagerPlugIn::onContextEstablished); - disconnect(dispatcher, &IfdDispatcher::fireReceived, this, &IfdReaderManagerPlugIn::onMessage); - disconnect(dispatcher, &IfdDispatcher::fireClosed, this, &IfdReaderManagerPlugIn::onDispatcherClosed); + disconnect(dispatcher, &IfdDispatcherClient::fireContextEstablished, this, &IfdReaderManagerPlugin::onContextEstablished); + disconnect(dispatcher, &IfdDispatcher::fireReceived, this, &IfdReaderManagerPlugin::onMessage); + disconnect(dispatcher, &IfdDispatcher::fireClosed, this, &IfdReaderManagerPlugin::onDispatcherClosed); mDispatcherList.remove(pId); } -void IfdReaderManagerPlugIn::removeAllDispatchers() +void IfdReaderManagerPlugin::removeAllDispatchers() { for (const auto& dispatcher : std::as_const(mDispatcherList)) { @@ -55,7 +55,48 @@ void IfdReaderManagerPlugIn::removeAllDispatchers() } -void IfdReaderManagerPlugIn::handleIFDStatus(const QJsonObject& pJsonObject, const QString& pId) +void IfdReaderManagerPlugin::processConnectedReader(const QString& pReaderName, const IfdStatus& pIfdStatus, const QSharedPointer& pDispatcher, const QString& pId) +{ + bool newReader = false; + if (mReaderList.contains(pReaderName)) + { + if (auto* reader = mReaderList.value(pReaderName); reader) + { + qCDebug(card_remote) << "Update reader" << pReaderName; + static_cast(reader)->updateStatus(pIfdStatus); + return; + } + qCDebug(card_remote) << "Enable reader" << pReaderName; + } + else + { + qCDebug(card_remote) << "Add reader" << pReaderName; + newReader = true; + } + + auto* reader = new IfdReader(getInfo().getPluginType(), pReaderName, pDispatcher, pIfdStatus); + connect(reader, &IfdReader::fireCardInserted, this, &IfdReaderManagerPlugin::fireCardInserted); + connect(reader, &IfdReader::fireCardRemoved, this, &IfdReaderManagerPlugin::fireCardRemoved); + connect(reader, &IfdReader::fireCardInfoChanged, this, &IfdReaderManagerPlugin::fireCardInfoChanged); + connect(reader, &IfdReader::fireReaderPropertiesUpdated, this, &IfdReaderManagerPlugin::fireReaderPropertiesUpdated); + + mReaderList.insert(pReaderName, reader); + if (newReader) + { + mReadersForDispatcher.insert(pId, pReaderName); + Q_EMIT fireReaderAdded(reader->getReaderInfo()); + } + else + { + Q_EMIT fireReaderPropertiesUpdated(reader->getReaderInfo()); + } + + // Also update card + reader->updateStatus(pIfdStatus); +} + + +void IfdReaderManagerPlugin::handleIFDStatus(const QJsonObject& pJsonObject, const QString& pId) { const auto it = mDispatcherList.constFind(pId); if (it == mDispatcherList.constEnd()) @@ -70,43 +111,7 @@ void IfdReaderManagerPlugIn::handleIFDStatus(const QJsonObject& pJsonObject, con if (ifdStatus.getConnectedReader()) { - bool newReader = false; - if (mReaderList.contains(readerName)) - { - if (auto* reader = mReaderList.value(readerName); reader) - { - qCDebug(card_remote) << "Update reader" << readerName; - static_cast(reader)->updateStatus(ifdStatus); - return; - } - qCDebug(card_remote) << "Enable reader" << readerName; - } - else - { - qCDebug(card_remote) << "Add reader" << readerName; - newReader = true; - } - - auto reader = new IfdReader(getInfo().getPlugInType(), readerName, dispatcher, ifdStatus); - connect(reader, &IfdReader::fireCardInserted, this, &IfdReaderManagerPlugIn::fireCardInserted); - connect(reader, &IfdReader::fireCardRemoved, this, &IfdReaderManagerPlugIn::fireCardRemoved); - connect(reader, &IfdReader::fireCardInfoChanged, this, &IfdReaderManagerPlugIn::fireCardInfoChanged); - connect(reader, &IfdReader::fireReaderPropertiesUpdated, this, &IfdReaderManagerPlugIn::fireReaderPropertiesUpdated); - - mReaderList.insert(readerName, reader); - if (newReader) - { - mReadersForDispatcher.insert(pId, readerName); - Q_EMIT fireReaderAdded(reader->getReaderInfo()); - } - else - { - Q_EMIT fireReaderPropertiesUpdated(reader->getReaderInfo()); - } - - // Also update card - reader->updateStatus(ifdStatus); - + processConnectedReader(readerName, ifdStatus, dispatcher, pId); return; } @@ -131,13 +136,19 @@ void IfdReaderManagerPlugIn::handleIFDStatus(const QJsonObject& pJsonObject, con } -void IfdReaderManagerPlugIn::onContextEstablished(const QString& pIfdName, const QString& pId) const +void IfdReaderManagerPlugin::onContextEstablished(const QString& pIfdName, const QString& pId) const { const auto& dispatcher = mDispatcherList.value(pId); - if (getInfo().getPlugInType() == ReaderManagerPlugInType::REMOTE_IFD) + if (getInfo().getPluginType() == ReaderManagerPluginType::REMOTE_IFD) { + const RemoteServiceSettings& settings = Env::getSingleton()->getRemoteServiceSettings(); + QString savedIfdName = settings.getRemoteInfo(pId).getNameEscaped(); dispatcher->saveRemoteNameInSettings(pIfdName); + if (savedIfdName != RemoteServiceSettings::escapeDeviceName(pIfdName)) + { + Q_EMIT getIfdClient()->fireDispatcherChanged(dispatcher); + } if (dispatcher->isPairingConnection()) { QMetaObject::invokeMethod(dispatcher.data(), &IfdDispatcher::close, Qt::QueuedConnection); @@ -152,7 +163,7 @@ void IfdReaderManagerPlugIn::onContextEstablished(const QString& pIfdName, const } -void IfdReaderManagerPlugIn::onMessage(IfdMessageType pMessageType, const QJsonObject& pJsonObject, const QString& pId) +void IfdReaderManagerPlugin::onMessage(IfdMessageType pMessageType, const QJsonObject& pJsonObject, const QString& pId) { switch (pMessageType) { @@ -163,6 +174,7 @@ void IfdReaderManagerPlugIn::onMessage(IfdMessageType pMessageType, const QJsonO case IfdMessageType::IFDTransmitResponse: case IfdMessageType::IFDDisconnectResponse: case IfdMessageType::IFDEstablishPACEChannelResponse: + case IfdMessageType::IFDDestroyPACEChannelResponse: case IfdMessageType::IFDModifyPINResponse: break; @@ -172,6 +184,7 @@ void IfdReaderManagerPlugIn::onMessage(IfdMessageType pMessageType, const QJsonO case IfdMessageType::IFDDisconnect: case IfdMessageType::IFDTransmit: case IfdMessageType::IFDEstablishPACEChannel: + case IfdMessageType::IFDDestroyPACEChannel: case IfdMessageType::IFDModifyPIN: { qCWarning(card_remote) << "Received an unexpected message of type:" << pMessageType; @@ -190,15 +203,15 @@ void IfdReaderManagerPlugIn::onMessage(IfdMessageType pMessageType, const QJsonO } -void IfdReaderManagerPlugIn::onDispatcherClosed(GlobalStatus::Code pCloseCode, const QString& pId) +void IfdReaderManagerPlugin::onDispatcherClosed(GlobalStatus::Code pCloseCode, const QString& pId) { qCDebug(card_remote) << "IfdDispatcherClient was closed with:" << pCloseCode; removeDispatcher(pId); } -IfdReaderManagerPlugIn::IfdReaderManagerPlugIn(ReaderManagerPlugInType pPlugInType, bool pAvailable, bool pPlugInEnabled) - : ReaderManagerPlugIn(pPlugInType, pAvailable, pPlugInEnabled) +IfdReaderManagerPlugin::IfdReaderManagerPlugin(ReaderManagerPluginType pPluginType, bool pAvailable, bool pPluginEnabled) + : ReaderManagerPlugin(pPluginType, pAvailable, pPluginEnabled) , mReadersForDispatcher() , mDispatcherList() , mReaderList() @@ -206,7 +219,7 @@ IfdReaderManagerPlugIn::IfdReaderManagerPlugIn(ReaderManagerPlugInType pPlugInTy } -IfdReaderManagerPlugIn::~IfdReaderManagerPlugIn() +IfdReaderManagerPlugin::~IfdReaderManagerPlugin() { // can't wait for removeAllDispatchers answer because were are in dtor // and must delete Reader* of mReaderList. @@ -218,16 +231,16 @@ IfdReaderManagerPlugIn::~IfdReaderManagerPlugIn() } -void IfdReaderManagerPlugIn::init() +void IfdReaderManagerPlugin::init() { - ReaderManagerPlugIn::init(); + ReaderManagerPlugin::init(); const auto ifdClient = getIfdClient(); - connect(ifdClient, &IfdClient::fireNewDispatcher, this, &IfdReaderManagerPlugIn::addDispatcher); + connect(ifdClient, &IfdClient::fireNewDispatcher, this, &IfdReaderManagerPlugin::addDispatcher); } -QList IfdReaderManagerPlugIn::getReaders() const +QList IfdReaderManagerPlugin::getReaders() const { auto readerList = mReaderList.values(); readerList.removeAll(nullptr); @@ -235,21 +248,21 @@ QList IfdReaderManagerPlugIn::getReaders() const } -void IfdReaderManagerPlugIn::addDispatcher(const QSharedPointer& pDispatcher) +void IfdReaderManagerPlugin::addDispatcher(const QSharedPointer& pDispatcher) { Q_ASSERT(pDispatcher); mDispatcherList.insert(pDispatcher->getId(), pDispatcher); - connect(pDispatcher.data(), &IfdDispatcherClient::fireContextEstablished, this, &IfdReaderManagerPlugIn::onContextEstablished); - connect(pDispatcher.data(), &IfdDispatcherClient::fireReceived, this, &IfdReaderManagerPlugIn::onMessage); - connect(pDispatcher.data(), &IfdDispatcherClient::fireClosed, this, &IfdReaderManagerPlugIn::onDispatcherClosed); + connect(pDispatcher.data(), &IfdDispatcherClient::fireContextEstablished, this, &IfdReaderManagerPlugin::onContextEstablished); + connect(pDispatcher.data(), &IfdDispatcherClient::fireReceived, this, &IfdReaderManagerPlugin::onMessage); + connect(pDispatcher.data(), &IfdDispatcherClient::fireClosed, this, &IfdReaderManagerPlugin::onDispatcherClosed); QMetaObject::invokeMethod(pDispatcher.data(), &IfdDispatcherClient::sendEstablishContext, Qt::QueuedConnection); } -void IfdReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant& pData) +void IfdReaderManagerPlugin::insert(const QString& pReaderName, const QVariant& pData) { Reader* const reader = mReaderList.value(pReaderName); if (!reader || !reader->getReaderInfo().isInsertable()) @@ -262,24 +275,24 @@ void IfdReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant& } -void IfdReaderManagerPlugIn::startScan(bool pAutoConnect) +void IfdReaderManagerPlugin::startScan(bool pAutoConnect) { const auto ifdClient = getIfdClient(); QMetaObject::invokeMethod(ifdClient, &IfdClient::startDetection, Qt::QueuedConnection); - ReaderManagerPlugIn::startScan(pAutoConnect); + ReaderManagerPlugin::startScan(pAutoConnect); } -void IfdReaderManagerPlugIn::stopScan(const QString& pError) +void IfdReaderManagerPlugin::stopScan(const QString& pError) { const auto ifdClient = getIfdClient(); QMetaObject::invokeMethod(ifdClient, &IfdClient::stopDetection, Qt::QueuedConnection); removeAllDispatchers(); - ReaderManagerPlugIn::stopScan(pError); + ReaderManagerPlugin::stopScan(pError); } -const QMap>& IfdReaderManagerPlugIn::getDispatchers() const +const QMap>& IfdReaderManagerPlugin::getDispatchers() const { return mDispatcherList; } diff --git a/src/ifd/base/IfdReaderManagerPlugIn.h b/src/ifd/base/IfdReaderManagerPlugin.h similarity index 66% rename from src/ifd/base/IfdReaderManagerPlugIn.h rename to src/ifd/base/IfdReaderManagerPlugin.h index bb80aae28..363fbc2ec 100644 --- a/src/ifd/base/IfdReaderManagerPlugIn.h +++ b/src/ifd/base/IfdReaderManagerPlugin.h @@ -1,36 +1,37 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "IfdClient.h" #include "IfdDispatcherClient.h" -#include "ReaderManagerPlugIn.h" -#include "messages/IfdMessage.h" +#include "ReaderManagerPlugin.h" +#include "messages/IfdStatus.h" #include #include -class test_RemoteIfdReaderManagerPlugIn; +class test_RemoteIfdReaderManagerPlugin; namespace governikus { -class IfdReaderManagerPlugIn - : public ReaderManagerPlugIn +class IfdReaderManagerPlugin + : public ReaderManagerPlugin { Q_OBJECT - friend class ::test_RemoteIfdReaderManagerPlugIn; + friend class ::test_RemoteIfdReaderManagerPlugin; private: QMultiMap mReadersForDispatcher; QMap> mDispatcherList; QMap mReaderList; + void processConnectedReader(const QString& pReaderName, const IfdStatus& pIfdStatus, const QSharedPointer& pDispatcher, const QString& pId); void handleIFDStatus(const QJsonObject& pJsonObject, const QString& pId); private Q_SLOTS: @@ -44,11 +45,11 @@ class IfdReaderManagerPlugIn void removeDispatcher(const QString& pId); [[nodiscard]] const QMap>& getDispatchers() const; - virtual IfdClient* getIfdClient() = 0; + virtual IfdClient* getIfdClient() const = 0; public: - IfdReaderManagerPlugIn(ReaderManagerPlugInType pPlugInType, bool pAvailable = false, bool pPlugInEnabled = false); - ~IfdReaderManagerPlugIn() override; + IfdReaderManagerPlugin(ReaderManagerPluginType pPluginType, bool pAvailable = false, bool pPluginEnabled = false); + ~IfdReaderManagerPlugin() override; void init() override; [[nodiscard]] QList getReaders() const override; diff --git a/src/ifd/base/IfdServer.cpp b/src/ifd/base/IfdServer.cpp index 123e6a6f5..33df6e80e 100644 --- a/src/ifd/base/IfdServer.cpp +++ b/src/ifd/base/IfdServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdServer.h" diff --git a/src/ifd/base/IfdServer.h b/src/ifd/base/IfdServer.h index ba3484ab7..3bda89308 100644 --- a/src/ifd/base/IfdServer.h +++ b/src/ifd/base/IfdServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -48,6 +48,7 @@ class IfdServer void fireIsRunningChanged(); void firePairingCompleted(const QSslCertificate& pCertificate); void fireSocketError(QAbstractSocket::SocketError pSocketError); + void fireNameChanged(); }; } // namespace governikus diff --git a/src/ifd/base/ServerMessageHandler.cpp b/src/ifd/base/ServerMessageHandler.cpp index 8c609bf8e..6aeddcaeb 100644 --- a/src/ifd/base/ServerMessageHandler.cpp +++ b/src/ifd/base/ServerMessageHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ServerMessageHandler.h" diff --git a/src/ifd/base/ServerMessageHandler.h b/src/ifd/base/ServerMessageHandler.h index 26b3c701f..6d5634fdf 100644 --- a/src/ifd/base/ServerMessageHandler.h +++ b/src/ifd/base/ServerMessageHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -35,7 +35,7 @@ class ServerMessageHandler virtual void sendEstablishPaceChannelResponse(const QString& pSlotHandle, const EstablishPaceChannelOutput&) = 0; virtual void sendModifyPinResponse(const QString& pSlotHandle, const ResponseApdu& pResponseApdu) = 0; - virtual void setAllowedCardTypes(const QVector& pAllowedCardTypes) = 0; + virtual void setAllowedCardTypes(const QList& pAllowedCardTypes) = 0; Q_SIGNALS: void fireCardConnected(const QSharedPointer& pConnection); @@ -45,6 +45,7 @@ class ServerMessageHandler void fireCardDisconnected(const QSharedPointer& pConnection); void fireClosed(); void fireSecureMessagingStopped(); + void fireNameChanged(); }; } // namespace governikus diff --git a/src/ifd/base/ServerMessageHandlerImpl.cpp b/src/ifd/base/ServerMessageHandlerImpl.cpp index f5a58a368..9cef9a200 100644 --- a/src/ifd/base/ServerMessageHandlerImpl.cpp +++ b/src/ifd/base/ServerMessageHandlerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ServerMessageHandlerImpl.h" @@ -10,6 +10,8 @@ #include "ReaderManager.h" #include "messages/IfdConnect.h" #include "messages/IfdConnectResponse.h" +#include "messages/IfdDestroyPaceChannel.h" +#include "messages/IfdDestroyPaceChannelResponse.h" #include "messages/IfdDisconnect.h" #include "messages/IfdDisconnectResponse.h" #include "messages/IfdError.h" @@ -32,31 +34,32 @@ Q_DECLARE_LOGGING_CATEGORY(ifd) namespace governikus { -template<> ServerMessageHandler* createNewObject&, QVector&> - (QSharedPointer& pChannel, QVector& pAllowedPlugInTypes) +template<> ServerMessageHandler* createNewObject&, QList&> + (QSharedPointer& pChannel, QList& pAllowedPluginTypes) { - return new ServerMessageHandlerImpl(pChannel, pAllowedPlugInTypes); + return new ServerMessageHandlerImpl(pChannel, pAllowedPluginTypes); } ServerMessageHandlerImpl::ServerMessageHandlerImpl(const QSharedPointer& pDataChannel, - const QVector& pAllowedTypes) + const QList& pAllowedTypes) : ServerMessageHandler() , mDispatcher(Env::create(pDataChannel), &QObject::deleteLater) - , mAllowedPlugInTypes(pAllowedTypes) + , mAllowedPluginTypes(pAllowedTypes) , mAllowedCardTypes(pAllowedTypes) , mCardConnections() { connect(mDispatcher.data(), &IfdDispatcherServer::fireReceived, this, &ServerMessageHandlerImpl::onMessage); connect(mDispatcher.data(), &IfdDispatcherServer::fireClosed, this, &ServerMessageHandlerImpl::onClosed); + connect(mDispatcher.data(), &IfdDispatcherServer::fireNameChanged, this, &ServerMessageHandler::fireNameChanged); connect(mDispatcher.data(), &IfdDispatcherServer::fireContextEstablished, this, [this] { - const auto readerManager = Env::getSingleton(); - connect(readerManager, &ReaderManager::fireReaderAdded, this, &ServerMessageHandlerImpl::onReaderChanged, Qt::UniqueConnection); - connect(readerManager, &ReaderManager::fireReaderRemoved, this, &ServerMessageHandlerImpl::onReaderRemoved, Qt::UniqueConnection); - connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &ServerMessageHandlerImpl::onReaderChanged, Qt::UniqueConnection); - connect(readerManager, &ReaderManager::fireCardInserted, this, &ServerMessageHandlerImpl::onReaderChanged, Qt::UniqueConnection); - connect(readerManager, &ReaderManager::fireCardRemoved, this, &ServerMessageHandlerImpl::onReaderChanged, Qt::UniqueConnection); + const auto* readerManager = Env::getSingleton(); + connect(readerManager, &ReaderManager::fireReaderAdded, this, &ServerMessageHandlerImpl::onReaderChanged); + connect(readerManager, &ReaderManager::fireReaderRemoved, this, &ServerMessageHandlerImpl::onReaderRemoved); + connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &ServerMessageHandlerImpl::onReaderChanged); + connect(readerManager, &ReaderManager::fireCardInserted, this, &ServerMessageHandlerImpl::onReaderChanged); + connect(readerManager, &ReaderManager::fireCardRemoved, this, &ServerMessageHandlerImpl::onReaderChanged); }); } @@ -64,7 +67,7 @@ ServerMessageHandlerImpl::ServerMessageHandlerImpl(const QSharedPointer(); + const auto* readerManager = Env::getSingleton(); if (!ifdGetStatus.getSlotName().isEmpty()) { @@ -89,7 +92,7 @@ void ServerMessageHandlerImpl::handleIfdGetStatus(const QJsonObject& pJsonObject continue; } - if (!mAllowedPlugInTypes.contains(readerInfo.getPlugInType())) + if (!mAllowedPluginTypes.contains(readerInfo.getPluginType())) { continue; } @@ -102,7 +105,7 @@ void ServerMessageHandlerImpl::handleIfdGetStatus(const QJsonObject& pJsonObject void ServerMessageHandlerImpl::handleIfdConnect(const QJsonObject& pJsonObject) { const IfdConnect ifdConnect(pJsonObject); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); const auto& info = readerManager->getReaderInfo(ifdConnect.getSlotName()); if (!info.isValid()) @@ -174,6 +177,20 @@ QString ServerMessageHandlerImpl::slotHandleForReaderName(const QString& pReader } +bool ServerMessageHandlerImpl::isAllowed(const QSharedPointer& pCardConnection, QStringView pCommand) const +{ + const bool isBasicReader = pCardConnection->getReaderInfo().isBasicReader(); + const bool pinPadMode = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); + if (isBasicReader && !pinPadMode) + { + qCWarning(ifd) << pCommand << "is only available in pin pad mode."; + return false; + } + + return true; +} + + void ServerMessageHandlerImpl::handleIfdDisconnect(const QJsonObject& pJsonObject) { const IfdDisconnect ifdDisconnect(pJsonObject); @@ -209,7 +226,7 @@ void ServerMessageHandlerImpl::handleIfdTransmit(const QJsonObject& pJsonObject) return; } - const QSharedPointer& cardConnection = mCardConnections.value(slotHandle); + const auto& cardConnection = mCardConnections.value(slotHandle); const QString& progressMessage = ifdTransmit.getDisplayText(); if (!progressMessage.isNull()) @@ -218,7 +235,7 @@ void ServerMessageHandlerImpl::handleIfdTransmit(const QJsonObject& pJsonObject) Q_EMIT fireDisplayTextChanged(progressMessage); } - qCDebug(ifd) << "Transmit card APDU for" << slotHandle; + qCDebug(ifd) << "Transmit APDU for" << slotHandle; InputAPDUInfo inputApduInfo(ifdTransmit.getInputApdu()); cardConnection->callTransmitCommand(this, &ServerMessageHandlerImpl::onTransmitCardCommandDone, {inputApduInfo}, slotHandle); } @@ -237,13 +254,9 @@ void ServerMessageHandlerImpl::handleIfdEstablishPaceChannel(const QJsonObject& return; } - QSharedPointer cardConnection = mCardConnections.value(slotHandle); - - const bool isBasicReader = cardConnection->getReaderInfo().isBasicReader(); - const bool pinPadMode = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); - if (isBasicReader && !pinPadMode) + const auto& cardConnection = mCardConnections.value(slotHandle); + if (!isAllowed(cardConnection, QStringView(u"EstablishPaceChannel"))) { - qCWarning(ifd) << "EstablishPaceChannel is only available in pin pad mode."; const auto& response = QSharedPointer::create(slotHandle, EstablishPaceChannelOutput(), ECardApiResult::Minor::AL_Unknown_Error); mDispatcher->send(response); return; @@ -274,19 +287,37 @@ void ServerMessageHandlerImpl::sendEstablishPaceChannelResponse(const QString& p } -void ServerMessageHandlerImpl::handleIfdModifyPIN(const QJsonObject& pJsonObject) +void ServerMessageHandlerImpl::handleIfdDestroyPaceChannel(const QJsonObject& pJsonObject) { - const auto& ifdModifyPin = QSharedPointer::create(pJsonObject); - const QString slotHandle = ifdModifyPin->getSlotHandle(); - const bool pinPadMode = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); - if (!pinPadMode) + const IfdDestroyPaceChannel ifdDestroy(pJsonObject); + const QString& slotHandle = ifdDestroy.getSlotHandle(); + + if (!mCardConnections.contains(slotHandle)) { - qCWarning(ifd) << "ModifyPin is only available in pin pad mode."; - const auto& response = QSharedPointer::create(slotHandle, QByteArray(), ECardApiResult::Minor::AL_Unknown_Error); + qCWarning(ifd) << "Card is not connected" << slotHandle; + const auto& response = QSharedPointer::create(slotHandle, QByteArray(), ECardApiResult::Minor::IFDL_InvalidSlotHandle); + mDispatcher->send(response); + return; + } + + const auto& cardConnection = mCardConnections.value(slotHandle); + if (!isAllowed(cardConnection, QStringView(u"DestroyPaceChannel"))) + { + const auto& response = QSharedPointer::create(slotHandle, ECardApiResult::Minor::AL_Unknown_Error); mDispatcher->send(response); return; } + qCDebug(ifd) << "Destroy PACE channel for" << slotHandle; + cardConnection->callDestroyPaceChannelCommand(this, &ServerMessageHandlerImpl::onDestroyPaceChannelCommandDone, slotHandle); +} + + +void ServerMessageHandlerImpl::handleIfdModifyPIN(const QJsonObject& pJsonObject) +{ + const auto& ifdModifyPin = QSharedPointer::create(pJsonObject); + const QString slotHandle = ifdModifyPin->getSlotHandle(); + if (!mCardConnections.contains(slotHandle)) { qCWarning(ifd) << "Card is not connected" << slotHandle; @@ -295,7 +326,15 @@ void ServerMessageHandlerImpl::handleIfdModifyPIN(const QJsonObject& pJsonObject return; } - Q_EMIT fireModifyPin(ifdModifyPin, mCardConnections[slotHandle]); + const auto& cardConnection = mCardConnections.value(slotHandle); + if (!isAllowed(cardConnection, QStringView(u"ModifyPin"))) + { + const auto& response = QSharedPointer::create(slotHandle, QByteArray(), ECardApiResult::Minor::AL_Unknown_Error); + mDispatcher->send(response); + return; + } + + Q_EMIT fireModifyPin(ifdModifyPin, cardConnection); } @@ -303,7 +342,7 @@ void ServerMessageHandlerImpl::sendIfdStatus(const ReaderInfo& pReaderInfo) { if (!mDispatcher->getContextHandle().isEmpty()) { - const bool isCardAllowed = mAllowedCardTypes.contains(pReaderInfo.getPlugInType()); + const bool isCardAllowed = mAllowedCardTypes.contains(pReaderInfo.getPluginType()); mDispatcher->send(QSharedPointer::create(pReaderInfo, isCardAllowed)); } } @@ -347,13 +386,13 @@ void ServerMessageHandlerImpl::sendModifyPinResponse(const QString& pSlotHandle, } -void ServerMessageHandlerImpl::setAllowedCardTypes(const QVector& pAllowedCardTypes) +void ServerMessageHandlerImpl::setAllowedCardTypes(const QList& pAllowedCardTypes) { if (mAllowedCardTypes != pAllowedCardTypes) { mAllowedCardTypes = pAllowedCardTypes; - const auto& readerInfos = Env::getSingleton()->getReaderInfos(ReaderFilter(mAllowedPlugInTypes)); + const auto& readerInfos = Env::getSingleton()->getReaderInfos(ReaderFilter(mAllowedPluginTypes)); for (const auto& readerInfo : readerInfos) { sendIfdStatus(readerInfo); @@ -369,7 +408,7 @@ void ServerMessageHandlerImpl::onTransmitCardCommandDone(QSharedPointergetReturnCode() != CardReturnCode::OK) { - qCWarning(ifd) << "Card transmit for" << slotHandle << "failed" << transmitCommand->getReturnCode(); + qCWarning(ifd) << "Transmit for" << slotHandle << "failed" << transmitCommand->getReturnCode(); const auto& response = QSharedPointer::create(slotHandle, QByteArray(), ECardApiResult::Minor::AL_Unknown_Error); mDispatcher->send(response); return; @@ -381,7 +420,7 @@ void ServerMessageHandlerImpl::onTransmitCardCommandDone(QSharedPointergetOutputApduAsHex().first()); } - qCInfo(ifd) << "Card transmit succeeded" << slotHandle; + qCInfo(ifd) << "Transmit for" << slotHandle << "succeeded"; const auto& response = QSharedPointer::create(slotHandle, responseApdu); mDispatcher->send(response); @@ -392,6 +431,30 @@ void ServerMessageHandlerImpl::onTransmitCardCommandDone(QSharedPointer pCommand) +{ + auto destroyPaceChannelCommand = pCommand.staticCast(); + const QString& slotHandle = destroyPaceChannelCommand->getSlotHandle(); + + if (destroyPaceChannelCommand->getReturnCode() != CardReturnCode::OK) + { + qCWarning(ifd) << "DestroyPaceChannel for" << slotHandle << "failed" << destroyPaceChannelCommand->getReturnCode(); + const auto& response = QSharedPointer::create(slotHandle, ECardApiResult::Minor::AL_Unknown_Error); + mDispatcher->send(response); + return; + } + + qCInfo(ifd) << "DestroyPaceChannel for" << slotHandle << "succeeded"; + const auto& response = QSharedPointer::create(slotHandle); + mDispatcher->send(response); + + if (destroyPaceChannelCommand->getSecureMessagingStopped()) + { + Q_EMIT fireSecureMessagingStopped(); + } +} + + void ServerMessageHandlerImpl::onClosed() { mCardConnections.clear(); @@ -415,6 +478,7 @@ void ServerMessageHandlerImpl::onMessage(IfdMessageType pMessageType, const QJso case IfdMessageType::IFDDisconnectResponse: case IfdMessageType::IFDTransmitResponse: case IfdMessageType::IFDEstablishPACEChannelResponse: + case IfdMessageType::IFDDestroyPACEChannelResponse: case IfdMessageType::IFDModifyPINResponse: { qCWarning(ifd) << "Received an unexpected message of type:" << pMessageType; @@ -446,6 +510,10 @@ void ServerMessageHandlerImpl::onMessage(IfdMessageType pMessageType, const QJso handleIfdEstablishPaceChannel(pJsonObject); break; + case IfdMessageType::IFDDestroyPACEChannel: + handleIfdDestroyPaceChannel(pJsonObject); + break; + case IfdMessageType::IFDModifyPIN: handleIfdModifyPIN(pJsonObject); break; @@ -455,7 +523,7 @@ void ServerMessageHandlerImpl::onMessage(IfdMessageType pMessageType, const QJso void ServerMessageHandlerImpl::onReaderChanged(const ReaderInfo& pInfo) { - if (!mAllowedPlugInTypes.contains(pInfo.getPlugInType())) + if (!mAllowedPluginTypes.contains(pInfo.getPluginType())) { return; } @@ -475,7 +543,7 @@ void ServerMessageHandlerImpl::onReaderChanged(const ReaderInfo& pInfo) void ServerMessageHandlerImpl::onReaderRemoved(const ReaderInfo& pInfo) { - if (!mAllowedPlugInTypes.contains(pInfo.getPlugInType())) + if (!mAllowedPluginTypes.contains(pInfo.getPluginType())) { return; } diff --git a/src/ifd/base/ServerMessageHandlerImpl.h b/src/ifd/base/ServerMessageHandlerImpl.h index a229df68f..1e7acbfcf 100644 --- a/src/ifd/base/ServerMessageHandlerImpl.h +++ b/src/ifd/base/ServerMessageHandlerImpl.h @@ -1,9 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Handler for messages on the server side of a smartphone as card reader (SaC) scenario. + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -11,15 +7,15 @@ #include "DataChannel.h" #include "IfdDispatcherServer.h" #include "ReaderInfo.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include "ServerMessageHandler.h" #include "command/BaseCardCommand.h" #include "command/CreateCardConnectionCommand.h" #include "messages/IfdMessage.h" +#include #include #include -#include namespace governikus @@ -32,23 +28,26 @@ class ServerMessageHandlerImpl private: const QSharedPointer mDispatcher; - QVector mAllowedPlugInTypes; - QVector mAllowedCardTypes; + QList mAllowedPluginTypes; + QList mAllowedCardTypes; QMap> mCardConnections; [[nodiscard]] QString slotHandleForReaderName(const QString& pReaderName) const; + [[nodiscard]] bool isAllowed(const QSharedPointer& pCardConnection, QStringView pCommand) const; void handleIfdGetStatus(const QJsonObject& pJsonObject); void handleIfdConnect(const QJsonObject& pJsonObject); void handleIfdDisconnect(const QJsonObject& pJsonObject); void handleIfdTransmit(const QJsonObject& pJsonObject); void handleIfdEstablishPaceChannel(const QJsonObject& pJsonObject); + void handleIfdDestroyPaceChannel(const QJsonObject& pJsonObject); void handleIfdModifyPIN(const QJsonObject& pJsonObject); void sendIfdStatus(const ReaderInfo& pReaderInfo); private Q_SLOTS: void onCreateCardConnectionCommandDone(QSharedPointer pCommand); void onTransmitCardCommandDone(QSharedPointer pCommand); + void onDestroyPaceChannelCommandDone(QSharedPointer pCommand); void onClosed(); void onMessage(IfdMessageType pMessageType, const QJsonObject& pJsonObject); void onReaderChanged(const ReaderInfo& pInfo); @@ -56,11 +55,11 @@ class ServerMessageHandlerImpl public: explicit ServerMessageHandlerImpl(const QSharedPointer& pDataChannel, - const QVector& pAllowedTypes = Enum::getList()); + const QList& pAllowedTypes = Enum::getList()); void sendEstablishPaceChannelResponse(const QString& pSlotHandle, const EstablishPaceChannelOutput& pChannelOutput) override; void sendModifyPinResponse(const QString& pSlotHandle, const ResponseApdu& pResponseApdu) override; - void setAllowedCardTypes(const QVector& pAllowedCardTypes) override; + void setAllowedCardTypes(const QList& pAllowedCardTypes) override; }; diff --git a/src/ifd/base/TlsServer.cpp b/src/ifd/base/TlsServer.cpp index 204f1d968..3b5af532e 100644 --- a/src/ifd/base/TlsServer.cpp +++ b/src/ifd/base/TlsServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "TlsServer.h" diff --git a/src/ifd/base/TlsServer.h b/src/ifd/base/TlsServer.h index a3c830cbc..789e2d379 100644 --- a/src/ifd/base/TlsServer.h +++ b/src/ifd/base/TlsServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/WebSocketChannel.cpp b/src/ifd/base/WebSocketChannel.cpp index 35c209222..39e4a7723 100644 --- a/src/ifd/base/WebSocketChannel.cpp +++ b/src/ifd/base/WebSocketChannel.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WebSocketChannel.h" #include "RemoteServiceSettings.h" #include "SecureStorage.h" +#include "TlsChecker.h" #include #include @@ -26,7 +27,8 @@ QString WebSocketChannel::makeConnectionId(const QSharedPointer& pCo { if (pConnection) { - return RemoteServiceSettings::generateFingerprint(pConnection->sslConfiguration().peerCertificate()); + const auto& selfSignedCert = TlsChecker::getRootCertificate(pConnection->sslConfiguration().peerCertificateChain()); + return RemoteServiceSettings::generateFingerprint(selfSignedCert); } return QString(); diff --git a/src/ifd/base/WebSocketChannel.h b/src/ifd/base/WebSocketChannel.h index 8ae639994..13ecf736f 100644 --- a/src/ifd/base/WebSocketChannel.h +++ b/src/ifd/base/WebSocketChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/base/WebSocketServer.cpp b/src/ifd/base/WebSocketServer.cpp index e16232423..f8955911d 100644 --- a/src/ifd/base/WebSocketServer.cpp +++ b/src/ifd/base/WebSocketServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WebSocketServer.h" diff --git a/src/ifd/base/WebSocketServer.h b/src/ifd/base/WebSocketServer.h index ff733ae0f..6834edcaf 100644 --- a/src/ifd/base/WebSocketServer.h +++ b/src/ifd/base/WebSocketServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -45,6 +45,7 @@ class WebSocketServer void fireMessageHandlerAdded(QSharedPointer pHandler); void firePskChanged(const QByteArray& pPsk); void fireSocketError(QAbstractSocket::SocketError pSocketError); + void fireNameChanged(); }; } // namespace governikus diff --git a/src/ifd/base/WebSocketServerImpl.cpp b/src/ifd/base/WebSocketServerImpl.cpp index d78e42c7f..dc1da4c23 100644 --- a/src/ifd/base/WebSocketServerImpl.cpp +++ b/src/ifd/base/WebSocketServerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WebSocketServerImpl.h" @@ -28,8 +28,9 @@ void WebSocketServerImpl::onWebsocketConnection() } QSharedPointer channel(new WebSocketChannel(connection), &QObject::deleteLater); - mServerMessageHandler.reset(Env::create(channel, mAllowedPlugInTypes)); + mServerMessageHandler.reset(Env::create(channel, mAllowedPluginTypes)); connect(mServerMessageHandler.data(), &ServerMessageHandler::fireClosed, this, &WebSocketServerImpl::onConnectionClosed); + connect(mServerMessageHandler.data(), &ServerMessageHandler::fireNameChanged, this, &WebSocketServer::fireNameChanged); Q_EMIT fireMessageHandlerAdded(mServerMessageHandler); Q_EMIT fireNewConnection(connection); Q_EMIT fireConnectedChanged(isConnected()); @@ -49,12 +50,12 @@ void WebSocketServerImpl::onServerError(QWebSocketProtocol::CloseCode pCloseCode } -WebSocketServerImpl::WebSocketServerImpl(QSharedPointer pTlsServer, const QVector& pAllowedPlugInTypes) +WebSocketServerImpl::WebSocketServerImpl(QSharedPointer pTlsServer, const QList& pAllowedPluginTypes) : WebSocketServer() , mServer(QString(), QWebSocketServer::NonSecureMode) , mTlsServer(pTlsServer) , mServerMessageHandler() - , mAllowedPlugInTypes(pAllowedPlugInTypes) + , mAllowedPluginTypes(pAllowedPluginTypes) { Q_ASSERT(mTlsServer); diff --git a/src/ifd/base/WebSocketServerImpl.h b/src/ifd/base/WebSocketServerImpl.h index 08d2c55a8..a5667605f 100644 --- a/src/ifd/base/WebSocketServerImpl.h +++ b/src/ifd/base/WebSocketServerImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,11 +8,11 @@ #pragma once -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include "TlsServer.h" #include "WebSocketServer.h" -#include +#include #include namespace governikus @@ -27,7 +27,7 @@ class WebSocketServerImpl QWebSocketServer mServer; QSharedPointer mTlsServer; QSharedPointer mServerMessageHandler; - QVector mAllowedPlugInTypes; + QList mAllowedPluginTypes; private Q_SLOTS: void onWebsocketConnection(); @@ -35,7 +35,7 @@ class WebSocketServerImpl void onServerError(QWebSocketProtocol::CloseCode pCloseCode) const; public: - explicit WebSocketServerImpl(QSharedPointer pTlsServer, const QVector& pAllowedPlugInTypes); + explicit WebSocketServerImpl(QSharedPointer pTlsServer, const QList& pAllowedPluginTypes); ~WebSocketServerImpl() override; [[nodiscard]] bool isListening() const override; diff --git a/src/ifd/base/messages/Discovery.cpp b/src/ifd/base/messages/Discovery.cpp index 0b0caefb2..739304ac7 100644 --- a/src/ifd/base/messages/Discovery.cpp +++ b/src/ifd/base/messages/Discovery.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -82,13 +82,16 @@ void Discovery::parseIfdId(const QJsonObject& pMessageObject) if (!ifdCertificate.isNull()) { mIfdId = RemoteServiceSettings::generateFingerprint(ifdCertificate); + return; } + + mIfdId = mIfdId.toLower(); } void Discovery::parsePairing(const QJsonObject& pMessageObject) { - QVector sorted(mSupportedApis); + QList sorted(mSupportedApis); std::sort(sorted.rbegin(), sorted.rend()); if (sorted.isEmpty() || sorted.first() < IfdVersion::Version::v2) @@ -106,9 +109,9 @@ void Discovery::parsePairing(const QJsonObject& pMessageObject) } -Discovery::Discovery(const QString& pIfdName, const QString& pIfdId, quint16 pPort, const QVector& pSupportedApis, bool pPairing) +Discovery::Discovery(const QString& pIfdName, const QString& pIfdId, quint16 pPort, const QList& pSupportedApis, bool pPairing) : IfdMessage(IfdMessageType::UNDEFINED) - , mIfdName(pIfdName) + , mIfdName(pIfdName.toHtmlEscaped()) , mIfdId(pIfdId) , mPort(pPort) , mSupportedApis(pSupportedApis) @@ -131,7 +134,7 @@ Discovery::Discovery(const QJsonObject& pMessageObject) } parseSupportedApi(pMessageObject); - mIfdName = getStringValue(pMessageObject, IFD_NAME()); + mIfdName = getStringValue(pMessageObject, IFD_NAME()).toHtmlEscaped(); parseIfdId(pMessageObject); mPort = static_cast(getIntValue(pMessageObject, PORT(), 0)); parsePairing(pMessageObject); @@ -156,7 +159,7 @@ quint16 Discovery::getPort() const } -const QVector& Discovery::getSupportedApis() const +const QList& Discovery::getSupportedApis() const { return mSupportedApis; } diff --git a/src/ifd/base/messages/Discovery.h b/src/ifd/base/messages/Discovery.h index 51195660c..3c3662806 100644 --- a/src/ifd/base/messages/Discovery.h +++ b/src/ifd/base/messages/Discovery.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -7,7 +7,7 @@ #include "IfdMessage.h" #include "IfdVersion.h" -#include +#include namespace governikus @@ -19,7 +19,7 @@ class Discovery QString mIfdName; QString mIfdId; quint16 mPort; - QVector mSupportedApis; + QList mSupportedApis; bool mPairing; void parseSupportedApi(const QJsonObject& pMessageObject); @@ -27,14 +27,14 @@ class Discovery void parsePairing(const QJsonObject& pMessageObject); public: - Discovery(const QString& pIfdName, const QString& pIfdId, quint16 pPort, const QVector& pSupportedApis, bool pPairing = false); + Discovery(const QString& pIfdName, const QString& pIfdId, quint16 pPort, const QList& pSupportedApis, bool pPairing = false); explicit Discovery(const QJsonObject& pMessageObject); ~Discovery() override = default; [[nodiscard]] const QString& getIfdName() const; [[nodiscard]] const QString& getIfdId() const; [[nodiscard]] quint16 getPort() const; - [[nodiscard]] const QVector& getSupportedApis() const; + [[nodiscard]] const QList& getSupportedApis() const; void setPairing(bool pEnabled); [[nodiscard]] bool getPairing() const; diff --git a/src/ifd/base/messages/IfdConnect.cpp b/src/ifd/base/messages/IfdConnect.cpp index 482d4f99a..961f0c38e 100644 --- a/src/ifd/base/messages/IfdConnect.cpp +++ b/src/ifd/base/messages/IfdConnect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -38,10 +38,7 @@ IfdConnect::IfdConnect(const QJsonObject& pMessageObject) mSlotName = getStringValue(pMessageObject, SLOT_NAME()); mExclusive = getBoolValue(pMessageObject, EXCLUSIVE()); - if (getType() != IfdMessageType::IFDConnect) - { - markIncomplete(QStringLiteral("The value of msg should be IFDConnect")); - } + ensureType(IfdMessageType::IFDConnect); } diff --git a/src/ifd/base/messages/IfdConnect.h b/src/ifd/base/messages/IfdConnect.h index e72e8a2f1..8fd95519a 100644 --- a/src/ifd/base/messages/IfdConnect.h +++ b/src/ifd/base/messages/IfdConnect.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdConnectResponse.cpp b/src/ifd/base/messages/IfdConnectResponse.cpp index 983da1b26..748f4d6e3 100644 --- a/src/ifd/base/messages/IfdConnectResponse.cpp +++ b/src/ifd/base/messages/IfdConnectResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -35,10 +35,7 @@ IfdConnectResponse::IfdConnectResponse(const QJsonObject& pMessageObject) mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); mError = pMessageObject.value(QLatin1String("error")).toString(); - if (getType() != IfdMessageType::IFDConnectResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDConnectResponse")); - } + ensureType(IfdMessageType::IFDConnectResponse); } diff --git a/src/ifd/base/messages/IfdConnectResponse.h b/src/ifd/base/messages/IfdConnectResponse.h index bfb8f636b..2bd05db17 100644 --- a/src/ifd/base/messages/IfdConnectResponse.h +++ b/src/ifd/base/messages/IfdConnectResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdDestroyPaceChannel.cpp b/src/ifd/base/messages/IfdDestroyPaceChannel.cpp new file mode 100644 index 000000000..af2093b6f --- /dev/null +++ b/src/ifd/base/messages/IfdDestroyPaceChannel.cpp @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + + +#include "IfdDestroyPaceChannel.h" + +#include +#include + + +Q_DECLARE_LOGGING_CATEGORY(ifd) + + +using namespace governikus; + + +namespace +{ +VALUE_NAME(SLOT_HANDLE, "SlotHandle") +} // namespace + + +IfdDestroyPaceChannel::IfdDestroyPaceChannel(const QString& pSlotHandle) + : IfdMessage(IfdMessageType::IFDDestroyPACEChannel) + , mSlotHandle(pSlotHandle) +{ +} + + +IfdDestroyPaceChannel::IfdDestroyPaceChannel(const QJsonObject& pMessageObject) + : IfdMessage(pMessageObject) + , mSlotHandle() +{ + mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); + + ensureType(IfdMessageType::IFDDestroyPACEChannel); +} + + +const QString& IfdDestroyPaceChannel::getSlotHandle() const +{ + return mSlotHandle; +} + + +QByteArray IfdDestroyPaceChannel::toByteArray(IfdVersion::Version, const QString& pContextHandle) const +{ + QJsonObject result = createMessageBody(pContextHandle); + + result[SLOT_HANDLE()] = mSlotHandle; + + return IfdMessage::toByteArray(result); +} diff --git a/src/ifd/base/messages/IfdDestroyPaceChannel.h b/src/ifd/base/messages/IfdDestroyPaceChannel.h new file mode 100644 index 000000000..de1afb744 --- /dev/null +++ b/src/ifd/base/messages/IfdDestroyPaceChannel.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "IfdMessage.h" + + +namespace governikus +{ +class IfdDestroyPaceChannel + : public IfdMessage +{ + private: + QString mSlotHandle; + + public: + explicit IfdDestroyPaceChannel(const QString& pSlotHandle); + explicit IfdDestroyPaceChannel(const QJsonObject& pMessageObject); + ~IfdDestroyPaceChannel() override = default; + + [[nodiscard]] const QString& getSlotHandle() const; + [[nodiscard]] QByteArray toByteArray(IfdVersion::Version pIfdVersion, const QString& pContextHandle) const override; +}; + + +} // namespace governikus diff --git a/src/ifd/base/messages/IfdDestroyPaceChannelResponse.cpp b/src/ifd/base/messages/IfdDestroyPaceChannelResponse.cpp new file mode 100644 index 000000000..8f6a52523 --- /dev/null +++ b/src/ifd/base/messages/IfdDestroyPaceChannelResponse.cpp @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + + +#include "IfdDestroyPaceChannelResponse.h" + +#include +#include + + +Q_DECLARE_LOGGING_CATEGORY(ifd) + + +using namespace governikus; + + +namespace +{ +VALUE_NAME(SLOT_HANDLE, "SlotHandle") +} // namespace + + +IfdDestroyPaceChannelResponse::IfdDestroyPaceChannelResponse(const QString& pSlotHandle, ECardApiResult::Minor pResultMinor) + : IfdMessageResponse(IfdMessageType::IFDDestroyPACEChannelResponse, pResultMinor) + , mSlotHandle(pSlotHandle) +{ +} + + +IfdDestroyPaceChannelResponse::IfdDestroyPaceChannelResponse(const QJsonObject& pMessageObject) + : IfdMessageResponse(pMessageObject) + , mSlotHandle() +{ + mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); + + ensureType(IfdMessageType::IFDDestroyPACEChannelResponse); +} + + +const QString& IfdDestroyPaceChannelResponse::getSlotHandle() const +{ + return mSlotHandle; +} + + +QByteArray IfdDestroyPaceChannelResponse::toByteArray(IfdVersion::Version, const QString& pContextHandle) const +{ + QJsonObject result = createMessageBody(pContextHandle); + + result[SLOT_HANDLE()] = mSlotHandle; + + return IfdMessage::toByteArray(result); +} diff --git a/src/ifd/base/messages/IfdDestroyPaceChannelResponse.h b/src/ifd/base/messages/IfdDestroyPaceChannelResponse.h new file mode 100644 index 000000000..be028d139 --- /dev/null +++ b/src/ifd/base/messages/IfdDestroyPaceChannelResponse.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "IfdMessageResponse.h" + + +namespace governikus +{ +class IfdDestroyPaceChannelResponse + : public IfdMessageResponse +{ + private: + QString mSlotHandle; + + public: + explicit IfdDestroyPaceChannelResponse(const QString& pSlotHandle, ECardApiResult::Minor pResultMinor = ECardApiResult::Minor::null); + explicit IfdDestroyPaceChannelResponse(const QJsonObject& pMessageObject); + ~IfdDestroyPaceChannelResponse() override = default; + + [[nodiscard]] const QString& getSlotHandle() const; + [[nodiscard]] QByteArray toByteArray(IfdVersion::Version pIfdVersion, const QString& pContextHandle) const override; +}; + + +} // namespace governikus diff --git a/src/ifd/base/messages/IfdDisconnect.cpp b/src/ifd/base/messages/IfdDisconnect.cpp index 97f052fdd..f9d549d37 100644 --- a/src/ifd/base/messages/IfdDisconnect.cpp +++ b/src/ifd/base/messages/IfdDisconnect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -34,10 +34,7 @@ IfdDisconnect::IfdDisconnect(const QJsonObject& pMessageObject) { mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); - if (getType() != IfdMessageType::IFDDisconnect) - { - markIncomplete(QStringLiteral("The value of msg should be IFDDisconnect")); - } + ensureType(IfdMessageType::IFDDisconnect); } diff --git a/src/ifd/base/messages/IfdDisconnect.h b/src/ifd/base/messages/IfdDisconnect.h index fb1f26057..642707e6f 100644 --- a/src/ifd/base/messages/IfdDisconnect.h +++ b/src/ifd/base/messages/IfdDisconnect.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdDisconnectResponse.cpp b/src/ifd/base/messages/IfdDisconnectResponse.cpp index 1bd4c259e..88b28ee1c 100644 --- a/src/ifd/base/messages/IfdDisconnectResponse.cpp +++ b/src/ifd/base/messages/IfdDisconnectResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -34,10 +34,7 @@ IfdDisconnectResponse::IfdDisconnectResponse(const QJsonObject& pMessageObject) { mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); - if (getType() != IfdMessageType::IFDDisconnectResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDDisconnectResponse")); - } + ensureType(IfdMessageType::IFDDisconnectResponse); } diff --git a/src/ifd/base/messages/IfdDisconnectResponse.h b/src/ifd/base/messages/IfdDisconnectResponse.h index 20d2fb5c4..372829b2d 100644 --- a/src/ifd/base/messages/IfdDisconnectResponse.h +++ b/src/ifd/base/messages/IfdDisconnectResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdError.cpp b/src/ifd/base/messages/IfdError.cpp index 2d2acd713..b5a95e2e1 100644 --- a/src/ifd/base/messages/IfdError.cpp +++ b/src/ifd/base/messages/IfdError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -34,10 +34,7 @@ IfdError::IfdError(const QJsonObject& pMessageObject) { mSlotHandle = getStringValue(pMessageObject, SLOT_HANDLE()); - if (getType() != IfdMessageType::IFDError) - { - markIncomplete(QStringLiteral("The value of msg should be IFDError")); - } + ensureType(IfdMessageType::IFDError); } diff --git a/src/ifd/base/messages/IfdError.h b/src/ifd/base/messages/IfdError.h index 7c30fd680..d7b87aff5 100644 --- a/src/ifd/base/messages/IfdError.h +++ b/src/ifd/base/messages/IfdError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdEstablishContext.cpp b/src/ifd/base/messages/IfdEstablishContext.cpp index f73477cc8..fa9e38df6 100644 --- a/src/ifd/base/messages/IfdEstablishContext.cpp +++ b/src/ifd/base/messages/IfdEstablishContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -36,10 +36,7 @@ IfdEstablishContext::IfdEstablishContext(const QJsonObject& pMessageObject) , mProtocol(IfdVersion(mProtocolRaw)) , mUdName(getStringValue(pMessageObject, UD_NAME())) { - if (getType() != IfdMessageType::IFDEstablishContext) - { - markIncomplete(QStringLiteral("The value of msg should be IFDEstablishContext")); - } + ensureType(IfdMessageType::IFDEstablishContext); } diff --git a/src/ifd/base/messages/IfdEstablishContext.h b/src/ifd/base/messages/IfdEstablishContext.h index 523c92943..2840b8e43 100644 --- a/src/ifd/base/messages/IfdEstablishContext.h +++ b/src/ifd/base/messages/IfdEstablishContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdEstablishContextResponse.cpp b/src/ifd/base/messages/IfdEstablishContextResponse.cpp index b28634eb9..8675562a5 100644 --- a/src/ifd/base/messages/IfdEstablishContextResponse.cpp +++ b/src/ifd/base/messages/IfdEstablishContextResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -32,10 +32,7 @@ IfdEstablishContextResponse::IfdEstablishContextResponse(const QJsonObject& pMes { mIfdName = getStringValue(pMessageObject, IFD_NAME()); - if (getType() != IfdMessageType::IFDEstablishContextResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDEstablishContextResponse")); - } + ensureType(IfdMessageType::IFDEstablishContextResponse); } diff --git a/src/ifd/base/messages/IfdEstablishContextResponse.h b/src/ifd/base/messages/IfdEstablishContextResponse.h index 8cc42adae..5daff7a7a 100644 --- a/src/ifd/base/messages/IfdEstablishContextResponse.h +++ b/src/ifd/base/messages/IfdEstablishContextResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdEstablishPaceChannel.cpp b/src/ifd/base/messages/IfdEstablishPaceChannel.cpp index 9a31acc70..66554ecb5 100644 --- a/src/ifd/base/messages/IfdEstablishPaceChannel.cpp +++ b/src/ifd/base/messages/IfdEstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdEstablishPaceChannel.h" @@ -82,10 +82,7 @@ IfdEstablishPaceChannel::IfdEstablishPaceChannel(const QJsonObject& pMessageObje mExpectedPinLength = getIntValue(pMessageObject, EXPECTED_PIN_LENGTH(), 0); } - if (getType() != IfdMessageType::IFDEstablishPACEChannel) - { - markIncomplete(QStringLiteral("The value of msg should be IFDEstablishPACEChannel")); - } + ensureType(IfdMessageType::IFDEstablishPACEChannel); } @@ -122,7 +119,7 @@ QByteArray IfdEstablishPaceChannel::toByteArray(IfdVersion::Version pIfdVersion, } else { - result[INPUT_DATA()] = QString::fromLatin1(mInputData.createCommandDataCcid().toHex()); + result[INPUT_DATA()] = QString::fromLatin1(mInputData.createASN1StructCcid().toHex()); } return IfdMessage::toByteArray(result); diff --git a/src/ifd/base/messages/IfdEstablishPaceChannel.h b/src/ifd/base/messages/IfdEstablishPaceChannel.h index caaa24296..2cb96cf38 100644 --- a/src/ifd/base/messages/IfdEstablishPaceChannel.h +++ b/src/ifd/base/messages/IfdEstablishPaceChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdEstablishPaceChannelResponse.cpp b/src/ifd/base/messages/IfdEstablishPaceChannelResponse.cpp index 60982d874..ebe1e5f0e 100644 --- a/src/ifd/base/messages/IfdEstablishPaceChannelResponse.cpp +++ b/src/ifd/base/messages/IfdEstablishPaceChannelResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdEstablishPaceChannelResponse.h" @@ -76,10 +76,7 @@ IfdEstablishPaceChannelResponse::IfdEstablishPaceChannelResponse(const QJsonObje parseOutputData(pMessageObject); - if (getType() != IfdMessageType::IFDEstablishPACEChannelResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDEstablishPACEChannelResponse")); - } + ensureType(IfdMessageType::IFDEstablishPACEChannelResponse); } diff --git a/src/ifd/base/messages/IfdEstablishPaceChannelResponse.h b/src/ifd/base/messages/IfdEstablishPaceChannelResponse.h index e6214bbe9..8a7650d6d 100644 --- a/src/ifd/base/messages/IfdEstablishPaceChannelResponse.h +++ b/src/ifd/base/messages/IfdEstablishPaceChannelResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdGetStatus.cpp b/src/ifd/base/messages/IfdGetStatus.cpp index 2802d323c..27ba59e23 100644 --- a/src/ifd/base/messages/IfdGetStatus.cpp +++ b/src/ifd/base/messages/IfdGetStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -34,10 +34,7 @@ IfdGetStatus::IfdGetStatus(const QJsonObject& pMessageObject) { mSlotName = getStringValue(pMessageObject, SLOT_NAME()); - if (getType() != IfdMessageType::IFDGetStatus) - { - markIncomplete(QStringLiteral("The value of msg should be IFDGetStatus")); - } + ensureType(IfdMessageType::IFDGetStatus); } diff --git a/src/ifd/base/messages/IfdGetStatus.h b/src/ifd/base/messages/IfdGetStatus.h index b2e1f3fd5..9bc7b1a4f 100644 --- a/src/ifd/base/messages/IfdGetStatus.h +++ b/src/ifd/base/messages/IfdGetStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdMessage.cpp b/src/ifd/base/messages/IfdMessage.cpp index 827d87946..8a2a1a18f 100644 --- a/src/ifd/base/messages/IfdMessage.cpp +++ b/src/ifd/base/messages/IfdMessage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -62,6 +62,15 @@ QByteArray IfdMessage::toByteArray(const QJsonObject& pJsonObject) } +void IfdMessage::ensureType(IfdMessageType pType) +{ + if (mMessageType != pType) + { + markIncomplete(QStringLiteral("The value of msg should be %1").arg(Enum::getName(pType))); + } +} + + void IfdMessage::markIncomplete(const QString& pLogMessage) { Q_ASSERT(!pLogMessage.isEmpty()); diff --git a/src/ifd/base/messages/IfdMessage.h b/src/ifd/base/messages/IfdMessage.h index 97b9de6df..168556b1f 100644 --- a/src/ifd/base/messages/IfdMessage.h +++ b/src/ifd/base/messages/IfdMessage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -34,6 +34,8 @@ defineEnumType(IfdMessageType, IFDTransmitResponse, IFDEstablishPACEChannel, IFDEstablishPACEChannelResponse, + IFDDestroyPACEChannel, + IFDDestroyPACEChannelResponse, IFDModifyPIN, IFDModifyPINResponse, UNDEFINED) @@ -50,6 +52,7 @@ class IfdMessage [[nodiscard]] virtual QJsonObject createMessageBody(const QString& pContextHandle) const; static QByteArray toByteArray(const QJsonObject& pJsonObject); + void ensureType(IfdMessageType pType); void markIncomplete(const QString& pLogMessage); void missingValue(const QLatin1String& pName); void invalidType(const QLatin1String& pName, const QLatin1String& pExpectedType); diff --git a/src/ifd/base/messages/IfdMessageResponse.cpp b/src/ifd/base/messages/IfdMessageResponse.cpp index 0aba5afb5..8ccdab3d2 100644 --- a/src/ifd/base/messages/IfdMessageResponse.cpp +++ b/src/ifd/base/messages/IfdMessageResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ diff --git a/src/ifd/base/messages/IfdMessageResponse.h b/src/ifd/base/messages/IfdMessageResponse.h index f2acd107c..950f150a9 100644 --- a/src/ifd/base/messages/IfdMessageResponse.h +++ b/src/ifd/base/messages/IfdMessageResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdModifyPin.cpp b/src/ifd/base/messages/IfdModifyPin.cpp index a3f870ccb..5cff92507 100644 --- a/src/ifd/base/messages/IfdModifyPin.cpp +++ b/src/ifd/base/messages/IfdModifyPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdModifyPin.h" @@ -39,10 +39,7 @@ IfdModifyPin::IfdModifyPin(const QJsonObject& pMessageObject) const QString& inputData = getStringValue(pMessageObject, INPUT_DATA()); mInputData = QByteArray::fromHex(inputData.toUtf8()); - if (getType() != IfdMessageType::IFDModifyPIN) - { - markIncomplete(QStringLiteral("The value of msg should be IFDModifyPIN")); - } + ensureType(IfdMessageType::IFDModifyPIN); } diff --git a/src/ifd/base/messages/IfdModifyPin.h b/src/ifd/base/messages/IfdModifyPin.h index e111767f3..32c41610e 100644 --- a/src/ifd/base/messages/IfdModifyPin.h +++ b/src/ifd/base/messages/IfdModifyPin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdModifyPinResponse.cpp b/src/ifd/base/messages/IfdModifyPinResponse.cpp index 3133a0835..e905b16c8 100644 --- a/src/ifd/base/messages/IfdModifyPinResponse.cpp +++ b/src/ifd/base/messages/IfdModifyPinResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdModifyPinResponse.h" @@ -39,10 +39,7 @@ IfdModifyPinResponse::IfdModifyPinResponse(const QJsonObject& pMessageObject) const QString& inputData = getStringValue(pMessageObject, OUTPUT_DATA()); mOutputData = QByteArray::fromHex(inputData.toUtf8()); - if (getType() != IfdMessageType::IFDModifyPINResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDModifyPINResponse")); - } + ensureType(IfdMessageType::IFDModifyPINResponse); } diff --git a/src/ifd/base/messages/IfdModifyPinResponse.h b/src/ifd/base/messages/IfdModifyPinResponse.h index a0d2c063a..b6397de98 100644 --- a/src/ifd/base/messages/IfdModifyPinResponse.h +++ b/src/ifd/base/messages/IfdModifyPinResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdStatus.cpp b/src/ifd/base/messages/IfdStatus.cpp index d62679136..6d0f252df 100644 --- a/src/ifd/base/messages/IfdStatus.cpp +++ b/src/ifd/base/messages/IfdStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -95,10 +95,10 @@ IfdStatus::IfdStatus(const ReaderInfo& pReaderInfo, bool pPublishCard) return; } - switch (pReaderInfo.getPlugInType()) + switch (pReaderInfo.getPluginType()) { - case ReaderManagerPlugInType::NFC: - case ReaderManagerPlugInType::SMART: + case ReaderManagerPluginType::NFC: + case ReaderManagerPluginType::SMART: mHasPinPad = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); break; @@ -129,10 +129,7 @@ IfdStatus::IfdStatus(const QJsonObject& pMessageObject) mConnectedReader = getBoolValue(pMessageObject, CONNECTED_READER()); mCardAvailable = getBoolValue(pMessageObject, CARD_AVAILABLE()); - if (getType() != IfdMessageType::IFDStatus) - { - markIncomplete(QStringLiteral("The value of msg should be IFDStatus")); - } + ensureType(IfdMessageType::IFDStatus); } diff --git a/src/ifd/base/messages/IfdStatus.h b/src/ifd/base/messages/IfdStatus.h index 0acdfdc03..830211836 100644 --- a/src/ifd/base/messages/IfdStatus.h +++ b/src/ifd/base/messages/IfdStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -10,7 +10,7 @@ #include -class test_RemoteIfdReaderManagerPlugIn; +class test_RemoteIfdReaderManagerPlugin; namespace governikus @@ -20,7 +20,7 @@ class MockIfdDispatcher; class IfdStatus : public IfdMessage { - friend class ::test_RemoteIfdReaderManagerPlugIn; + friend class ::test_RemoteIfdReaderManagerPlugin; private: QString mSlotName; diff --git a/src/ifd/base/messages/IfdTransmit.cpp b/src/ifd/base/messages/IfdTransmit.cpp index dbc798446..23e03d2ad 100644 --- a/src/ifd/base/messages/IfdTransmit.cpp +++ b/src/ifd/base/messages/IfdTransmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -99,10 +99,7 @@ IfdTransmit::IfdTransmit(const QJsonObject& pMessageObject) mDisplayText = getStringValue(pMessageObject, DISPLAY_TEXT()); } - if (getType() != IfdMessageType::IFDTransmit) - { - markIncomplete(QStringLiteral("The value of msg should be IFDTransmit")); - } + ensureType(IfdMessageType::IFDTransmit); } diff --git a/src/ifd/base/messages/IfdTransmit.h b/src/ifd/base/messages/IfdTransmit.h index eac127d18..d38958796 100644 --- a/src/ifd/base/messages/IfdTransmit.h +++ b/src/ifd/base/messages/IfdTransmit.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdTransmitResponse.cpp b/src/ifd/base/messages/IfdTransmitResponse.cpp index 1c70f0e65..ef6daba0f 100644 --- a/src/ifd/base/messages/IfdTransmitResponse.cpp +++ b/src/ifd/base/messages/IfdTransmitResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -88,10 +88,7 @@ IfdTransmitResponse::IfdTransmitResponse(const QJsonObject& pMessageObject) parseResponseApdu(pMessageObject); - if (getType() != IfdMessageType::IFDTransmitResponse) - { - markIncomplete(QStringLiteral("The value of msg should be IFDTransmitResponse")); - } + ensureType(IfdMessageType::IFDTransmitResponse); } diff --git a/src/ifd/base/messages/IfdTransmitResponse.h b/src/ifd/base/messages/IfdTransmitResponse.h index 28b97ab5d..e16e317fa 100644 --- a/src/ifd/base/messages/IfdTransmitResponse.h +++ b/src/ifd/base/messages/IfdTransmitResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ifd/base/messages/IfdVersion.cpp b/src/ifd/base/messages/IfdVersion.cpp index 6e0541a37..17482f081 100644 --- a/src/ifd/base/messages/IfdVersion.cpp +++ b/src/ifd/base/messages/IfdVersion.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ @@ -67,15 +67,15 @@ QString IfdVersion::toString() const } -QVector IfdVersion::supported() +QList IfdVersion::supported() { - return QVector({Version::v2}); + return QList({Version::v2}); } -IfdVersion::Version IfdVersion::selectLatestSupported(const QVector& pVersions) +IfdVersion::Version IfdVersion::selectLatestSupported(const QList& pVersions) { - QVector sorted(pVersions); + QList sorted(pVersions); std::sort(sorted.rbegin(), sorted.rend()); for (const IfdVersion::Version version : sorted) diff --git a/src/ifd/base/messages/IfdVersion.h b/src/ifd/base/messages/IfdVersion.h index c81f6a7fd..4d8eaf920 100644 --- a/src/ifd/base/messages/IfdVersion.h +++ b/src/ifd/base/messages/IfdVersion.h @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include +#include #include -#include namespace governikus { @@ -39,8 +39,8 @@ class IfdVersion [[nodiscard]] QString toString() const; - static QVector supported(); - static Version selectLatestSupported(const QVector& pVersions); + static QList supported(); + static Version selectLatestSupported(const QList& pVersions); }; diff --git a/src/ifd/local/LocalIfdClient.cpp b/src/ifd/local/LocalIfdClient.cpp index 1dfd73552..b213eca4e 100644 --- a/src/ifd/local/LocalIfdClient.cpp +++ b/src/ifd/local/LocalIfdClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "LocalIfdClient.h" @@ -69,8 +69,8 @@ void LocalIfdClient::startDetection() const auto packageName = QJniObject::fromString(Env::getSingleton()->getLocalIfdPackageName()); handle.callObjectMethod("setPackage", "(Ljava/lang/String;)Landroid/content/Intent;", packageName.object()); - mPsk = Randomizer::getInstance().createUuid().toString(QUuid::Id128); - serviceIntent.putExtra(QStringLiteral("PSK"), mPsk.toUtf8()); + mPsk = Randomizer::getInstance().createUuid().toByteArray(QUuid::Id128); + serviceIntent.putExtra(QStringLiteral("PSK"), mPsk); QJniObject context = QNativeInterface::QAndroidApplication::context(); if (!context.isValid()) @@ -128,13 +128,13 @@ bool LocalIfdClient::isDetecting() } -const QString& LocalIfdClient::getPsk() const +const QByteArray& LocalIfdClient::getPsk() const { return mPsk; } -QVector LocalIfdClient::getConnectedDeviceInfos() +QList LocalIfdClient::getConnectedDeviceInfos() { return {}; } diff --git a/src/ifd/local/LocalIfdClient.h b/src/ifd/local/LocalIfdClient.h index 0980cd126..0cb84f61b 100644 --- a/src/ifd/local/LocalIfdClient.h +++ b/src/ifd/local/LocalIfdClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -22,7 +22,7 @@ class LocalIfdClient friend LocalIfdClient* createNewObject(); private: - QString mPsk; + QByteArray mPsk; QSharedPointer mDevice; #ifdef Q_OS_ANDROID QJniObject mServiceConnection; @@ -35,9 +35,9 @@ class LocalIfdClient void startDetection() override; void stopDetection() override; bool isDetecting() override; - QVector getConnectedDeviceInfos() override; + QList getConnectedDeviceInfos() override; - [[nodiscard]] const QString& getPsk() const; + [[nodiscard]] const QByteArray& getPsk() const; void serviceConnected(); void serviceDisconnected(); diff --git a/src/ifd/local/LocalIfdReaderManagerPlugIn.cpp b/src/ifd/local/LocalIfdReaderManagerPlugin.cpp similarity index 70% rename from src/ifd/local/LocalIfdReaderManagerPlugIn.cpp rename to src/ifd/local/LocalIfdReaderManagerPlugin.cpp index 2d9d16d9c..c60f9171f 100644 --- a/src/ifd/local/LocalIfdReaderManagerPlugIn.cpp +++ b/src/ifd/local/LocalIfdReaderManagerPlugin.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ -#include "LocalIfdReaderManagerPlugIn.h" +#include "LocalIfdReaderManagerPlugin.h" #include "BuildHelper.h" #include "SecureStorage.h" @@ -18,8 +18,8 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(ifd) -LocalIfdReaderManagerPlugIn::LocalIfdReaderManagerPlugIn() - : IfdReaderManagerPlugIn(ReaderManagerPlugInType::LOCAL_IFD) +LocalIfdReaderManagerPlugin::LocalIfdReaderManagerPlugin() + : IfdReaderManagerPlugin(ReaderManagerPluginType::LOCAL_IFD) , mServiceConnected(false) { updateState(); @@ -30,7 +30,7 @@ LocalIfdReaderManagerPlugIn::LocalIfdReaderManagerPlugIn() } -void LocalIfdReaderManagerPlugIn::startScan(bool pAutoConnect) +void LocalIfdReaderManagerPlugin::startScan(bool pAutoConnect) { updateState(); if (!getInfo().isAvailable()) @@ -39,8 +39,8 @@ void LocalIfdReaderManagerPlugIn::startScan(bool pAutoConnect) return; } - const auto ifdClient = LocalIfdReaderManagerPlugIn::getIfdClient(); - connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &LocalIfdReaderManagerPlugIn::connectToReader, Qt::UniqueConnection); + const auto ifdClient = LocalIfdReaderManagerPlugin::getIfdClient(); + connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &LocalIfdReaderManagerPlugin::connectToReader); connect(ifdClient, &LocalIfdClient::fireDeviceAppeared, this, [this] { mServiceConnected = true; setState(LocalIfdState::CONNECTED); @@ -52,11 +52,11 @@ void LocalIfdReaderManagerPlugIn::startScan(bool pAutoConnect) Q_EMIT fireStatusChanged(getInfo()); }); - IfdReaderManagerPlugIn::startScan(pAutoConnect); + IfdReaderManagerPlugin::startScan(pAutoConnect); } -void LocalIfdReaderManagerPlugIn::stopScan(const QString& pError) +void LocalIfdReaderManagerPlugin::stopScan(const QString& pError) { if (!getInfo().isAvailable()) { @@ -66,29 +66,29 @@ void LocalIfdReaderManagerPlugIn::stopScan(const QString& pError) // Make sure to disconnect the signal, so we don't stop the scan again once the service closes the connection for (auto& dispatcher : getDispatchers()) { - disconnect(dispatcher.data(), &IfdDispatcherClient::fireClosed, this, &LocalIfdReaderManagerPlugIn::onLocalIfdConnectionClosed); + disconnect(dispatcher.data(), &IfdDispatcherClient::fireClosed, this, &LocalIfdReaderManagerPlugin::onLocalIfdConnectionClosed); } - const auto ifdClient = LocalIfdReaderManagerPlugIn::getIfdClient(); - disconnect(ifdClient, &IfdClient::fireDeviceAppeared, this, &LocalIfdReaderManagerPlugIn::connectToReader); - IfdReaderManagerPlugIn::stopScan(pError); + const auto ifdClient = LocalIfdReaderManagerPlugin::getIfdClient(); + disconnect(ifdClient, &IfdClient::fireDeviceAppeared, this, &LocalIfdReaderManagerPlugin::connectToReader); + IfdReaderManagerPlugin::stopScan(pError); } -LocalIfdClient* LocalIfdReaderManagerPlugIn::getIfdClient() +LocalIfdClient* LocalIfdReaderManagerPlugin::getIfdClient() const { return Env::getSingleton(); } -void LocalIfdReaderManagerPlugIn::addDispatcher(const QSharedPointer& pDispatcher) +void LocalIfdReaderManagerPlugin::addDispatcher(const QSharedPointer& pDispatcher) { - connect(pDispatcher.data(), &IfdDispatcherClient::fireClosed, this, &LocalIfdReaderManagerPlugIn::onLocalIfdConnectionClosed); - IfdReaderManagerPlugIn::addDispatcher(pDispatcher); + connect(pDispatcher.data(), &IfdDispatcherClient::fireClosed, this, &LocalIfdReaderManagerPlugin::onLocalIfdConnectionClosed); + IfdReaderManagerPlugin::addDispatcher(pDispatcher); } -void LocalIfdReaderManagerPlugIn::onLocalIfdConnectionClosed(GlobalStatus::Code pCloseCode, const QString& pId) +void LocalIfdReaderManagerPlugin::onLocalIfdConnectionClosed(GlobalStatus::Code pCloseCode, const QString& pId) { Q_UNUSED(pId) @@ -97,7 +97,7 @@ void LocalIfdReaderManagerPlugIn::onLocalIfdConnectionClosed(GlobalStatus::Code } -bool LocalIfdReaderManagerPlugIn::isAusweisAppInstalled() +bool LocalIfdReaderManagerPlugin::isAusweisAppInstalled() { if (mServiceConnected) { @@ -105,7 +105,7 @@ bool LocalIfdReaderManagerPlugIn::isAusweisAppInstalled() } #if defined(Q_OS_ANDROID) - const auto& secureStorage = Env::getSingleton(); + const auto* secureStorage = Env::getSingleton(); const auto& aa2PackageName = secureStorage->getLocalIfdPackageName(); const auto& aa2MinVersion = VersionNumber(secureStorage->getLocalIfdMinVersion()); const auto& aa2CertificateHashes = secureStorage->getLocalIfdAllowedCertificateHashes(); @@ -148,23 +148,23 @@ bool LocalIfdReaderManagerPlugIn::isAusweisAppInstalled() } -void LocalIfdReaderManagerPlugIn::setState(LocalIfdState pState) +void LocalIfdReaderManagerPlugin::setState(LocalIfdState pState) { - setPlugInValue(ReaderManagerPlugInInfo::Key::LOCAL_IFD_STATE, getEnumName(pState)); + setPluginValue(ReaderManagerPluginInfo::Key::LOCAL_IFD_STATE, getEnumName(pState)); } -void LocalIfdReaderManagerPlugIn::updateState() +void LocalIfdReaderManagerPlugin::updateState() { const bool ausweisAppInstalled = isAusweisAppInstalled(); if (getInfo().isAvailable() != ausweisAppInstalled) { - setPlugInAvailable(ausweisAppInstalled); + setPluginAvailable(ausweisAppInstalled); } } -void LocalIfdReaderManagerPlugIn::connectToReader(const QSharedPointer pIfdDevice) +void LocalIfdReaderManagerPlugin::connectToReader(const QSharedPointer pIfdDevice) const { const auto ifdClient = getIfdClient(); ifdClient->establishConnection(pIfdDevice, ifdClient->getPsk()); diff --git a/src/ifd/local/LocalIfdReaderManagerPlugIn.h b/src/ifd/local/LocalIfdReaderManagerPlugin.h similarity index 69% rename from src/ifd/local/LocalIfdReaderManagerPlugIn.h rename to src/ifd/local/LocalIfdReaderManagerPlugin.h index 488df359f..37b4877d3 100644 --- a/src/ifd/local/LocalIfdReaderManagerPlugIn.h +++ b/src/ifd/local/LocalIfdReaderManagerPlugin.h @@ -1,11 +1,11 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "EnumHelper.h" -#include "IfdReaderManagerPlugIn.h" +#include "IfdReaderManagerPlugin.h" #include "LocalIfdClient.h" #include @@ -21,21 +21,21 @@ defineEnumType(LocalIfdState , NOT_INSTALLED ) -class LocalIfdReaderManagerPlugIn - : public IfdReaderManagerPlugIn +class LocalIfdReaderManagerPlugin + : public IfdReaderManagerPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) public: - LocalIfdReaderManagerPlugIn(); + LocalIfdReaderManagerPlugin(); void startScan(bool pAutoConnect) override; void stopScan(const QString& pError = QString()) override; protected: - LocalIfdClient* getIfdClient() override; + LocalIfdClient* getIfdClient() const override; void addDispatcher(const QSharedPointer& pDispatcher) override; private Q_SLOTS: @@ -48,7 +48,7 @@ class LocalIfdReaderManagerPlugIn void updateState(); private Q_SLOTS: - void connectToReader(const QSharedPointer pIfdDevice); + void connectToReader(const QSharedPointer pIfdDevice) const; }; } // namespace governikus diff --git a/src/ifd/local/LocalIfdServer.cpp b/src/ifd/local/LocalIfdServer.cpp index 24251484c..d950dd1d3 100644 --- a/src/ifd/local/LocalIfdServer.cpp +++ b/src/ifd/local/LocalIfdServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "LocalIfdServer.h" diff --git a/src/ifd/local/LocalIfdServer.h b/src/ifd/local/LocalIfdServer.h index 082d784bb..d837101bc 100644 --- a/src/ifd/local/LocalIfdServer.h +++ b/src/ifd/local/LocalIfdServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/local/LocalTlsServer.cpp b/src/ifd/local/LocalTlsServer.cpp index ff75b23ea..354897509 100644 --- a/src/ifd/local/LocalTlsServer.cpp +++ b/src/ifd/local/LocalTlsServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "LocalTlsServer.h" @@ -23,7 +23,7 @@ bool LocalTlsServer::startListening(quint16 pPort) return false; } - const QVector localHosts = {QHostAddress::LocalHostIPv6, QHostAddress::LocalHost}; + const QList localHosts = {QHostAddress::LocalHostIPv6, QHostAddress::LocalHost}; for (const auto& localHost : localHosts) { if (listen(localHost, pPort)) diff --git a/src/ifd/local/LocalTlsServer.h b/src/ifd/local/LocalTlsServer.h index b76eddb4d..65d679317 100644 --- a/src/ifd/local/LocalTlsServer.h +++ b/src/ifd/local/LocalTlsServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/local/LocalWebSocketServer.cpp b/src/ifd/local/LocalWebSocketServer.cpp index d8bc0b1b4..6d051fbc9 100644 --- a/src/ifd/local/LocalWebSocketServer.cpp +++ b/src/ifd/local/LocalWebSocketServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "LocalWebSocketServer.h" diff --git a/src/ifd/local/LocalWebSocketServer.h b/src/ifd/local/LocalWebSocketServer.h index 30f03d292..770c623d8 100644 --- a/src/ifd/local/LocalWebSocketServer.h +++ b/src/ifd/local/LocalWebSocketServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/local/LocalWebSocketServerImpl.cpp b/src/ifd/local/LocalWebSocketServerImpl.cpp index 792c43f2d..8a8e779b7 100644 --- a/src/ifd/local/LocalWebSocketServerImpl.cpp +++ b/src/ifd/local/LocalWebSocketServerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "LocalWebSocketServerImpl.h" @@ -26,7 +26,7 @@ template<> LocalWebSocketServer* createNewObject() LocalWebSocketServerImpl::LocalWebSocketServerImpl() : LocalWebSocketServer() , mLocalTlsServer(QSharedPointer::create()) - , mWebSocketServer(mLocalTlsServer, {ReaderManagerPlugInType::SMART, ReaderManagerPlugInType::UNKNOWN}) + , mWebSocketServer(mLocalTlsServer, {ReaderManagerPluginType::SMART, ReaderManagerPluginType::UNKNOWN}) { connect(&mWebSocketServer, &WebSocketServer::fireNewConnection, this, &LocalWebSocketServerImpl::fireNewConnection); connect(&mWebSocketServer, &WebSocketServer::fireConnectedChanged, this, &LocalWebSocketServerImpl::fireConnectedChanged); diff --git a/src/ifd/local/LocalWebSocketServerImpl.h b/src/ifd/local/LocalWebSocketServerImpl.h index 11b5177e0..6a6eb493d 100644 --- a/src/ifd/local/LocalWebSocketServerImpl.h +++ b/src/ifd/local/LocalWebSocketServerImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/local/metadata.json b/src/ifd/local/metadata.json index 1430a313e..995f2c6ad 100644 --- a/src/ifd/local/metadata.json +++ b/src/ifd/local/metadata.json @@ -1,4 +1,4 @@ { - "name" : "LocalIfdReaderManagerPlugIn", + "name" : "LocalIfdReaderManagerPlugin", "dependencies" : [] } \ No newline at end of file diff --git a/src/ifd/remote/RemoteIfdClient.cpp b/src/ifd/remote/RemoteIfdClient.cpp index 8feee8cdd..e7461a790 100644 --- a/src/ifd/remote/RemoteIfdClient.cpp +++ b/src/ifd/remote/RemoteIfdClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteIfdClient.h" @@ -91,7 +91,7 @@ bool RemoteIfdClient::isDetecting() } -QVector> RemoteIfdClient::getAnnouncingRemoteDevices() const +QList> RemoteIfdClient::getAnnouncingRemoteDevices() const { return mIfdList->getIfdList(); } @@ -103,11 +103,11 @@ void RemoteIfdClient::requestRemoteDevices() } -QVector RemoteIfdClient::getConnectedDeviceInfos() +QList RemoteIfdClient::getConnectedDeviceInfos() { const RemoteServiceSettings& settings = Env::getSingleton()->getRemoteServiceSettings(); auto remoteInfos = settings.getRemoteInfos(); - QVector result; + QList result; for (const auto& info : std::as_const(remoteInfos)) { const auto& deviceIDs = getConnectedDeviceIDs(); diff --git a/src/ifd/remote/RemoteIfdClient.h b/src/ifd/remote/RemoteIfdClient.h index 88ab6ea16..95f0a45f1 100644 --- a/src/ifd/remote/RemoteIfdClient.h +++ b/src/ifd/remote/RemoteIfdClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -38,9 +38,9 @@ class RemoteIfdClient Q_INVOKABLE void stopDetection() override; Q_INVOKABLE bool isDetecting() override; - [[nodiscard]] QVector> getAnnouncingRemoteDevices() const override; + [[nodiscard]] QList> getAnnouncingRemoteDevices() const override; Q_INVOKABLE void requestRemoteDevices() override; - QVector getConnectedDeviceInfos() override; + QList getConnectedDeviceInfos() override; }; diff --git a/src/ifd/remote/RemoteIfdReaderManagerPlugIn.h b/src/ifd/remote/RemoteIfdReaderManagerPlugIn.h deleted file mode 100644 index 393f47e84..000000000 --- a/src/ifd/remote/RemoteIfdReaderManagerPlugIn.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Implementation of \ref ReaderManagerPlugIn for smartphone as card reader (SaC). - */ - -#pragma once - -#include "IfdList.h" -#include "IfdReaderManagerPlugIn.h" - -#include -#include - -class test_RemoteIfdReaderManagerPlugIn; - -namespace governikus -{ - -class RemoteIfdReaderManagerPlugIn - : public IfdReaderManagerPlugIn -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) - - friend class ::test_RemoteIfdReaderManagerPlugIn; - - private: - QTimer mScanTimer; - bool mConnectToPairedReaders; - QStringList mConnectionAttempts; - - private Q_SLOTS: - void connectToPairedReaders(); - void continueConnectToPairedReaders(const QVector>& pRemoteDevices); - void onDeviceVanished(const QSharedPointer& pEntry); - void onEstablishConnectionDone(const QSharedPointer& pEntry, const GlobalStatus& pStatus); - - public: - RemoteIfdReaderManagerPlugIn(); - ~RemoteIfdReaderManagerPlugIn() override; - - void startScan(bool pAutoConnect) override; - void stopScan(const QString& pError = QString()) override; - - protected: - IfdClient* getIfdClient() override; - -}; - -} // namespace governikus diff --git a/src/ifd/remote/RemoteIfdReaderManagerPlugIn.cpp b/src/ifd/remote/RemoteIfdReaderManagerPlugin.cpp similarity index 66% rename from src/ifd/remote/RemoteIfdReaderManagerPlugIn.cpp rename to src/ifd/remote/RemoteIfdReaderManagerPlugin.cpp index 5d1867ce6..6a33ff6aa 100644 --- a/src/ifd/remote/RemoteIfdReaderManagerPlugIn.cpp +++ b/src/ifd/remote/RemoteIfdReaderManagerPlugin.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ -#include "RemoteIfdReaderManagerPlugIn.h" +#include "RemoteIfdReaderManagerPlugin.h" #include "AppSettings.h" #include "RemoteIfdClient.h" @@ -15,7 +15,7 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(card_remote) -void RemoteIfdReaderManagerPlugIn::connectToPairedReaders() +void RemoteIfdReaderManagerPlugin::connectToPairedReaders() const { if (!mConnectToPairedReaders) { @@ -23,18 +23,18 @@ void RemoteIfdReaderManagerPlugIn::connectToPairedReaders() } const auto ifdClient = getIfdClient(); - connect(ifdClient, &IfdClient::fireRemoteDevicesInfo, this, &RemoteIfdReaderManagerPlugIn::continueConnectToPairedReaders); - connect(ifdClient, &IfdClient::fireDeviceVanished, this, &RemoteIfdReaderManagerPlugIn::onDeviceVanished); - connect(ifdClient, &IfdClient::fireEstablishConnectionDone, this, &RemoteIfdReaderManagerPlugIn::onEstablishConnectionDone); + connect(ifdClient, &IfdClient::fireRemoteDevicesInfo, this, &RemoteIfdReaderManagerPlugin::continueConnectToPairedReaders); + connect(ifdClient, &IfdClient::fireDeviceVanished, this, &RemoteIfdReaderManagerPlugin::onDeviceVanished); + connect(ifdClient, &IfdClient::fireEstablishConnectionDone, this, &RemoteIfdReaderManagerPlugin::onEstablishConnectionDone); QMetaObject::invokeMethod(ifdClient, &IfdClient::requestRemoteDevices, Qt::QueuedConnection); } -void RemoteIfdReaderManagerPlugIn::continueConnectToPairedReaders(const QVector>& pRemoteDevices) +void RemoteIfdReaderManagerPlugin::continueConnectToPairedReaders(const QList>& pRemoteDevices) { const auto ifdClient = getIfdClient(); - disconnect(ifdClient, &IfdClient::fireRemoteDevicesInfo, this, &RemoteIfdReaderManagerPlugIn::continueConnectToPairedReaders); + disconnect(ifdClient, &IfdClient::fireRemoteDevicesInfo, this, &RemoteIfdReaderManagerPlugin::continueConnectToPairedReaders); const RemoteServiceSettings& remoteServiceSettings = Env::getSingleton()->getRemoteServiceSettings(); for (const QSharedPointer& remoteDevice : pRemoteDevices) @@ -60,14 +60,15 @@ void RemoteIfdReaderManagerPlugIn::continueConnectToPairedReaders(const QVector< { mConnectionAttempts << ifdId; QMetaObject::invokeMethod(ifdClient, [ifdClient, remoteDevice] { - ifdClient->establishConnection(remoteDevice, QString()); + ifdClient->establishConnection(remoteDevice, QByteArray()); }, Qt::QueuedConnection); } } + setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); } -void RemoteIfdReaderManagerPlugIn::onDeviceVanished(const QSharedPointer& pEntry) +void RemoteIfdReaderManagerPlugin::onDeviceVanished(const QSharedPointer& pEntry) { const auto& ifdId = pEntry->getIfdDescriptor().getIfdId(); if (mConnectionAttempts.contains(ifdId)) @@ -78,7 +79,7 @@ void RemoteIfdReaderManagerPlugIn::onDeviceVanished(const QSharedPointer& pEntry, const GlobalStatus& pStatus) +void RemoteIfdReaderManagerPlugin::onEstablishConnectionDone(const QSharedPointer& pEntry, const GlobalStatus& pStatus) { const auto& ifdId = pEntry->getIfdDescriptor().getIfdId(); if (mConnectionAttempts.contains(ifdId)) @@ -89,43 +90,43 @@ void RemoteIfdReaderManagerPlugIn::onEstablishConnectionDone(const QSharedPointe } -RemoteIfdReaderManagerPlugIn::RemoteIfdReaderManagerPlugIn() - : IfdReaderManagerPlugIn(ReaderManagerPlugInType::REMOTE_IFD, true) +RemoteIfdReaderManagerPlugin::RemoteIfdReaderManagerPlugin() + : IfdReaderManagerPlugin(ReaderManagerPluginType::REMOTE_IFD, true) , mScanTimer() , mConnectToPairedReaders(true) , mConnectionAttempts() { mScanTimer.setInterval(1000); - connect(&mScanTimer, &QTimer::timeout, this, &RemoteIfdReaderManagerPlugIn::connectToPairedReaders); + connect(&mScanTimer, &QTimer::timeout, this, &RemoteIfdReaderManagerPlugin::connectToPairedReaders); } -RemoteIfdReaderManagerPlugIn::~RemoteIfdReaderManagerPlugIn() +RemoteIfdReaderManagerPlugin::~RemoteIfdReaderManagerPlugin() { mScanTimer.stop(); } -void RemoteIfdReaderManagerPlugIn::startScan(bool pAutoConnect) +void RemoteIfdReaderManagerPlugin::startScan(bool pAutoConnect) { mConnectToPairedReaders = pAutoConnect; const auto ifdClient = getIfdClient(); - connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteIfdReaderManagerPlugIn::connectToPairedReaders, Qt::UniqueConnection); + connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteIfdReaderManagerPlugin::connectToPairedReaders); mScanTimer.start(); - IfdReaderManagerPlugIn::startScan(pAutoConnect); + IfdReaderManagerPlugin::startScan(pAutoConnect); } -void RemoteIfdReaderManagerPlugIn::stopScan(const QString& pError) +void RemoteIfdReaderManagerPlugin::stopScan(const QString& pError) { const auto ifdClient = getIfdClient(); - disconnect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteIfdReaderManagerPlugIn::connectToPairedReaders); + disconnect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteIfdReaderManagerPlugin::connectToPairedReaders); mScanTimer.stop(); - IfdReaderManagerPlugIn::stopScan(pError); + IfdReaderManagerPlugin::stopScan(pError); } -IfdClient* RemoteIfdReaderManagerPlugIn::getIfdClient() +IfdClient* RemoteIfdReaderManagerPlugin::getIfdClient() const { return Env::getSingleton(); } diff --git a/src/ifd/remote/RemoteIfdReaderManagerPlugin.h b/src/ifd/remote/RemoteIfdReaderManagerPlugin.h new file mode 100644 index 000000000..14d007444 --- /dev/null +++ b/src/ifd/remote/RemoteIfdReaderManagerPlugin.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany + */ + +/*! + * \brief Implementation of \ref ReaderManagerPlugin for smartphone as card reader (SaC). + */ + +#pragma once + +#include "IfdList.h" +#include "IfdReaderManagerPlugin.h" + +#include +#include + +class test_RemoteIfdReaderManagerPlugin; + +namespace governikus +{ + +class RemoteIfdReaderManagerPlugin + : public IfdReaderManagerPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) + + friend class ::test_RemoteIfdReaderManagerPlugin; + + private: + QTimer mScanTimer; + bool mConnectToPairedReaders; + QStringList mConnectionAttempts; + + private Q_SLOTS: + void connectToPairedReaders() const; + void continueConnectToPairedReaders(const QList>& pRemoteDevices); + void onDeviceVanished(const QSharedPointer& pEntry); + void onEstablishConnectionDone(const QSharedPointer& pEntry, const GlobalStatus& pStatus); + + public: + RemoteIfdReaderManagerPlugin(); + ~RemoteIfdReaderManagerPlugin() override; + + void startScan(bool pAutoConnect) override; + void stopScan(const QString& pError = QString()) override; + + protected: + IfdClient* getIfdClient() const override; + +}; + +} // namespace governikus diff --git a/src/ifd/remote/RemoteIfdServer.cpp b/src/ifd/remote/RemoteIfdServer.cpp index 3abed53d8..e00af4de4 100644 --- a/src/ifd/remote/RemoteIfdServer.cpp +++ b/src/ifd/remote/RemoteIfdServer.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteIfdServer.h" #include "AppSettings.h" #include "Env.h" +#include "TlsChecker.h" using namespace governikus; @@ -30,7 +31,7 @@ void RemoteIfdServer::onConnectedChanged(bool pConnected) { const auto& ifdName = mWebSocketServer->getServerName(); const auto& remoteServiceSettings = Env::getSingleton()->getRemoteServiceSettings(); - const auto& ifdId = QString::fromLatin1(remoteServiceSettings.getCertificate().toPem()); + const auto& ifdId = RemoteServiceSettings::generateFingerprint(TlsChecker::getRootCertificate(remoteServiceSettings.getCertificates())); quint16 port = mWebSocketServer->getServerPort(); bool isPairing = mWebSocketServer->isPairingAnnounced(); mRemoteReaderAdvertiser.reset(Env::create(ifdName, ifdId, port, isPairing)); @@ -50,6 +51,7 @@ RemoteIfdServer::RemoteIfdServer() connect(mWebSocketServer.data(), &RemoteWebSocketServer::fireMessageHandlerAdded, this, &IfdServer::fireMessageHandlerAdded); connect(mWebSocketServer.data(), &RemoteWebSocketServer::firePairingCompleted, this, &IfdServer::firePairingCompleted); connect(mWebSocketServer.data(), &RemoteWebSocketServer::fireSocketError, this, &IfdServer::fireSocketError); + connect(mWebSocketServer.data(), &WebSocketServer::fireNameChanged, this, &IfdServer::fireNameChanged); } diff --git a/src/ifd/remote/RemoteIfdServer.h b/src/ifd/remote/RemoteIfdServer.h index d59201bd8..07c968e77 100644 --- a/src/ifd/remote/RemoteIfdServer.h +++ b/src/ifd/remote/RemoteIfdServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/remote/RemoteReaderAdvertiser.cpp b/src/ifd/remote/RemoteReaderAdvertiser.cpp index 91e8ecd19..f118a7c1b 100644 --- a/src/ifd/remote/RemoteReaderAdvertiser.cpp +++ b/src/ifd/remote/RemoteReaderAdvertiser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteReaderAdvertiser.h" diff --git a/src/ifd/remote/RemoteReaderAdvertiser.h b/src/ifd/remote/RemoteReaderAdvertiser.h index 1c5dd0e03..6df8015de 100644 --- a/src/ifd/remote/RemoteReaderAdvertiser.h +++ b/src/ifd/remote/RemoteReaderAdvertiser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/remote/RemoteTlsServer.cpp b/src/ifd/remote/RemoteTlsServer.cpp index 5e443b201..a7172c78d 100644 --- a/src/ifd/remote/RemoteTlsServer.cpp +++ b/src/ifd/remote/RemoteTlsServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteTlsServer.h" @@ -25,7 +25,7 @@ QSslConfiguration RemoteTlsServer::sslConfiguration() const QSslConfiguration config = Env::getSingleton()->getTlsConfigRemoteIfd(cipherCfg).getConfiguration(); const auto& settings = Env::getSingleton()->getRemoteServiceSettings(); config.setPrivateKey(settings.getKey()); - config.setLocalCertificate(settings.getCertificate()); + config.setLocalCertificateChain(settings.getCertificates()); config.setPeerVerifyMode(QSslSocket::VerifyPeer); if (psk.isEmpty()) @@ -52,8 +52,7 @@ bool RemoteTlsServer::startListening(quint16 pPort) } auto& remoteServiceSettings = Env::getSingleton()->getRemoteServiceSettings(); - const bool invalidLength = !TlsChecker::hasValidCertificateKeyLength(remoteServiceSettings.getCertificate()); - if (!remoteServiceSettings.checkAndGenerateKey(invalidLength)) + if (!remoteServiceSettings.checkAndGenerateKey(Env::getSingleton()->getIfdCreateSize())) { qCCritical(ifd) << "Cannot get required key/certificate for tls"; return false; @@ -78,7 +77,8 @@ bool RemoteTlsServer::startListening(quint16 pPort) void RemoteTlsServer::onSslErrors(const QList& pErrors) { const auto& socket = getSslSocket(); - if (pErrors.size() == 1 && pErrors.first().error() == QSslError::SelfSignedCertificate) + if (pErrors.size() == 1 && + (pErrors.first().error() == QSslError::SelfSignedCertificate || pErrors.first().error() == QSslError::SelfSignedCertificateInChain)) { const auto& pairingCiphers = Env::getSingleton()->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getCiphers(); if (pairingCiphers.contains(socket->sessionCipher())) @@ -99,29 +99,42 @@ void RemoteTlsServer::onEncrypted() const auto& cfg = socket->sslConfiguration(); TlsChecker::logSslConfig(cfg, spawnMessageLogger(ifd)); - if (!TlsChecker::hasValidCertificateKeyLength(cfg.peerCertificate())) + QLatin1String error; + const auto& minimalKeySizes = [](QSsl::KeyAlgorithm pKeyAlgorithm){ + return Env::getSingleton()->getMinimumIfdKeySize(pKeyAlgorithm); + }; + if (!TlsChecker::hasValidCertificateKeyLength(cfg.peerCertificate(), minimalKeySizes)) { - qCCritical(ifd) << "Client denied... abort connection!"; + error = QLatin1String("Client denied... abort connection!"); + } + + const auto rootCert = TlsChecker::getRootCertificate(cfg.peerCertificateChain()); + if (rootCert.isNull()) + { + error = QLatin1String("Client denied... no root certificate found!"); + } + + if (!error.isEmpty()) + { + qCCritical(ifd) << error; socket->abort(); socket->deleteLater(); return; } qCDebug(ifd) << "Client connected"; - auto& settings = Env::getSingleton()->getRemoteServiceSettings(); const auto& pairingCiphers = Env::getSingleton()->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getCiphers(); if (pairingCiphers.contains(cfg.sessionCipher())) { - const auto& sslCertificate = cfg.peerCertificate(); - qCDebug(ifd) << "Pairing completed | Add certificate:" << sslCertificate; - settings.addTrustedCertificate(sslCertificate); + qCDebug(ifd) << "Pairing completed | Add certificate:" << rootCert; + settings.addTrustedCertificate(rootCert); setPairing(false); - Q_EMIT firePairingCompleted(sslCertificate); + Q_EMIT firePairingCompleted(rootCert); } else { - auto info = settings.getRemoteInfo(cfg.peerCertificate()); + auto info = settings.getRemoteInfo(rootCert); info.setLastConnected(QDateTime::currentDateTime()); settings.updateRemoteInfo(info); } diff --git a/src/ifd/remote/RemoteTlsServer.h b/src/ifd/remote/RemoteTlsServer.h index 648b5574d..e995c1fcc 100644 --- a/src/ifd/remote/RemoteTlsServer.h +++ b/src/ifd/remote/RemoteTlsServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/remote/RemoteWebSocketServer.cpp b/src/ifd/remote/RemoteWebSocketServer.cpp index d955bad8d..fa242d76f 100644 --- a/src/ifd/remote/RemoteWebSocketServer.cpp +++ b/src/ifd/remote/RemoteWebSocketServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteWebSocketServer.h" diff --git a/src/ifd/remote/RemoteWebSocketServer.h b/src/ifd/remote/RemoteWebSocketServer.h index 938f3c5aa..26d2521ea 100644 --- a/src/ifd/remote/RemoteWebSocketServer.h +++ b/src/ifd/remote/RemoteWebSocketServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/remote/RemoteWebSocketServerImpl.cpp b/src/ifd/remote/RemoteWebSocketServerImpl.cpp index 9770a16db..f1235531e 100644 --- a/src/ifd/remote/RemoteWebSocketServerImpl.cpp +++ b/src/ifd/remote/RemoteWebSocketServerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteWebSocketServerImpl.h" @@ -38,7 +38,7 @@ void RemoteWebSocketServerImpl::onNewConnection(QSharedPointer pSock RemoteWebSocketServerImpl::RemoteWebSocketServerImpl() : RemoteWebSocketServer() , mRemoteTlsServer(QSharedPointer::create()) - , mWebSocketServer(mRemoteTlsServer, {ReaderManagerPlugInType::NFC, ReaderManagerPlugInType::SMART, ReaderManagerPlugInType::UNKNOWN}) + , mWebSocketServer(mRemoteTlsServer, {ReaderManagerPluginType::NFC, ReaderManagerPluginType::SMART, ReaderManagerPluginType::UNKNOWN}) , mPairingConnection(false) { connect(mRemoteTlsServer.data(), &RemoteTlsServer::firePairingCompleted, this, &RemoteWebSocketServer::firePairingCompleted); @@ -46,6 +46,7 @@ RemoteWebSocketServerImpl::RemoteWebSocketServerImpl() connect(&mWebSocketServer, &WebSocketServer::fireConnectedChanged, this, &RemoteWebSocketServerImpl::fireConnectedChanged); connect(&mWebSocketServer, &WebSocketServer::fireMessageHandlerAdded, this, &RemoteWebSocketServerImpl::fireMessageHandlerAdded); connect(&mWebSocketServer, &WebSocketServer::firePskChanged, this, &RemoteWebSocketServerImpl::firePskChanged); + connect(&mWebSocketServer, &WebSocketServer::fireNameChanged, this, &RemoteWebSocketServer::fireNameChanged); } diff --git a/src/ifd/remote/RemoteWebSocketServerImpl.h b/src/ifd/remote/RemoteWebSocketServerImpl.h index ba7d8bf4a..78072c60f 100644 --- a/src/ifd/remote/RemoteWebSocketServerImpl.h +++ b/src/ifd/remote/RemoteWebSocketServerImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ifd/remote/metadata.json b/src/ifd/remote/metadata.json index 51103d026..66918b815 100644 --- a/src/ifd/remote/metadata.json +++ b/src/ifd/remote/metadata.json @@ -1,4 +1,4 @@ { - "name" : "RemoteIfdReaderManagerPlugIn", + "name" : "RemoteIfdReaderManagerPlugin", "dependencies" : [] } diff --git a/src/init/Bootstrap.cpp b/src/init/Bootstrap.cpp index f54c86fd8..6772df2f8 100644 --- a/src/init/Bootstrap.cpp +++ b/src/init/Bootstrap.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Bootstrap.h" @@ -60,9 +60,9 @@ static inline void printInfo() qCInfo(init) << "##################################################"; const auto& info = BuildHelper::getInformationHeader(); - for (const auto& entry : info) + for (const auto& [key, value] : info) { - qCInfo(init).noquote().nospace() << "### " << entry.first << ": " << entry.second; + qCInfo(init).noquote().nospace() << "### " << key << ": " << value; } qCInfo(init) << "##################################################"; diff --git a/src/init/Bootstrap.h b/src/init/Bootstrap.h index 5e71c27ae..3546475ba 100644 --- a/src/init/Bootstrap.h +++ b/src/init/Bootstrap.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/init/CommandLineParser.cpp b/src/init/CommandLineParser.cpp index 643bcbbb6..b34c9f673 100644 --- a/src/init/CommandLineParser.cpp +++ b/src/init/CommandLineParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CommandLineParser.h" @@ -10,7 +10,7 @@ #include "NetworkManager.h" #include "PortFile.h" #include "SingletonHelper.h" -#include "UILoader.h" +#include "UiLoader.h" #include "controller/AppController.h" #include @@ -29,7 +29,7 @@ CommandLineParser::CommandLineParser() , mOptionNoLogHandler(QStringLiteral("no-loghandler"), QStringLiteral("Disable default log handler.")) , mOptionShowWindow(QStringLiteral("show"), QStringLiteral("Show window on startup.")) , mOptionProxy(QStringLiteral("no-proxy"), QStringLiteral("Ignore proxy settings.")) - , mOptionUi(QStringLiteral("ui"), QStringLiteral("Use given UI plugin."), UILoader::getDefault()) + , mOptionUi(QStringLiteral("ui"), QStringLiteral("Use given UI plugin."), UiLoader::getDefault()) , mOptionPort(QStringLiteral("port"), QStringLiteral("Use listening port."), QString::number(PortFile::cDefaultPort)) , mOptionAddresses(QStringLiteral("address"), QStringLiteral("Use address binding."), HttpServer::getDefault()) { @@ -67,8 +67,7 @@ void CommandLineParser::parse(const QCoreApplication* pApp) mParser.process(*pApp); parseUiPlugin(); - const auto& logHandler = Env::getSingleton(); - + auto* logHandler = Env::getSingleton(); logHandler->setAutoRemove(!mParser.isSet(mOptionKeepLog)); logHandler->setLogFile(!mParser.isSet(mOptionNoLogFile)); logHandler->setUseHandler(!mParser.isSet(mOptionNoLogHandler)); @@ -112,6 +111,6 @@ void CommandLineParser::parseUiPlugin() { if (mParser.isSet(mOptionUi)) { - UILoader::setUserRequest(mParser.values(mOptionUi)); + UiLoader::setUserRequest(mParser.values(mOptionUi)); } } diff --git a/src/init/CommandLineParser.h b/src/init/CommandLineParser.h index b48229913..c967052ee 100644 --- a/src/init/CommandLineParser.h +++ b/src/init/CommandLineParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/init/SignalHandler.cpp b/src/init/SignalHandler.cpp index 243067f74..ea7125876 100644 --- a/src/init/SignalHandler.cpp +++ b/src/init/SignalHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SignalHandler.h" diff --git a/src/init/SignalHandler.h b/src/init/SignalHandler.h index 9efe79d4b..9a7931aac 100644 --- a/src/init/SignalHandler.h +++ b/src/init/SignalHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/init/SignalHandler_bsd_linux_osx.cpp b/src/init/SignalHandler_bsd_linux_osx.cpp index e9b8b8211..b094581ae 100644 --- a/src/init/SignalHandler_bsd_linux_osx.cpp +++ b/src/init/SignalHandler_bsd_linux_osx.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "SignalHandler.h" diff --git a/src/init/SignalHandler_win.cpp b/src/init/SignalHandler_win.cpp index 360903f92..a423ba17e 100644 --- a/src/init/SignalHandler_win.cpp +++ b/src/init/SignalHandler_win.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "SignalHandler.h" @@ -17,7 +17,7 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(system) -#define SERVICE_NAME TEXT("AusweisApp2") +#define SERVICE_NAME TEXT("AusweisApp") namespace { diff --git a/src/main.cpp b/src/main.cpp index 5f43812e8..cadec3a45 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Bootstrap.h" @@ -9,53 +9,53 @@ #include -Q_IMPORT_PLUGIN(SimulatorReaderManagerPlugIn) +Q_IMPORT_PLUGIN(SimulatorReaderManagerPlugin) #if !defined(Q_OS_WINRT) && !defined(INTEGRATED_SDK) -Q_IMPORT_PLUGIN(RemoteIfdReaderManagerPlugIn) +Q_IMPORT_PLUGIN(RemoteIfdReaderManagerPlugin) #endif #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_WINRT) -Q_IMPORT_PLUGIN(PcscReaderManagerPlugIn) +Q_IMPORT_PLUGIN(PcscReaderManagerPlugin) #if !defined(INTEGRATED_SDK) || defined(CONTAINER_SDK) -Q_IMPORT_PLUGIN(UIPlugInWebService) -Q_IMPORT_PLUGIN(UIPlugInProxy) +Q_IMPORT_PLUGIN(UiPluginWebService) +Q_IMPORT_PLUGIN(UiPluginProxy) #endif #if defined(USE_SMARTEID) && (defined(CONTAINER_SDK) || !defined(QT_NO_DEBUG)) -Q_IMPORT_PLUGIN(SmartReaderManagerPlugIn) +Q_IMPORT_PLUGIN(SmartReaderManagerPlugin) #endif #endif #if defined(Q_OS_ANDROID) -Q_IMPORT_PLUGIN(NfcReaderManagerPlugIn) +Q_IMPORT_PLUGIN(NfcReaderManagerPlugin) #ifndef INTEGRATED_SDK -Q_IMPORT_PLUGIN(UIPlugInScheme) +Q_IMPORT_PLUGIN(UiPluginScheme) #ifdef USE_SMARTEID -Q_IMPORT_PLUGIN(UIPlugInLocalIfd) -Q_IMPORT_PLUGIN(SmartReaderManagerPlugIn) +Q_IMPORT_PLUGIN(UiPluginLocalIfd) +Q_IMPORT_PLUGIN(SmartReaderManagerPlugin) #endif #else -Q_IMPORT_PLUGIN(LocalIfdReaderManagerPlugIn) +Q_IMPORT_PLUGIN(LocalIfdReaderManagerPlugin) #endif #endif #if defined(Q_OS_IOS) -Q_IMPORT_PLUGIN(NfcReaderManagerPlugIn) +Q_IMPORT_PLUGIN(NfcReaderManagerPlugin) #ifndef INTEGRATED_SDK -Q_IMPORT_PLUGIN(UIPlugInScheme) +Q_IMPORT_PLUGIN(UiPluginScheme) #ifdef USE_SMARTEID -Q_IMPORT_PLUGIN(SmartReaderManagerPlugIn) +Q_IMPORT_PLUGIN(SmartReaderManagerPlugin) #endif Q_IMPORT_PLUGIN(QJpegPlugin) @@ -66,24 +66,24 @@ Q_IMPORT_PLUGIN(QSvgPlugin) #if defined(Q_OS_ANDROID) || !defined(QT_NO_DEBUG) -Q_IMPORT_PLUGIN(UIPlugInAidl) +Q_IMPORT_PLUGIN(UiPluginAidl) #endif #ifndef INTEGRATED_SDK -Q_IMPORT_PLUGIN(UIPlugInQml) +Q_IMPORT_PLUGIN(UiPluginQml) #endif #if defined(INTEGRATED_SDK) && !defined(Q_OS_ANDROID) && !defined(CONTAINER_SDK) -Q_IMPORT_PLUGIN(UIPlugInFunctional) +Q_IMPORT_PLUGIN(UiPluginFunctional) #endif #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && (!defined(INTEGRATED_SDK) || defined(CONTAINER_SDK)) -Q_IMPORT_PLUGIN(UIPlugInAutomatic) -Q_IMPORT_PLUGIN(UIPlugInWebSocket) +Q_IMPORT_PLUGIN(UiPluginAutomatic) +Q_IMPORT_PLUGIN(UiPluginWebSocket) #endif #if !defined(Q_OS_IOS) || defined(INTEGRATED_SDK) -Q_IMPORT_PLUGIN(UIPlugInJson) +Q_IMPORT_PLUGIN(UiPluginJson) #endif Q_DECL_EXPORT int main(int argc, char** argv) diff --git a/src/network/DatagramHandler.cpp b/src/network/DatagramHandler.cpp index 42d2f6444..87b62431c 100644 --- a/src/network/DatagramHandler.cpp +++ b/src/network/DatagramHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "DatagramHandler.h" diff --git a/src/network/DatagramHandler.h b/src/network/DatagramHandler.h index 61d48d479..53399a22e 100644 --- a/src/network/DatagramHandler.h +++ b/src/network/DatagramHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/DatagramHandlerImpl.cpp b/src/network/DatagramHandlerImpl.cpp index 5d7cd7500..264ed5157 100644 --- a/src/network/DatagramHandlerImpl.cpp +++ b/src/network/DatagramHandlerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "DatagramHandlerImpl.h" @@ -145,9 +145,9 @@ bool DatagramHandlerImpl::isValidBroadcastInterface(const QNetworkInterface& pIn } -QVector DatagramHandlerImpl::getAllBroadcastAddresses(const QNetworkInterface& pInterface) const +QList DatagramHandlerImpl::getAllBroadcastAddresses(const QNetworkInterface& pInterface) const { - QVector broadcastAddresses; + QList broadcastAddresses; if (!isValidBroadcastInterface(pInterface)) { @@ -225,7 +225,7 @@ void DatagramHandlerImpl::sendToAllAddressEntries(const QByteArray& pData, quint } } - QVector broadcastAddresses; + QList broadcastAddresses; for (const QNetworkInterface& interface : allInterfaces) { broadcastAddresses << getAllBroadcastAddresses(interface); diff --git a/src/network/DatagramHandlerImpl.h b/src/network/DatagramHandlerImpl.h index f533ee9aa..818557f62 100644 --- a/src/network/DatagramHandlerImpl.h +++ b/src/network/DatagramHandlerImpl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -39,7 +39,7 @@ class DatagramHandlerImpl void resetSocket(); [[nodiscard]] bool isValidBroadcastInterface(const QNetworkInterface& pInterface) const; - [[nodiscard]] QVector getAllBroadcastAddresses(const QNetworkInterface& pInterface) const; + [[nodiscard]] QList getAllBroadcastAddresses(const QNetworkInterface& pInterface) const; [[nodiscard]] bool sendToAddress(const QByteArray& pData, const QHostAddress& pAddress, quint16 pPort = 0, bool pLogError = true); void sendToAllAddressEntries(const QByteArray& pData, quint16 pPort); diff --git a/src/network/HttpHandler.cpp b/src/network/HttpHandler.cpp index 854b093bd..997d4ed62 100644 --- a/src/network/HttpHandler.cpp +++ b/src/network/HttpHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpHandler.h" @@ -26,35 +26,23 @@ void HttpHandler::handle(const QSharedPointer& pRequest) const auto& url = pRequest->getUrl(); if (url.path() == QLatin1String("/eID-Client")) { - const auto queryUrl = QUrlQuery(url); - UrlUtil::setHiddenSettings(queryUrl); - const auto [type, value] = UrlUtil::getRequest(queryUrl); - switch (type) + switch (pRequest->getHttpMethod()) { - case UrlQueryRequest::SHOWUI: - { - qCDebug(network) << "Request type: showui"; - handleShowUiRequest(value, pRequest); + case HTTP_GET: + if (handleGetRequest(pRequest, url)) + { + return; + } + break; + + case HTTP_OPTIONS: + case HTTP_HEAD: + qCDebug(network) << "Request type: Pre-flight CORS"; + handleCorsRequest(pRequest); return; - } - - case UrlQueryRequest::STATUS: - { - qCDebug(network) << "Request type: status"; - const StatusFormat statusFormat = UrlUtil::prepareToEnum(value, StatusFormat::PLAIN); - handleStatusRequest(statusFormat, pRequest); - return; - } - - case UrlQueryRequest::TCTOKENURL: - { - qCDebug(network) << "Request type: authentication"; - handleWorkflowRequest(pRequest); - return; - } default: - qCWarning(network) << "Unknown request type:" << url; + qCDebug(network) << "Unhandled HTTP method:" << pRequest->getMethod(); } } else if (url.path() == QLatin1String("/favicon.ico")) @@ -95,6 +83,50 @@ void HttpHandler::handle(const QSharedPointer& pRequest) } +void HttpHandler::handleCorsRequest(const QSharedPointer& pRequest) const +{ + HttpResponse response(HTTP_STATUS_NO_CONTENT); + setCorsResponseHeaders(response); + pRequest->send(response); +} + + +bool HttpHandler::handleGetRequest(const QSharedPointer& pRequest, const QUrl& pUrl) +{ + const auto queryUrl = QUrlQuery(pUrl); + UrlUtil::setHiddenSettings(queryUrl); + const auto [type, value] = UrlUtil::getRequest(queryUrl); + switch (type) + { + case UrlQueryRequest::SHOWUI: + { + qCDebug(network) << "Request type: showui"; + handleShowUiRequest(value, pRequest); + return true; + } + + case UrlQueryRequest::STATUS: + { + qCDebug(network) << "Request type: status"; + const StatusFormat statusFormat = UrlUtil::prepareToEnum(value, StatusFormat::PLAIN); + handleStatusRequest(statusFormat, pRequest); + return true; + } + + case UrlQueryRequest::TCTOKENURL: + { + qCDebug(network) << "Request type: authentication"; + handleWorkflowRequest(pRequest); + return true; + } + + default: + qCWarning(network) << "Unknown request type:" << pUrl; + return false; + } +} + + void HttpHandler::handleImageRequest(const QSharedPointer& pRequest, const QString& pImagePath) const { HttpResponse response; @@ -139,13 +171,19 @@ QByteArray HttpHandler::guessImageContentType(const QString& pFileName) const } +void HttpHandler::setCorsResponseHeaders(HttpResponse& pResponse) const +{ + pResponse.setHeader(QByteArrayLiteral("Access-Control-Allow-Origin"), QByteArrayLiteral("*")); + pResponse.setHeader(QByteArrayLiteral("Access-Control-Allow-Private-Network"), QByteArrayLiteral("true")); +} + + void HttpHandler::handleStatusRequest(StatusFormat pStatusFormat, const QSharedPointer& pRequest) const { qCDebug(network) << "Create response with status format:" << pStatusFormat; HttpResponse response(HTTP_STATUS_OK); - response.setHeader(QByteArrayLiteral("Access-Control-Allow-Origin"), QByteArrayLiteral("*")); - response.setHeader(QByteArrayLiteral("Access-Control-Allow-Private-Network"), QByteArrayLiteral("true")); + setCorsResponseHeaders(response); switch (pStatusFormat) { case StatusFormat::PLAIN: diff --git a/src/network/HttpHandler.h b/src/network/HttpHandler.h index 05cd11f7c..fcdd66371 100644 --- a/src/network/HttpHandler.h +++ b/src/network/HttpHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -7,7 +7,9 @@ #include "EnumHelper.h" #include "HttpRequest.h" -class test_UIPlugInWebService; +#include + +class test_UiPluginWebService; namespace governikus { @@ -20,10 +22,13 @@ defineEnumType(StatusFormat, class HttpHandler { Q_DECLARE_TR_FUNCTIONS(governikus::HttpHandler) - friend class ::test_UIPlugInWebService; + friend class ::test_UiPluginWebService; private: [[nodiscard]] QByteArray guessImageContentType(const QString& pFileName) const; + void setCorsResponseHeaders(HttpResponse& pRequest) const; + void handleCorsRequest(const QSharedPointer& pRequest) const; + bool handleGetRequest(const QSharedPointer& pRequest, const QUrl& pUrl); protected: virtual ~HttpHandler() = default; @@ -34,8 +39,6 @@ class HttpHandler virtual void handleStatusRequest(StatusFormat pStatusFormat, const QSharedPointer& pRequest) const; virtual void handleShowUiRequest(const QString& pUiModule, const QSharedPointer& pRequest) = 0; virtual void handleWorkflowRequest(const QSharedPointer& pRequest) = 0; - - }; } // namespace governikus diff --git a/src/network/HttpRequest.cpp b/src/network/HttpRequest.cpp index 5d535d3a9..3fb657ef6 100644 --- a/src/network/HttpRequest.cpp +++ b/src/network/HttpRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpRequest.h" diff --git a/src/network/HttpRequest.h b/src/network/HttpRequest.h index 54046aa8b..c1bc3edcb 100644 --- a/src/network/HttpRequest.h +++ b/src/network/HttpRequest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/HttpResponse.cpp b/src/network/HttpResponse.cpp index 2e41779db..842586681 100644 --- a/src/network/HttpResponse.cpp +++ b/src/network/HttpResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpResponse.h" @@ -100,7 +100,7 @@ QByteArray HttpResponse::getStatusMessage() const QByteArray HttpResponse::getMessage() const { - static const QByteArray CR_LF = QByteArrayLiteral("\r\n"); + static const auto CR_LF = QByteArrayLiteral("\r\n"); QByteArrayList list; list += QByteArrayLiteral("HTTP/1.0 ") % QByteArray::number(mStatus) % ' ' % getStatusMessage(); diff --git a/src/network/HttpResponse.h b/src/network/HttpResponse.h index 6ee8ba9aa..dd59ba733 100644 --- a/src/network/HttpResponse.h +++ b/src/network/HttpResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/HttpServer.cpp b/src/network/HttpServer.cpp index b2192574c..e8edaf8a5 100644 --- a/src/network/HttpServer.cpp +++ b/src/network/HttpServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpServer.h" @@ -13,10 +13,10 @@ Q_DECLARE_LOGGING_CATEGORY(network) quint16 HttpServer::cPort = PortFile::cDefaultPort; -QVector HttpServer::cAddresses = {QHostAddress::LocalHost, QHostAddress::LocalHostIPv6}; +QList HttpServer::cAddresses = {QHostAddress::LocalHost, QHostAddress::LocalHostIPv6}; -HttpServer::HttpServer(quint16 pPort, const QVector& pAddresses) +HttpServer::HttpServer(quint16 pPort, const QList& pAddresses) : QObject() , mServer() , mPortFile() @@ -45,7 +45,7 @@ void HttpServer::shutdown() } -void HttpServer::bindAddresses(quint16 pPort, const QVector& pAddresses) +void HttpServer::bindAddresses(quint16 pPort, const QList& pAddresses) { auto port = pPort; @@ -121,7 +121,7 @@ quint16 HttpServer::getServerPort() const } -void HttpServer::rebind(quint16 pPort, const QVector& pAddresses) +void HttpServer::rebind(quint16 pPort, const QList& pAddresses) { qCDebug(network) << "Rebind HttpServer:" << pPort << '|' << pAddresses; mPortFile.remove(); diff --git a/src/network/HttpServer.h b/src/network/HttpServer.h index a32b8da76..3cd44cf9d 100644 --- a/src/network/HttpServer.h +++ b/src/network/HttpServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,10 +11,10 @@ #include "HttpRequest.h" #include "PortFile.h" +#include #include #include #include -#include namespace governikus { @@ -25,26 +25,26 @@ class HttpServer Q_OBJECT private: - QVector mServer; + QList mServer; PortFile mPortFile; void shutdown(); - void bindAddresses(quint16 pPort, const QVector& pAddresses); + void bindAddresses(quint16 pPort, const QList& pAddresses); bool checkReceiver(const QMetaMethod& pSignal, HttpRequest* pRequest); public: static quint16 cPort; - static QVector cAddresses; + static QList cAddresses; static QString getDefault(); explicit HttpServer(quint16 pPort = HttpServer::cPort, - const QVector& pAddresses = HttpServer::cAddresses); + const QList& pAddresses = HttpServer::cAddresses); ~HttpServer() override; [[nodiscard]] QStringList boundAddresses() const; [[nodiscard]] bool isListening() const; [[nodiscard]] quint16 getServerPort() const; - void rebind(quint16 pPort = 0, const QVector& pAddresses = HttpServer::cAddresses); + void rebind(quint16 pPort = 0, const QList& pAddresses = HttpServer::cAddresses); private Q_SLOTS: void onNewConnection(); diff --git a/src/network/HttpServerRequestor.cpp b/src/network/HttpServerRequestor.cpp index a4e335da2..0dacac9aa 100644 --- a/src/network/HttpServerRequestor.cpp +++ b/src/network/HttpServerRequestor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpServerRequestor.h" @@ -85,6 +85,24 @@ QSharedPointer HttpServerRequestor::deleteRequest(const QUrl& pUr } +QSharedPointer HttpServerRequestor::headRequest(const QUrl& pUrl, int pTimeOut) +{ + QNetworkRequest request(pUrl); + qCDebug(network) << "Request URL (HEAD):" << pUrl; + auto reply = mNetworkManager ? mNetworkManager->head(request) : nullptr; + return waitForReply(reply, pTimeOut); +} + + +QSharedPointer HttpServerRequestor::optionsRequest(const QUrl& pUrl, int pTimeOut) +{ + QNetworkRequest request(pUrl); + qCDebug(network) << "Request URL (OPTIONS):" << pUrl; + auto reply = mNetworkManager ? mNetworkManager->options(request) : nullptr; + return waitForReply(reply, pTimeOut); +} + + QSharedPointer HttpServerRequestor::waitForReply(QSharedPointer pReply, int pTimeOut) { if (!pReply) diff --git a/src/network/HttpServerRequestor.h b/src/network/HttpServerRequestor.h index 53de6ae59..fe6f25a8f 100644 --- a/src/network/HttpServerRequestor.h +++ b/src/network/HttpServerRequestor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -16,7 +16,7 @@ #include #include -class test_UIPlugInWebService; +class test_UiPluginWebService; namespace governikus { @@ -33,7 +33,7 @@ class HttpServerRequestor : public QObject { Q_OBJECT - friend class ::test_UIPlugInWebService; + friend class ::test_UiPluginWebService; private: QPointer mNetworkManager; @@ -51,6 +51,8 @@ class HttpServerRequestor [[nodiscard]] QSharedPointer getRequest(const QUrl& pUrl, int pTimeOut = 2000); [[nodiscard]] QSharedPointer postRequest(const QUrl& pUrl, const QByteArray& pData, const QString& pContentType, int pTimeOut = 2000); [[nodiscard]] QSharedPointer deleteRequest(const QUrl& pUrl, int pTimeOut = 2000); + [[nodiscard]] QSharedPointer headRequest(const QUrl& pUrl, int pTimeOut = 2000); + [[nodiscard]] QSharedPointer optionsRequest(const QUrl& pUrl, int pTimeOut = 2000); static QUrl createUrl(const QString& pQuery, quint16 pPort, const QHostAddress& pHost, const QString& pPath = QStringLiteral("/eID-Client")); diff --git a/src/network/HttpServerStatusParser.cpp b/src/network/HttpServerStatusParser.cpp index 0fdab6f1c..5f4ed748a 100644 --- a/src/network/HttpServerStatusParser.cpp +++ b/src/network/HttpServerStatusParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpServerStatusParser.h" diff --git a/src/network/HttpServerStatusParser.h b/src/network/HttpServerStatusParser.h index 787ce8907..fb7f4f185 100644 --- a/src/network/HttpServerStatusParser.h +++ b/src/network/HttpServerStatusParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/MulticastLock.cpp b/src/network/MulticastLock.cpp index 6d5f1898b..6ad3bf43a 100644 --- a/src/network/MulticastLock.cpp +++ b/src/network/MulticastLock.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "MulticastLock.h" diff --git a/src/network/MulticastLock.h b/src/network/MulticastLock.h index f325c3696..d66ef1702 100644 --- a/src/network/MulticastLock.h +++ b/src/network/MulticastLock.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/network/MulticastLockJniBridgeUtil.java b/src/network/MulticastLockJniBridgeUtil.java index 24b33eba7..3e3ec7c8e 100644 --- a/src/network/MulticastLockJniBridgeUtil.java +++ b/src/network/MulticastLockJniBridgeUtil.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/network/NetworkManager.cpp b/src/network/NetworkManager.cpp index 9af2abe41..45029d797 100644 --- a/src/network/NetworkManager.cpp +++ b/src/network/NetworkManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "NetworkManager.h" @@ -99,6 +99,22 @@ QSharedPointer NetworkManager::deleteResource(QNetworkRequest& pR } +QSharedPointer NetworkManager::head(QNetworkRequest& pRequest) +{ + return processRequest(pRequest, [this] (const QNetworkRequest& request){ + return trackConnection(mNetAccessManager.head(request)); + }); +} + + +QSharedPointer NetworkManager::options(QNetworkRequest& pRequest) +{ + return processRequest(pRequest, [this] (const QNetworkRequest& request){ + return trackConnection(mNetAccessManager.sendCustomRequest(request, "OPTIONS")); + }); +} + + QSharedPointer NetworkManager::getAsUpdater(QNetworkRequest& pRequest) { return processUpdaterRequest(pRequest, [this] (QNetworkRequest& request){ @@ -132,7 +148,7 @@ QSharedPointer NetworkManager::processUpdaterRequest(QNetworkRequ { QSharedPointer response = processRequest(pRequest, [pInvoke] (QNetworkRequest& request){ auto cfg = request.sslConfiguration(); - cfg.setCaCertificates(Env::getSingleton()->getUpdateCertificates().toList()); + cfg.setCaCertificates(Env::getSingleton()->getUpdateCertificates()); request.setSslConfiguration(cfg); return pInvoke(request); }); @@ -344,6 +360,8 @@ bool NetworkManager::prepareConnection(QNetworkRequest& pRequest) const pRequest.setSslConfiguration(cfg); } + pRequest.setAttribute(QNetworkRequest::Http2AllowedAttribute, false); + return true; } @@ -409,9 +427,9 @@ int NetworkManager::getLoggedStatusCode(const QSharedPointerattribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); pLogger.debug() << "Status Code:" << statusCode << getStatusMessage(statusCode); - for (const auto& header : pReply->rawHeaderPairs()) + for (const auto& [key, value] : pReply->rawHeaderPairs()) { - pLogger.debug().nospace().noquote() << "Header | " << header.first << ": " << header.second; + pLogger.debug().nospace().noquote() << "Header | " << key << ": " << value; } return statusCode; } diff --git a/src/network/NetworkManager.h b/src/network/NetworkManager.h index c3723ce8e..9ae24937c 100644 --- a/src/network/NetworkManager.h +++ b/src/network/NetworkManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -95,6 +95,8 @@ class NetworkManager [[nodiscard]] virtual QSharedPointer post(QNetworkRequest& pRequest, const QByteArray& pData); [[nodiscard]] virtual QSharedPointer deleteResource(QNetworkRequest& pRequest); + [[nodiscard]] virtual QSharedPointer head(QNetworkRequest& pRequest); + [[nodiscard]] virtual QSharedPointer options(QNetworkRequest& pRequest); [[nodiscard]] QSharedPointer getAsUpdater(QNetworkRequest& pRequest); [[nodiscard]] QSharedPointer postAsUpdater(QNetworkRequest& pRequest, diff --git a/src/network/NetworkReplyError.cpp b/src/network/NetworkReplyError.cpp index 421218b9c..843833e9d 100644 --- a/src/network/NetworkReplyError.cpp +++ b/src/network/NetworkReplyError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "NetworkReplyError.h" diff --git a/src/network/NetworkReplyError.h b/src/network/NetworkReplyError.h index cfc5720e4..2fbc87de3 100644 --- a/src/network/NetworkReplyError.h +++ b/src/network/NetworkReplyError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/network/PortFile.cpp b/src/network/PortFile.cpp index 6a0728feb..acc029c25 100644 --- a/src/network/PortFile.cpp +++ b/src/network/PortFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "PortFile.h" diff --git a/src/network/PortFile.h b/src/network/PortFile.h index 0324196ca..8ee050041 100644 --- a/src/network/PortFile.h +++ b/src/network/PortFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/network/Template.cpp b/src/network/Template.cpp index b9682aa50..2d3a439fe 100644 --- a/src/network/Template.cpp +++ b/src/network/Template.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "Template.h" diff --git a/src/network/Template.h b/src/network/Template.h index b99221ec3..cee17e684 100644 --- a/src/network/Template.h +++ b/src/network/Template.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/TlsChecker.cpp b/src/network/TlsChecker.cpp index 650a21d78..23963bf97 100644 --- a/src/network/TlsChecker.cpp +++ b/src/network/TlsChecker.cpp @@ -1,10 +1,11 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TlsChecker.h" #include "AppSettings.h" +#include "EnumHelper.h" #include "SecureStorage.h" #include @@ -17,6 +18,10 @@ Q_DECLARE_LOGGING_CATEGORY(network) using namespace governikus; +const std::function TlsChecker::cDefaultFuncMinKeySize = [](QSsl::KeyAlgorithm pKeyAlgorithm){ + return Env::getSingleton()->getMinimumKeySize(pKeyAlgorithm); + }; + bool TlsChecker::checkCertificate(const QSslCertificate& pCertificate, QCryptographicHash::Algorithm pAlgorithm, const QSet& pAcceptedCertificateHashes) @@ -33,7 +38,7 @@ bool TlsChecker::checkCertificate(const QSslCertificate& pCertificate, } -bool TlsChecker::hasValidCertificateKeyLength(const QSslCertificate& pCertificate) +bool TlsChecker::hasValidCertificateKeyLength(const QSslCertificate& pCertificate, const std::function& pFuncMinKeySize) { if (pCertificate.isNull()) { @@ -43,12 +48,16 @@ bool TlsChecker::hasValidCertificateKeyLength(const QSslCertificate& pCertificat auto keyLength = pCertificate.publicKey().length(); auto keyAlgorithm = pCertificate.publicKey().algorithm(); +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) qDebug() << "Check certificate key of type" << TlsChecker::toString(keyAlgorithm) << "and key size" << keyLength; - return isValidKeyLength(keyLength, keyAlgorithm, false); +#else + qDebug() << "Check certificate key of type" << keyAlgorithm << "and key size" << keyLength; +#endif + return isValidKeyLength(keyLength, keyAlgorithm, pFuncMinKeySize(keyAlgorithm)); } -bool TlsChecker::hasValidEphemeralKeyLength(const QSslKey& pEphemeralServerKey) +bool TlsChecker::hasValidEphemeralKeyLength(const QSslKey& pEphemeralServerKey, const std::function& pFuncMinKeySize) { int keyLength = pEphemeralServerKey.length(); QSsl::KeyAlgorithm keyAlgorithm = pEphemeralServerKey.algorithm(); @@ -58,33 +67,54 @@ bool TlsChecker::hasValidEphemeralKeyLength(const QSslKey& pEphemeralServerKey) qWarning() << "Qt failed to determine algorithm"; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) qDebug() << "Check ephemeral key of type" << TlsChecker::toString(keyAlgorithm) << "and key size" << keyLength; - return isValidKeyLength(keyLength, keyAlgorithm, true); +#else + qDebug() << "Check ephemeral key of type" << keyAlgorithm << "and key size" << keyLength; +#endif + return isValidKeyLength(keyLength, keyAlgorithm, pFuncMinKeySize(keyAlgorithm)); +} + + +FailureCode::FailureInfoMap TlsChecker::getEphemeralKeyInfoMap(const QSslKey& pEphemeralServerKey) +{ + FailureCode::FailureInfoMap infoMap; +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) + infoMap.insert(FailureCode::Info::Ephemeral_Server_Key_Algorithm, TlsChecker::toString(pEphemeralServerKey.algorithm())); +#else + infoMap.insert(FailureCode::Info::Ephemeral_Server_Key_Algorithm, getEnumName(pEphemeralServerKey.algorithm())); +#endif + infoMap.insert(FailureCode::Info::Ephemeral_Server_Key_Length, QString::number(pEphemeralServerKey.length())); + return infoMap; } -QString TlsChecker::getCertificateIssuerName(const QSslCertificate& pCertificate) +QSslCertificate TlsChecker::getRootCertificate(const QList& pCertificates) { - const auto& issuerNameList = pCertificate.issuerInfo(QSslCertificate::CommonName); - if (!issuerNameList.isEmpty()) + for (const auto& cert : pCertificates) { - return issuerNameList.first(); + if (cert.isSelfSigned()) + { + return cert; + } } - return QString(); + + return QSslCertificate(); } -bool TlsChecker::isValidKeyLength(int pKeyLength, QSsl::KeyAlgorithm pKeyAlgorithm, bool pIsEphemeral) +bool TlsChecker::isValidKeyLength(int pKeyLength, QSsl::KeyAlgorithm pKeyAlgorithm, int pMinKeySize) { - const auto* secureStorage = Env::getSingleton(); - const int minKeySize = pIsEphemeral ? secureStorage->getMinimumEphemeralKeySize(pKeyAlgorithm) : secureStorage->getMinimumStaticKeySize(pKeyAlgorithm); + qDebug() << "Minimum requested key size" << pMinKeySize; - qDebug() << "Minimum requested key size" << minKeySize; - - bool sufficient = pKeyLength >= minKeySize; + bool sufficient = pKeyLength >= pMinKeySize; if (!sufficient) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) auto keySizeError = QStringLiteral("%1 key with insufficient key size found %2").arg(toString(pKeyAlgorithm)).arg(pKeyLength); +#else + auto keySizeError = QStringLiteral("%1 key with insufficient key size found %2").arg(getEnumName(pKeyAlgorithm)).arg(pKeyLength); +#endif if (Env::getSingleton()->getGeneralSettings().isDeveloperMode()) { qCWarning(developermode).noquote() << keySizeError; @@ -99,6 +129,7 @@ bool TlsChecker::isValidKeyLength(int pKeyLength, QSsl::KeyAlgorithm pKeyAlgorit } +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) QString TlsChecker::toString(QSsl::SslProtocol pProtocol) { switch (pProtocol) @@ -182,6 +213,8 @@ QString TlsChecker::toString(QSsl::KeyAlgorithm pKeyAlgorithm) } +#endif + QStringList TlsChecker::getFatalErrors(const QList& pErrors) { static const QSet fatalErrors( @@ -259,7 +292,11 @@ QString TlsChecker::sslErrorsToString(const QList& pErrors) void TlsChecker::logSslConfig(const QSslConfiguration& pCfg, const MessageLogger& pLogger) { pLogger.info() << "Used session cipher" << pCfg.sessionCipher(); +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) pLogger.info() << "Used session protocol:" << toString(pCfg.sessionProtocol()); +#else + pLogger.info() << "Used session protocol:" << pCfg.sessionProtocol(); +#endif { auto stream = pLogger.info(); diff --git a/src/network/TlsChecker.h b/src/network/TlsChecker.h index 72ab2e5d9..d35e8bc1f 100644 --- a/src/network/TlsChecker.h +++ b/src/network/TlsChecker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,6 +8,7 @@ #pragma once +#include "FailureCode.h" #include "LogHandler.h" #include @@ -24,15 +25,20 @@ namespace governikus class TlsChecker { private: - [[nodiscard]] static bool isValidKeyLength(int pKeyLength, QSsl::KeyAlgorithm pKeyAlgorithm, bool pIsEphemeral); + static const std::function cDefaultFuncMinKeySize; + + [[nodiscard]] static bool isValidKeyLength(int pKeyLength, QSsl::KeyAlgorithm pKeyAlgorithm, int pMinKeySize); TlsChecker() = delete; ~TlsChecker() = delete; public: static void logSslConfig(const QSslConfiguration& pCfg, const MessageLogger& pLogger); + +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) [[nodiscard]] static QString toString(QSsl::SslProtocol pProtocol); [[nodiscard]] static QString toString(QSsl::KeyAlgorithm pKeyAlgorithm); +#endif [[nodiscard]] static QStringList getFatalErrors(const QList& pErrors); [[nodiscard]] static bool containsFatalError(const QSharedPointer& pReply, const QList& pErrors); @@ -48,17 +54,17 @@ class TlsChecker /*! * Checks, whether the key length of the SSL certificate is of sufficient length. */ - [[nodiscard]] static bool hasValidCertificateKeyLength(const QSslCertificate& pCertificate); + [[nodiscard]] static bool hasValidCertificateKeyLength(const QSslCertificate& pCertificate, + const std::function& pFuncMinKeySize = cDefaultFuncMinKeySize); /*! * Checks, whether the length of the ephemeral key is of sufficient length. */ - [[nodiscard]] static bool hasValidEphemeralKeyLength(const QSslKey& pEphemeralServerKey); + [[nodiscard]] static bool hasValidEphemeralKeyLength(const QSslKey& pEphemeralServerKey, + const std::function& pFuncMinKeySize = cDefaultFuncMinKeySize); + [[nodiscard]] static FailureCode::FailureInfoMap getEphemeralKeyInfoMap(const QSslKey& pEphemeralServerKey); - /*! - * This method is only needed until QSslCertificate provides its own method issuerDisplayName in Qt 5.12 - */ - [[nodiscard]] static QString getCertificateIssuerName(const QSslCertificate& pCertificate); + [[nodiscard]] static QSslCertificate getRootCertificate(const QList& pCertificates); }; } // namespace governikus diff --git a/src/network/UrlUtil.cpp b/src/network/UrlUtil.cpp index e8822244e..f40a45949 100644 --- a/src/network/UrlUtil.cpp +++ b/src/network/UrlUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "UrlUtil.h" @@ -15,6 +15,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) + using namespace governikus; @@ -51,65 +52,6 @@ bool UrlUtil::isMatchingSameOriginPolicy(const QUrl& pUrl1, const QUrl& pUrl2) } -QString UrlUtil::removePrefix(QString pStr) -{ - return pStr.replace(QRegularExpression(QStringLiteral("(.*)#")), QLatin1String("")); -} - - -QString UrlUtil::getSuffix(ECardApiResult::Minor pMinor) -{ - return removePrefix(ECardApiResult::getMinorString(pMinor)); -} - - -QUrl UrlUtil::addMajorMinor(const QUrl& pOriginUrl, const GlobalStatus& pStatus) -{ - QUrlQuery q; - q.setQuery(pOriginUrl.query()); - - const ECardApiResult::Major majorEnumVal = pStatus.isError() ? ECardApiResult::Major::Error : ECardApiResult::Major::Ok; - QString major = removePrefix(ECardApiResult::getMajorString(majorEnumVal)); - q.addQueryItem(QStringLiteral("ResultMajor"), major); - - if (pStatus.isError()) - { - QString minor; - - switch (pStatus.getStatusCode()) - { - case GlobalStatus::Code::Paos_Error_AL_Communication_Error: - minor = getSuffix(ECardApiResult::Minor::AL_Communication_Error); - break; - - case GlobalStatus::Code::Paos_Error_DP_Trusted_Channel_Establishment_Failed: - minor = getSuffix(ECardApiResult::Minor::DP_Trusted_Channel_Establishment_Failed); - break; - - case GlobalStatus::Code::Paos_Error_SAL_Cancellation_by_User: - minor = getSuffix(ECardApiResult::Minor::SAL_Cancellation_by_User); - break; - - default: - if (pStatus.isOriginServer()) - { - minor = QStringLiteral("serverError"); - } - else - { - minor = QStringLiteral("clientError"); - } - break; - } - q.addQueryItem(QStringLiteral("ResultMinor"), minor); - } - - QUrl adaptedUrl(pOriginUrl); - adaptedUrl.setQuery(q); - return adaptedUrl; -} - - void UrlUtil::setHiddenSettings(const QUrlQuery& pUrl) { const auto queryUseTestUri = QLatin1String("useTestUri"); @@ -125,7 +67,7 @@ void UrlUtil::setHiddenSettings(const QUrlQuery& pUrl) { const auto value = pUrl.queryItemValue(queryEnableSimulator); const bool enableSimulator = QVariant(value).toBool(); - Env::getSingleton()->getGeneralSettings().setSimulatorEnabled(enableSimulator); + Env::getSingleton()->getSimulatorSettings().setEnabled(enableSimulator); } } @@ -133,12 +75,12 @@ void UrlUtil::setHiddenSettings(const QUrlQuery& pUrl) QPair UrlUtil::getRequest(const QUrlQuery& pUrl) { const auto queryItems = pUrl.queryItems(); - for (const auto& item : queryItems) + for (const auto& [key, value] : queryItems) { - const auto type = Enum::fromString(item.first.toUpper(), UrlQueryRequest::UNKNOWN); + const auto type = Enum::fromString(key.toUpper(), UrlQueryRequest::UNKNOWN); if (type != UrlQueryRequest::UNKNOWN) { - return {type, item.second}; + return {type, value}; } } diff --git a/src/network/UrlUtil.h b/src/network/UrlUtil.h index 943432a53..737e4cbfc 100644 --- a/src/network/UrlUtil.h +++ b/src/network/UrlUtil.h @@ -1,21 +1,16 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Helper to convert \ref Result to Redirect-Result-String and some other URL stuff. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "ECardApiResult.h" - #include "EnumHelper.h" #include #include #include + namespace governikus { @@ -33,9 +28,6 @@ defineEnumType(UrlQueryRequest, class UrlUtil { private: - static inline QString removePrefix(QString pStr); - static inline QString getSuffix(ECardApiResult::Minor pMinor); - UrlUtil() = delete; ~UrlUtil() = delete; @@ -50,11 +42,6 @@ class UrlUtil */ static bool isMatchingSameOriginPolicy(const QUrl& pUrl1, const QUrl& pUrl2); - /*! - * Append result to URL. - */ - static QUrl addMajorMinor(const QUrl& pUrl, const GlobalStatus& pStatus); - static void setHiddenSettings(const QUrlQuery& pUrl); static QPair getRequest(const QUrlQuery& pUrl); diff --git a/src/network/WifiInfo.cpp b/src/network/WifiInfo.cpp index 8152d7ee4..f5b240050 100644 --- a/src/network/WifiInfo.cpp +++ b/src/network/WifiInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WifiInfo.h" diff --git a/src/network/WifiInfo.h b/src/network/WifiInfo.h index f3f140b1b..9cd07d3df 100644 --- a/src/network/WifiInfo.h +++ b/src/network/WifiInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/network/WifiInfo.java b/src/network/WifiInfo.java index 3cf52b791..2f358fe6c 100644 --- a/src/network/WifiInfo.java +++ b/src/network/WifiInfo.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/network/WifiInfo_android.cpp b/src/network/WifiInfo_android.cpp index e05acb85e..9c6d7b454 100644 --- a/src/network/WifiInfo_android.cpp +++ b/src/network/WifiInfo_android.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WifiInfo.h" diff --git a/src/network/WifiInfo_generic.cpp b/src/network/WifiInfo_generic.cpp index 7ca2c5bc2..66c02b408 100644 --- a/src/network/WifiInfo_generic.cpp +++ b/src/network/WifiInfo_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "WifiInfo.h" diff --git a/src/network/WifiInfo_ios.mm b/src/network/WifiInfo_ios.mm index 1a58f88e9..a13eb1e08 100644 --- a/src/network/WifiInfo_ios.mm +++ b/src/network/WifiInfo_ios.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "WifiInfo.h" diff --git a/src/secure_storage/SecureStorage.cpp b/src/secure_storage/SecureStorage.cpp index c853cdca0..9440ae54f 100644 --- a/src/secure_storage/SecureStorage.cpp +++ b/src/secure_storage/SecureStorage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ @@ -43,8 +43,7 @@ CONFIG_NAME(CONFIGURATION_GROUP_NAME_TLS_CONFIGURATION_PSK, "tlsSettingsPsk") CONFIG_NAME(CONFIGURATION_GROUP_NAME_TLS_CONFIGURATION_REMOTE_IFD, "tlsSettingsRemoteIfd") CONFIG_NAME(CONFIGURATION_GROUP_NAME_TLS_CONFIGURATION_REMOTE_IFD_PAIRING, "tlsSettingsRemoteIfdPairing") CONFIG_NAME(CONFIGURATION_GROUP_NAME_TLS_CONFIGURATION_LOCAL_IFD, "tlsSettingsLocalIfd") -CONFIG_NAME(CONFIGURATION_GROUP_NAME_MIN_STATIC_KEY_SIZES, "minStaticKeySizes") -CONFIG_NAME(CONFIGURATION_GROUP_NAME_MIN_EPHEMERAL_KEY_SIZES, "minEphemeralKeySizes") +CONFIG_NAME(CONFIGURATION_GROUP_NAME_MIN_KEY_SIZES, "minKeySizes") CONFIG_NAME(CONFIGURATION_GROUP_NAME_SELF_AUTHENTICATION, "selfAuthentication") CONFIG_NAME(CONFIGURATION_NAME_SELF_AUTHENTICATION_URL, "url") @@ -72,6 +71,10 @@ CONFIG_NAME(CONFIGURATION_NAME_LOCAL_IFD_MIN_VERSION, "minVersion") CONFIG_NAME(CONFIGURATION_NAME_LOCAL_IFD_ALLOWED_CERTIFICATE_HASHES, "allowedCertificateHashes") CONFIG_NAME(CONFIGURATION_NAME_LOCAL_IFD_MIN_PSK_SIZE, "minPskSize") +CONFIG_NAME(CONFIGURATION_GROUP_NAME_SIZES_IFD, "sizesIfd") +CONFIG_NAME(CONFIGURATION_NAME_SIZES_IFD_CREATE, "createRsa") +CONFIG_NAME(CONFIGURATION_NAME_SIZES_IFD_MIN, "min") + } // namespace defineSingleton(SecureStorage) @@ -100,8 +103,9 @@ SecureStorage::SecureStorage() , mTlsConfigRemoteIfd() , mTlsConfigRemoteIfdPairing() , mTlsConfigLocalIfd() - , mMinStaticKeySizes() - , mMinEphemeralKeySizes() + , mMinKeySizes() + , mMinKeySizesIfd() + , mCreateKeySizeIfd() { load(); } @@ -120,7 +124,7 @@ QString SecureStorage::getDeveloperConfig() const QString SecureStorage::getCustomConfig() const { - const auto& path = FileDestination::getPath(QStringLiteral("config.json")); + const auto& path = getCustomConfigPath(); if (QFile(path).exists()) { return path; @@ -130,6 +134,12 @@ QString SecureStorage::getCustomConfig() const } +QString SecureStorage::getCustomConfigPath() const +{ + return FileDestination::getPath(QStringLiteral("config.json")); +} + + QString SecureStorage::getEmbeddedConfig() const { return QStringLiteral(":/config.json"); @@ -178,7 +188,7 @@ QJsonObject SecureStorage::loadFile(const QStringList& pFiles) const void SecureStorage::load() { const QStringList files({getDeveloperConfig(), getCustomConfig(), getEmbeddedConfig()}); - qDebug() << files; + qCDebug(securestorage) << "Try locations:" << files; const auto& config = loadFile(files); if (config.isEmpty()) { @@ -235,8 +245,11 @@ void SecureStorage::load() mTlsConfigLocalIfd.load(tlsLocalIfd.toObject()); } - mMinStaticKeySizes = readKeySizes(config, CONFIGURATION_GROUP_NAME_MIN_STATIC_KEY_SIZES()); - mMinEphemeralKeySizes = readKeySizes(config, CONFIGURATION_GROUP_NAME_MIN_EPHEMERAL_KEY_SIZES()); + mMinKeySizes = readKeySizes(config, CONFIGURATION_GROUP_NAME_MIN_KEY_SIZES()); + + const QJsonObject obj = config.value(CONFIGURATION_GROUP_NAME_SIZES_IFD()).toObject(); + mMinKeySizesIfd = readKeySizes(obj, CONFIGURATION_NAME_SIZES_IFD_MIN()); + mCreateKeySizeIfd = obj.value(CONFIGURATION_NAME_SIZES_IFD_CREATE()).toInt(); mSelfAuthenticationUrl = readGroup(config, CONFIGURATION_GROUP_NAME_SELF_AUTHENTICATION(), CONFIGURATION_NAME_SELF_AUTHENTICATION_URL()); mSelfAuthenticationTestUrl = readGroup(config, CONFIGURATION_GROUP_NAME_SELF_AUTHENTICATION(), CONFIGURATION_NAME_SELF_AUTHENTICATION_TEST_URL()); @@ -279,8 +292,7 @@ bool SecureStorage::isValid() const && mTlsConfigRemoteIfd.isValid() && mTlsConfigRemoteIfdPairing.isValid() && mTlsConfigLocalIfd.isValid() - && !mMinStaticKeySizes.isEmpty() - && !mMinEphemeralKeySizes.isEmpty() + && !mMinKeySizes.isEmpty() && mLocalIfdMinPskSize > 0; } @@ -335,7 +347,7 @@ const QByteArrayList& SecureStorage::getCVRootCertificates(bool pProductive) con } -const QVector& SecureStorage::getUpdateCertificates() const +const QList& SecureStorage::getUpdateCertificates() const { return mUpdateCertificates; } @@ -431,23 +443,29 @@ int SecureStorage::getLocalIfdMinPskSize() const } -int SecureStorage::getMinimumStaticKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const +int SecureStorage::getMinimumKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const { - if (!mMinStaticKeySizes.contains(pKeyAlgorithm)) + if (!mMinKeySizes.contains(pKeyAlgorithm)) { - qCWarning(securestorage) << "No minimum ephemeral key size specified, returning default"; + qCWarning(securestorage) << "No minimum key size specified, returning default"; } - return mMinStaticKeySizes.value(pKeyAlgorithm, 0); + return mMinKeySizes.value(pKeyAlgorithm, 0); } -int SecureStorage::getMinimumEphemeralKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const +int SecureStorage::getMinimumIfdKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const { - if (!mMinEphemeralKeySizes.contains(pKeyAlgorithm)) + if (!mMinKeySizesIfd.contains(pKeyAlgorithm)) { - qCWarning(securestorage) << "No minimum ephemeral key size specified, returning default"; + qCWarning(securestorage) << "No minimum key size specified, returning default"; } - return mMinEphemeralKeySizes.value(pKeyAlgorithm, 0); + return mMinKeySizesIfd.value(pKeyAlgorithm, 0); +} + + +int SecureStorage::getIfdCreateSize() const +{ + return mCreateKeySizeIfd; } diff --git a/src/secure_storage/SecureStorage.h b/src/secure_storage/SecureStorage.h index 2f2cb87d5..94407a710 100644 --- a/src/secure_storage/SecureStorage.h +++ b/src/secure_storage/SecureStorage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include #include -#include class test_SecureStorage; @@ -41,7 +41,7 @@ class SecureStorage QString mVendor; QByteArrayList mCvcas; QByteArrayList mCvcasTest; - QVector mUpdateCertificates; + QList mUpdateCertificates; QUrl mSelfAuthenticationUrl; QUrl mSelfAuthenticationTestUrl; QUrl mUpdateServerBaseUrl; @@ -62,8 +62,9 @@ class SecureStorage TlsConfiguration mTlsConfigRemoteIfd; TlsConfiguration mTlsConfigRemoteIfdPairing; TlsConfiguration mTlsConfigLocalIfd; - QMap mMinStaticKeySizes; - QMap mMinEphemeralKeySizes; + QMap mMinKeySizes; + QMap mMinKeySizesIfd; + int mCreateKeySizeIfd; [[nodiscard]] QJsonArray readJsonArray(const QJsonObject& pConfig, const QLatin1String pName) const; [[nodiscard]] QString readGroup(const QJsonObject& pConfig, const QLatin1String pGroup, const QLatin1String pName) const; @@ -89,7 +90,7 @@ class SecureStorage [[nodiscard]] const QString& getVendor() const; [[nodiscard]] const QByteArrayList& getCVRootCertificates(bool pProductive) const; - [[nodiscard]] const QVector& getUpdateCertificates() const; + [[nodiscard]] const QList& getUpdateCertificates() const; [[nodiscard]] const QUrl& getSelfAuthenticationUrl(bool pTest = false) const; [[nodiscard]] const QUrl& getUpdateServerBaseUrl() const; [[nodiscard]] const QUrl& getWhitelistServerBaseUrl() const; @@ -105,12 +106,14 @@ class SecureStorage [[nodiscard]] const TlsConfiguration& getTlsConfig(TlsSuite pTlsSuite = TlsSuite::DEFAULT) const; [[nodiscard]] const TlsConfiguration& getTlsConfigRemoteIfd(TlsSuite pTlsSuite = TlsSuite::DEFAULT) const; [[nodiscard]] const TlsConfiguration& getTlsConfigLocalIfd() const; - [[nodiscard]] int getMinimumStaticKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const; - [[nodiscard]] int getMinimumEphemeralKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const; + [[nodiscard]] int getMinimumKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const; + [[nodiscard]] int getMinimumIfdKeySize(QSsl::KeyAlgorithm pKeyAlgorithm) const; + [[nodiscard]] int getIfdCreateSize() const; [[nodiscard]] bool isValid() const; [[nodiscard]] QString getDeveloperConfig() const; [[nodiscard]] QString getCustomConfig() const; + [[nodiscard]] QString getCustomConfigPath() const; [[nodiscard]] QString getEmbeddedConfig() const; }; diff --git a/src/secure_storage/TlsConfiguration.cpp b/src/secure_storage/TlsConfiguration.cpp index cd44f3d42..b715d261a 100644 --- a/src/secure_storage/TlsConfiguration.cpp +++ b/src/secure_storage/TlsConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "TlsConfiguration.h" @@ -117,7 +117,7 @@ QList TlsConfiguration::getCiphers() const } -QVector TlsConfiguration::getEllipticCurves() const +QList TlsConfiguration::getEllipticCurves() const { return mConfiguration.ellipticCurves(); } diff --git a/src/secure_storage/TlsConfiguration.h b/src/secure_storage/TlsConfiguration.h index aac2399e5..a7f0c1b10 100644 --- a/src/secure_storage/TlsConfiguration.h +++ b/src/secure_storage/TlsConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,7 +15,6 @@ #include #include #include -#include class test_TlsConfiguration; @@ -36,7 +35,7 @@ class SslCipherList class SslEllipticCurveVector - : public QVector + : public QList { public: SslEllipticCurveVector& operator +=(const QString& pEllipticCurveName); @@ -67,7 +66,7 @@ class TlsConfiguration final [[nodiscard]] QSsl::SslProtocol getProtocolVersion() const; [[nodiscard]] bool getOcspStapling() const; [[nodiscard]] QList getCiphers() const; - [[nodiscard]] QVector getEllipticCurves() const; + [[nodiscard]] QList getEllipticCurves() const; [[nodiscard]] QByteArrayList getSignatureAlgorithms() const; [[nodiscard]] const QSslConfiguration& getConfiguration() const; }; diff --git a/src/services/AppUpdateData.cpp b/src/services/AppUpdateData.cpp index e79252d34..783f15517 100644 --- a/src/services/AppUpdateData.cpp +++ b/src/services/AppUpdateData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "AppUpdateData.h" diff --git a/src/services/AppUpdateData.h b/src/services/AppUpdateData.h index 8846da7bc..93c9ad611 100644 --- a/src/services/AppUpdateData.h +++ b/src/services/AppUpdateData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/services/AppUpdater.cpp b/src/services/AppUpdater.cpp index 111f3c4de..2989264f7 100644 --- a/src/services/AppUpdater.cpp +++ b/src/services/AppUpdater.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "AppUpdater.h" @@ -21,8 +21,7 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(appupdate) AppUpdater::AppUpdater() - : mForceUpdate(false) - , mAppUpdateJsonUrl() + : mAppUpdateJsonUrl() , mAppUpdateData() , mDownloadPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/')) , mDownloadInProgress(false) @@ -33,9 +32,8 @@ AppUpdater::AppUpdater() } -bool AppUpdater::checkAppUpdate(bool pForceUpdate) +bool AppUpdater::checkAppUpdate() { - mForceUpdate = pForceUpdate; mAppUpdateData = AppUpdateData(); return download(mAppUpdateJsonUrl); } @@ -120,13 +118,6 @@ const AppUpdateData& AppUpdater::getUpdateData() const } -void AppUpdater::skipVersion(const QString& pVersion) const -{ - qCInfo(appupdate) << "Skip application update:" << pVersion; - Env::getSingleton()->getGeneralSettings().skipVersion(pVersion); -} - - #ifndef QT_NO_DEBUG QString AppUpdater::getDownloadPath() const { @@ -195,18 +186,9 @@ void AppUpdater::handleVersionInfoDownloadFinished(const QByteArray& pData) if (VersionNumber(version) > VersionNumber::getApplicationVersion()) { - if (!mForceUpdate && version == Env::getSingleton()->getGeneralSettings().getSkipVersion()) - { - qCInfo(appupdate) << "Version will be skipped:" << version; - Q_EMIT fireAppcastCheckFinished(false, GlobalStatus::Code::No_Error); - } - else - { - mForceUpdate = false; - qCInfo(appupdate) << "Found new version:" << version << ", greater than old version" << QCoreApplication::applicationVersion(); - Env::getSingleton()->download(mAppUpdateData.getNotesUrl()); - return; - } + qCInfo(appupdate) << "Found new version:" << version << ", greater than old version" << QCoreApplication::applicationVersion(); + Env::getSingleton()->download(mAppUpdateData.getNotesUrl()); + return; } else { diff --git a/src/services/AppUpdater.h b/src/services/AppUpdater.h index bdb900ad4..4b613f925 100644 --- a/src/services/AppUpdater.h +++ b/src/services/AppUpdater.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -23,7 +23,6 @@ class AppUpdater friend class ::test_AppUpdatr; private: - bool mForceUpdate; QUrl mAppUpdateJsonUrl; AppUpdateData mAppUpdateData; QString mDownloadPath; @@ -41,9 +40,8 @@ class AppUpdater public: bool abortDownload() const; bool downloadUpdate(); - bool checkAppUpdate(bool pForceUpdate = false); + bool checkAppUpdate(); [[nodiscard]] const AppUpdateData& getUpdateData() const; - void skipVersion(const QString& pVersion) const; #ifndef QT_NO_DEBUG [[nodiscard]] QString getDownloadPath() const; diff --git a/src/services/Service.cpp b/src/services/Service.cpp index e6eaf4b96..51deb112c 100644 --- a/src/services/Service.cpp +++ b/src/services/Service.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "Service.h" @@ -7,6 +7,7 @@ #include "AppSettings.h" #include "AppUpdater.h" #include "ProviderConfiguration.h" +#include "SecureStorage.h" #if defined(Q_OS_WIN) || defined(Q_OS_MACOS) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #include "ReaderConfiguration.h" @@ -24,13 +25,12 @@ void Service::doAppUpdate(UpdateType pType, bool pForceUpdate) switch (pType) { case UpdateType::APPCAST: - mExplicitSuccessMessage = pForceUpdate; if (Env::getSingleton()->getGeneralSettings().isAutoUpdateAvailable()) { mTimer.start(mOneDayInMs); if (pForceUpdate || Env::getSingleton()->getGeneralSettings().isAutoUpdateCheck()) { - Q_UNUSED(Env::getSingleton()->checkAppUpdate(pForceUpdate)) + Q_UNUSED(Env::getSingleton()->checkAppUpdate()) break; } } @@ -77,10 +77,7 @@ void Service::onReaderUpdateFinished() void Service::onAppcastFinished(bool pUpdateAvailable, const GlobalStatus& pError) { - if (pUpdateAvailable || pError.isError() || mExplicitSuccessMessage) - { - Q_EMIT fireAppcastFinished(pUpdateAvailable, pError); - } + Q_EMIT fireAppcastFinished(pUpdateAvailable); if (pUpdateAvailable && !pError.isError()) { @@ -98,7 +95,6 @@ void Service::onAppcastFinished(bool pUpdateAvailable, const GlobalStatus& pErro Service::Service() : mTimer(this) , mUpdateScheduled(true) - , mExplicitSuccessMessage(true) { connect(&mTimer, &QTimer::timeout, this, &Service::onTimedUpdateTriggered); connect(Env::getSingleton(), &ProviderConfiguration::fireUpdated, this, &Service::onProviderUpdateFinished); @@ -127,8 +123,18 @@ bool Service::isUpdateScheduled() const } -void Service::runUpdateIfNeeded() +void Service::runUpdateIfNeeded(bool pSkipProxy) { + if (pSkipProxy) + { + const auto& appcastUrl = Env::getSingleton()->getAppcastUpdateUrl(); + const auto& proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(appcastUrl)); + if (!proxies.isEmpty() && proxies.first().type() != QNetworkProxy::NoProxy) + { + return; + } + } + if (mUpdateScheduled) { mUpdateScheduled = false; diff --git a/src/services/Service.h b/src/services/Service.h index 484f83627..963bd54b4 100644 --- a/src/services/Service.h +++ b/src/services/Service.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -25,7 +25,6 @@ class Service QTimer mTimer; bool mUpdateScheduled; - bool mExplicitSuccessMessage; const int mOneDayInMs = 1000 * 60 * 60 * 24; Service(); @@ -41,11 +40,11 @@ class Service public: void updateAppcast(); [[nodiscard]] bool isUpdateScheduled() const; - Q_INVOKABLE void runUpdateIfNeeded(); + void runUpdateIfNeeded(bool pSkipProxy = false); [[nodiscard]] const AppUpdateData& getUpdateData() const; Q_SIGNALS: - void fireAppcastFinished(bool pUpdateAvailable, const GlobalStatus& pError); + void fireAppcastFinished(bool pUpdateAvailable); void fireUpdateScheduled(); }; diff --git a/src/settings/AbstractSettings.cpp b/src/settings/AbstractSettings.cpp index 5a1576b3a..6ea771f87 100644 --- a/src/settings/AbstractSettings.cpp +++ b/src/settings/AbstractSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ @@ -21,6 +21,20 @@ AbstractSettings::AbstractSettings() } +QString AbstractSettings::getOrganization() +{ +#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) + const auto& organization = QCoreApplication::organizationDomain(); + +#else + const auto& organization = QCoreApplication::organizationName(); + +#endif + + return organization.isEmpty() ? QCoreApplication::applicationName() : organization; +} + + void AbstractSettings::save(const QSharedPointer& pSettings) { pSettings->sync(); @@ -28,10 +42,10 @@ void AbstractSettings::save(const QSharedPointer& pSettings) } -QSharedPointer AbstractSettings::getStore(const QString& pFilename, QSettings::Format pFormat) +QSharedPointer AbstractSettings::getStore(QSettings::Scope pScope, const QString& pFilename, QSettings::Format pFormat) { #ifndef QT_NO_DEBUG - if (QCoreApplication::applicationName().startsWith(QLatin1String("Test"))) + if (QCoreApplication::applicationName().startsWith(QLatin1StringView("Test"))) { if (mTestDir.isNull()) { @@ -39,18 +53,18 @@ QSharedPointer AbstractSettings::getStore(const QString& pFilename, Q Q_ASSERT(mTestDir->isValid()); } QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, mTestDir->path()); - return QSharedPointer::create(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QStringLiteral("AusweisApp2")); + return QSharedPointer::create(QSettings::IniFormat, QSettings::UserScope, getOrganization(), QCoreApplication::applicationName()); } #endif Q_ASSERT(pFilename.isEmpty() == (pFormat == QSettings::InvalidFormat)); -#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) - const auto& organization = QCoreApplication::organizationDomain(); - -#else - const auto& organization = QCoreApplication::organizationName(); + return pFilename.isEmpty() + ? QSharedPointer::create(pScope, getOrganization(), QStringLiteral("AusweisApp2")) + : QSharedPointer::create(pFilename, pFormat); +} -#endif - return pFilename.isEmpty() ? QSharedPointer::create(organization, QStringLiteral("AusweisApp2")) : QSharedPointer::create(pFilename, pFormat); +QSharedPointer AbstractSettings::getStore(const QString& pFilename, QSettings::Format pFormat) +{ + return getStore(QSettings::Scope::UserScope, pFilename, pFormat); } diff --git a/src/settings/AbstractSettings.h b/src/settings/AbstractSettings.h index 13fd34c05..c588216ad 100644 --- a/src/settings/AbstractSettings.h +++ b/src/settings/AbstractSettings.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -14,8 +14,8 @@ #endif #define SETTINGS_NAME(_name, _key)\ - QString _name(){\ - return QStringLiteral(_key);\ + QAnyStringView _name(){\ + return QAnyStringView(_key);\ } namespace governikus @@ -26,6 +26,9 @@ class AbstractSettings { Q_OBJECT + private: + static QString getOrganization(); + protected: AbstractSettings(); ~AbstractSettings() override = default; @@ -37,6 +40,7 @@ class AbstractSettings static QSharedPointer mTestDir; #endif + static QSharedPointer getStore(QSettings::Scope pScope, const QString& pFilename = QString(), QSettings::Format pFormat = QSettings::InvalidFormat); static QSharedPointer getStore(const QString& pFilename = QString(), QSettings::Format pFormat = QSettings::InvalidFormat); Q_SIGNALS: diff --git a/src/settings/AppSettings.cpp b/src/settings/AppSettings.cpp index 328b46631..b52878e44 100644 --- a/src/settings/AppSettings.cpp +++ b/src/settings/AppSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AppSettings.h" @@ -7,11 +7,13 @@ using namespace governikus; + AppSettings::AppSettings() : QObject() , mGeneralSettings() , mPreVerificationSettings() , mRemoteReaderSettings() + , mSimulatorSettings() { } @@ -32,3 +34,9 @@ RemoteServiceSettings& AppSettings::getRemoteServiceSettings() { return mRemoteReaderSettings; } + + +SimulatorSettings& AppSettings::getSimulatorSettings() +{ + return mSimulatorSettings; +} diff --git a/src/settings/AppSettings.h b/src/settings/AppSettings.h index 4c10c4273..11ad4ede4 100644 --- a/src/settings/AppSettings.h +++ b/src/settings/AppSettings.h @@ -1,27 +1,21 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Contains the definition of the AppSettings class. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once + #include "Env.h" #include "GeneralSettings.h" #include "PreVerificationSettings.h" #include "RemoteServiceSettings.h" +#include "SimulatorSettings.h" #include namespace governikus { - -/*! - * \brief Represents application settings. - */ class AppSettings : public QObject , private Env::ThreadSafe @@ -36,11 +30,13 @@ class AppSettings GeneralSettings mGeneralSettings; PreVerificationSettings mPreVerificationSettings; RemoteServiceSettings mRemoteReaderSettings; + SimulatorSettings mSimulatorSettings; public: - virtual GeneralSettings& getGeneralSettings(); - virtual PreVerificationSettings& getPreVerificationSettings(); - virtual RemoteServiceSettings& getRemoteServiceSettings(); + [[nodiscard]] GeneralSettings& getGeneralSettings(); + [[nodiscard]] PreVerificationSettings& getPreVerificationSettings(); + [[nodiscard]] RemoteServiceSettings& getRemoteServiceSettings(); + [[nodiscard]] SimulatorSettings& getSimulatorSettings(); }; diff --git a/src/settings/AutoStart.cpp b/src/settings/AutoStart.cpp index b0eeda7c3..febab47e1 100644 --- a/src/settings/AutoStart.cpp +++ b/src/settings/AutoStart.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "AutoStart.h" diff --git a/src/settings/AutoStart.h b/src/settings/AutoStart.h index c785098e7..762f0429b 100644 --- a/src/settings/AutoStart.h +++ b/src/settings/AutoStart.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/settings/AutoStart_generic.cpp b/src/settings/AutoStart_generic.cpp index ad507961d..4e55e3e6c 100644 --- a/src/settings/AutoStart_generic.cpp +++ b/src/settings/AutoStart_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AutoStart.h" diff --git a/src/settings/AutoStart_osx.mm b/src/settings/AutoStart_osx.mm index ca25424e2..d524c6397 100644 --- a/src/settings/AutoStart_osx.mm +++ b/src/settings/AutoStart_osx.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AutoStart.h" @@ -58,7 +58,11 @@ bool AutoStart::setInternal(bool pEnabled) { - if (SMLoginItemSetEnabled(static_cast(autostartBundleIdentifier), pEnabled)) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + const bool callSucceeded = SMLoginItemSetEnabled(static_cast(autostartBundleIdentifier), pEnabled); + QT_WARNING_POP + if (callSucceeded) { qCDebug(settings) << "Setting autostart to" << pEnabled << "succeeded"; return true; diff --git a/src/settings/AutoStart_win.cpp b/src/settings/AutoStart_win.cpp index bac21c46f..d43611a79 100644 --- a/src/settings/AutoStart_win.cpp +++ b/src/settings/AutoStart_win.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AutoStart.h" diff --git a/src/settings/Backup.h b/src/settings/Backup.h index b3beecc1d..ac1444dcb 100644 --- a/src/settings/Backup.h +++ b/src/settings/Backup.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/settings/Backup_generic.cpp b/src/settings/Backup_generic.cpp index 3c0714fed..34d3f9278 100644 --- a/src/settings/Backup_generic.cpp +++ b/src/settings/Backup_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "Backup.h" diff --git a/src/settings/Backup_ios_osx.mm b/src/settings/Backup_ios_osx.mm index a5fd2e347..d2bffef22 100644 --- a/src/settings/Backup_ios_osx.mm +++ b/src/settings/Backup_ios_osx.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "Backup.h" diff --git a/src/settings/GeneralSettings.cpp b/src/settings/GeneralSettings.cpp index 228356dd7..b6779f813 100644 --- a/src/settings/GeneralSettings.cpp +++ b/src/settings/GeneralSettings.cpp @@ -1,9 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Contains the method definitions of the GeneralSettings class. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "GeneralSettings.h" @@ -22,27 +18,27 @@ using namespace governikus; + Q_DECLARE_LOGGING_CATEGORY(settings) + namespace { SETTINGS_NAME(SETTINGS_NAME_PERSISTENT_SETTINGS_VERSION, "persistentSettingsVersion") -SETTINGS_NAME(SETTINGS_NAME_SKIP_VERSION, "skipVersion") SETTINGS_NAME(SETTINGS_NAME_AUTO_CLOSE_WINDOW, "autoCloseWindow") +SETTINGS_NAME(SETTINGS_NAME_AUTO_REDIRECT, "autoRedirect") SETTINGS_NAME(SETTINGS_NAME_UI_STARTUP_MODULE, "uiStartupModule") SETTINGS_NAME(SETTINGS_NAME_REMIND_USER_TO_CLOSE, "remindToClose") SETTINGS_NAME(SETTINGS_NAME_TRANSPORT_PIN_REMINDER, "transportPinReminder") SETTINGS_NAME(SETTINGS_NAME_DEVELOPER_OPTIONS, "developerOptions") SETTINGS_NAME(SETTINGS_NAME_DEVELOPER_MODE, "developerMode") SETTINGS_NAME(SETTINGS_NAME_USE_SELF_AUTH_TEST_URI, "selfauthTestUri") -SETTINGS_NAME(SETTINGS_NAME_SIMULATOR, "simulator") SETTINGS_NAME(SETTINGS_NAME_LANGUAGE, "language") SETTINGS_NAME(SETTINGS_NAME_DEVICE_SURVEY_PENDING, "deviceSurveyPending") SETTINGS_NAME(SETTINGS_NAME_LAST_READER_PLUGIN_TYPE, "lastTechnology") SETTINGS_NAME(SETTINGS_NAME_IN_APP_NOTIFICATIONS, "showInAppNotifications") SETTINGS_NAME(SETTINGS_NAME_REQUEST_STORE_FEEDBACK, "requestStoreFeedback") SETTINGS_NAME(SETTINGS_NAME_AUTO, "autoUpdateCheck") -SETTINGS_NAME(SETTINGS_NAME_KEYLESS_PASSWORD, "keylessPassword") SETTINGS_NAME(SETTINGS_NAME_VISUAL_PRIVACY, "visualPrivacy") SETTINGS_NAME(SETTINGS_NAME_SHUFFLE_SCREEN_KEYBOARD, "shuffleScreenKeyboard") SETTINGS_NAME(SETTINGS_NAME_CUSTOM_PROXY_HOST, "customProxyHost") @@ -51,6 +47,7 @@ SETTINGS_NAME(SETTINGS_NAME_CUSTOM_PROXY_TYPE, "customProxyType") SETTINGS_NAME(SETTINGS_NAME_USE_CUSTOM_PROXY, "useCustomProxy") SETTINGS_NAME(SETTINGS_NAME_DARK_MODE, "darkMode") SETTINGS_NAME(SETTINGS_NAME_USE_SYSTEM_FONT, "useSystemFont") +SETTINGS_NAME(SETTINGS_NAME_ANIMATIONS, "animations") SETTINGS_NAME(SETTINGS_NAME_ENABLE_CAN_ALLOWED, "enableCanAllowed") SETTINGS_NAME(SETTINGS_NAME_SKIP_RIGHTS_ON_CAN_ALLOWED, "skipRightsOnCanAllowed") SETTINGS_NAME(SETTINGS_NAME_IFD_SERVICE_TOKEN, "ifdServiceToken") @@ -70,10 +67,10 @@ GeneralSettings::GeneralSettings(QSharedPointer pStore) , mIsNewAppVersion(false) { // With 2.0.0 the option to change the screen orientation was removed - mStore->remove(QStringLiteral("screenOrientation")); + mStore->remove(QAnyStringView("screenOrientation")); // With 2.0.0 the history was removed - const auto& history = QStringLiteral("history"); + const QAnyStringView history("history"); if (mStore->childGroups().contains(history)) { mStore->beginGroup(history); @@ -81,6 +78,12 @@ GeneralSettings::GeneralSettings(QSharedPointer pStore) mStore->endGroup(); } + // With 2.1.0 the skipVersion was removed + mStore->remove(QAnyStringView("skipVersion")); + + // With 2.2.0 the keylessPassword was removed + mStore->remove(QAnyStringView("keylessPassword")); + const bool isNewInstallation = getPersistentSettingsVersion().isEmpty(); if (isNewInstallation) { @@ -184,36 +187,40 @@ QString GeneralSettings::getPersistentSettingsVersion() const } -QString GeneralSettings::getSkipVersion() const +bool GeneralSettings::isNewAppVersion() const { - return mStore->value(SETTINGS_NAME_SKIP_VERSION(), QString()).toString(); + return mIsNewAppVersion; } -void GeneralSettings::skipVersion(const QString& pVersion) +bool GeneralSettings::isAutoCloseWindowAfterAuthentication() const { - mStore->setValue(SETTINGS_NAME_SKIP_VERSION(), pVersion); - save(mStore); + return mStore->value(SETTINGS_NAME_AUTO_CLOSE_WINDOW(), true).toBool(); } -bool GeneralSettings::isNewAppVersion() const +void GeneralSettings::setAutoCloseWindowAfterAuthentication(bool pAutoClose) { - return mIsNewAppVersion; + if (pAutoClose != isAutoCloseWindowAfterAuthentication()) + { + mStore->setValue(SETTINGS_NAME_AUTO_CLOSE_WINDOW(), pAutoClose); + save(mStore); + Q_EMIT fireSettingsChanged(); + } } -bool GeneralSettings::isAutoCloseWindowAfterAuthentication() const +bool GeneralSettings::isAutoRedirectAfterAuthentication() const { - return mStore->value(SETTINGS_NAME_AUTO_CLOSE_WINDOW(), true).toBool(); + return mStore->value(SETTINGS_NAME_AUTO_REDIRECT(), true).toBool(); } -void GeneralSettings::setAutoCloseWindowAfterAuthentication(bool pAutoClose) +void GeneralSettings::setAutoRedirectAfterAuthentication(bool pAutoRedirect) { - if (pAutoClose != isAutoCloseWindowAfterAuthentication()) + if (pAutoRedirect != isAutoRedirectAfterAuthentication()) { - mStore->setValue(SETTINGS_NAME_AUTO_CLOSE_WINDOW(), pAutoClose); + mStore->setValue(SETTINGS_NAME_AUTO_REDIRECT(), pAutoRedirect); save(mStore); Q_EMIT fireSettingsChanged(); } @@ -342,30 +349,6 @@ void GeneralSettings::setUseSelfauthenticationTestUri(bool pUse) } -bool GeneralSettings::isSimulatorEnabled() const -{ -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - if (!isDeveloperOptions()) - { - return false; - } -#endif - - return mStore->value(SETTINGS_NAME_SIMULATOR(), false).toBool(); -} - - -void GeneralSettings::setSimulatorEnabled(bool pEnabled) -{ - if (pEnabled != isSimulatorEnabled()) - { - mStore->setValue(SETTINGS_NAME_SIMULATOR(), pEnabled); - save(mStore); - Q_EMIT fireDeveloperOptionsChanged(); - } -} - - QLocale::Language GeneralSettings::getLanguage() const { const QString loadedLanguage = mStore->value(SETTINGS_NAME_LANGUAGE(), QString()).toString(); @@ -485,7 +468,7 @@ bool GeneralSettings::isAutoUpdateCheck() const bool GeneralSettings::autoUpdateCheckIsSetByAdmin() const { - return QSettings(QSettings::Scope::SystemScope).contains(SETTINGS_NAME_AUTO()); + return getStore(QSettings::Scope::SystemScope)->contains(SETTINGS_NAME_AUTO()); } @@ -500,23 +483,6 @@ void GeneralSettings::setAutoUpdateCheck(bool pAutoUpdateCheck) } -bool GeneralSettings::isUseScreenKeyboard() const -{ - return mStore->value(SETTINGS_NAME_KEYLESS_PASSWORD(), false).toBool(); -} - - -void GeneralSettings::setUseScreenKeyboard(bool pUseScreenKeyboard) -{ - if (pUseScreenKeyboard != isUseScreenKeyboard()) - { - mStore->setValue(SETTINGS_NAME_KEYLESS_PASSWORD(), pUseScreenKeyboard); - save(mStore); - Q_EMIT fireSettingsChanged(); - } -} - - bool GeneralSettings::isVisualPrivacy() const { return mStore->value(SETTINGS_NAME_VISUAL_PRIVACY(), false).toBool(); @@ -702,6 +668,23 @@ void GeneralSettings::setUseSystemFont(bool pUseSystemFont) } +bool GeneralSettings::isUseAnimations() const +{ + return mStore->value(SETTINGS_NAME_ANIMATIONS(), true).toBool(); +} + + +void GeneralSettings::setUseAnimations(bool pUseAnimations) +{ + if (isUseAnimations() != pUseAnimations) + { + mStore->setValue(SETTINGS_NAME_ANIMATIONS(), pUseAnimations); + save(mStore); + Q_EMIT fireUseAnimationsChanged(); + } +} + + QString GeneralSettings::getDarkMode() const { return mStore->value(SETTINGS_NAME_DARK_MODE(), QString()).toString(); diff --git a/src/settings/GeneralSettings.h b/src/settings/GeneralSettings.h index ef5fa7946..58ef79347 100644 --- a/src/settings/GeneralSettings.h +++ b/src/settings/GeneralSettings.h @@ -1,13 +1,10 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Contains the definition of the GeneralSettings class. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once + #include "AbstractSettings.h" #include @@ -53,14 +50,14 @@ class GeneralSettings [[nodiscard]] bool showTrayIcon() const; void setAutoStart(bool pAutoStart); - [[nodiscard]] QString getSkipVersion() const; - void skipVersion(const QString& pVersion); - [[nodiscard]] bool isNewAppVersion() const; [[nodiscard]] bool isAutoCloseWindowAfterAuthentication() const; void setAutoCloseWindowAfterAuthentication(bool pAutoClose); + [[nodiscard]] bool isAutoRedirectAfterAuthentication() const; + void setAutoRedirectAfterAuthentication(bool pAutoRedirect); + [[nodiscard]] QString getStartupModule() const; void setStartupModule(const QString& pModule); @@ -79,9 +76,6 @@ class GeneralSettings [[nodiscard]] bool useSelfAuthTestUri() const; void setUseSelfauthenticationTestUri(bool pUse); - [[nodiscard]] bool isSimulatorEnabled() const; - void setSimulatorEnabled(bool pEnabled); - [[nodiscard]] QLocale::Language getLanguage() const; void setLanguage(const QLocale::Language pLanguage); @@ -101,9 +95,6 @@ class GeneralSettings [[nodiscard]] bool autoUpdateCheckIsSetByAdmin() const; void setAutoUpdateCheck(bool pAutoUpdateCheck); - [[nodiscard]] bool isUseScreenKeyboard() const; - void setUseScreenKeyboard(bool pUseScreenKeyboard); - [[nodiscard]] bool isVisualPrivacy() const; void setVisualPrivacy(bool pVisualPrivacy); @@ -135,6 +126,9 @@ class GeneralSettings [[nodiscard]] bool isUseSystemFont() const; void setUseSystemFont(bool pUseSystemFont); + [[nodiscard]] bool isUseAnimations() const; + void setUseAnimations(bool pUseAnimations); + [[nodiscard]] QString getDarkMode() const; void setDarkMode(const QString& pMode); @@ -154,6 +148,7 @@ class GeneralSettings void fireShowInAppNotificationsChanged(); void fireProxyChanged(); void fireUseSystemFontChanged(); + void fireUseAnimationsChanged(); void fireDarkModeChanged(); void fireSmartAvailableChanged(bool pSmartAvailable); }; diff --git a/src/settings/KeyPair.cpp b/src/settings/KeyPair.cpp index 3d3a83cab..00fb2cfac 100644 --- a/src/settings/KeyPair.cpp +++ b/src/settings/KeyPair.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -59,24 +58,18 @@ KeyPair::KeyPair(const QSslKey& pKey, const QSslCertificate& pCert) } -KeyPair KeyPair::generate(const char* pCurve) +KeyPair KeyPair::generatePair(EVP_PKEY* pKey, const QByteArray& pSignerKey, const QByteArray& pSignerCert) { - if (!Randomizer::getInstance().isSecureRandom()) - { - qCCritical(settings) << "Cannot get enough entropy"; - return KeyPair(); - } - - if (auto* pkey = createKey(pCurve); pkey) + if (pKey) { - auto cert = createCertificate(pkey); + const auto cert = createCertificate(pKey, parseKey(pSignerKey), parseCertificate(pSignerCert)); if (cert) { - return KeyPair(QSslKey(Qt::HANDLE(pkey), QSsl::PrivateKey), QSslCertificate(rewriteCertificate(cert.data()))); + return KeyPair(QSslKey(Qt::HANDLE(pKey), QSsl::PrivateKey), QSslCertificate(rewriteCertificate(cert.data()))); } else { - OpenSslCustomDeleter::cleanup(pkey); + OpenSslCustomDeleter::cleanup(pKey); } } @@ -84,6 +77,29 @@ KeyPair KeyPair::generate(const char* pCurve) } +KeyPair KeyPair::generate(const char* pCurve, const QByteArray& pSignerKey, const QByteArray& pSignerCert) +{ + if (!pCurve) + { + return KeyPair(); + } + + const auto& func = [pCurve](EVP_PKEY_CTX* pCtx) { + return EVP_PKEY_CTX_ctrl_str(pCtx, "ec_paramgen_curve", pCurve); + }; + return generatePair(createKey(EVP_PKEY_EC, func), pSignerKey, pSignerCert); +} + + +KeyPair KeyPair::generate(int pKeySize, const QByteArray& pSignerKey, const QByteArray& pSignerCert) +{ + const auto& func = [pKeySize](EVP_PKEY_CTX* pCtx) { + return EVP_PKEY_CTX_set_rsa_keygen_bits(pCtx, pKeySize); + }; + return generatePair(createKey(EVP_PKEY_RSA, func), pSignerKey, pSignerCert); +} + + const QSslKey& KeyPair::getKey() const { return mKey; @@ -96,9 +112,15 @@ const QSslCertificate& KeyPair::getCertificate() const } -EVP_PKEY* KeyPair::createKey(const char* pCurve) +EVP_PKEY* KeyPair::createKey(int pKeyCtxNid, const std::function& pFunc) { - QScopedPointer pkeyCtx(EVP_PKEY_CTX_new_id(pCurve ? EVP_PKEY_EC : EVP_PKEY_RSA, nullptr)); + if (!Randomizer::getInstance().isSecureRandom()) + { + qCCritical(settings) << "Cannot get enough entropy"; + return nullptr; + } + + QScopedPointer pkeyCtx(EVP_PKEY_CTX_new_id(pKeyCtxNid, nullptr)); if (pkeyCtx.isNull()) { @@ -106,28 +128,20 @@ EVP_PKEY* KeyPair::createKey(const char* pCurve) return nullptr; } - if (!EVP_PKEY_keygen_init(pkeyCtx.data())) + if (EVP_PKEY_keygen_init(pkeyCtx.data()) != 1) { qCCritical(settings) << "Cannot init key ctx"; return nullptr; } - if (pCurve) + if (pFunc && pFunc(pkeyCtx.data()) != 1) { - if (!EVP_PKEY_CTX_ctrl_str(pkeyCtx.data(), "ec_paramgen_curve", pCurve)) - { - qCCritical(settings) << "Cannot set curve"; - return nullptr; - } - } - else if (!EVP_PKEY_CTX_set_rsa_keygen_bits(pkeyCtx.data(), 2048)) - { - qCCritical(settings) << "Cannot generate key bits"; + qCCritical(settings) << "Cannot set parameters"; return nullptr; } EVP_PKEY* pkey = nullptr; - if (!EVP_PKEY_keygen(pkeyCtx.data(), &pkey)) + if (EVP_PKEY_keygen(pkeyCtx.data(), &pkey) != 1) { qCCritical(settings) << "Cannot generate key"; return nullptr; @@ -137,7 +151,31 @@ EVP_PKEY* KeyPair::createKey(const char* pCurve) } -QSharedPointer KeyPair::createCertificate(EVP_PKEY* pPkey) +QSharedPointer KeyPair::parseKey(const QByteArray& pData) +{ + if (pData.isEmpty()) + { + return nullptr; + } + + QScopedPointer bio(BIO_new_mem_buf(pData.constData(), -1)); + return QSharedPointer(PEM_read_bio_PrivateKey(bio.data(), nullptr, nullptr, nullptr), &EVP_PKEY_free); +} + + +QSharedPointer KeyPair::parseCertificate(const QByteArray& pData) +{ + if (pData.isEmpty()) + { + return nullptr; + } + + QScopedPointer bio(BIO_new_mem_buf(pData.constData(), -1)); + return QSharedPointer(PEM_read_bio_X509(bio.data(), nullptr, nullptr, nullptr), &X509_free); +} + + +QSharedPointer KeyPair::createCertificate(EVP_PKEY* pPkey, const QSharedPointer& pSignerKey, const QSharedPointer& pSignerCert) { QSharedPointer x509(X509_new(), &X509_free); if (x509.isNull()) @@ -163,9 +201,16 @@ QSharedPointer KeyPair::createCertificate(EVP_PKEY* pPkey) X509_NAME_add_entry_by_txt(name.data(), "serialNumber", MBSTRING_ASC, reinterpret_cast(randomSerial.constData()), -1, -1, 0); X509_set_subject_name(x509.data(), name.data()); + EVP_PKEY* signer = pPkey; + + if (pSignerKey && pSignerCert) + { + signer = pSignerKey.data(); + name.reset(X509_NAME_dup(X509_get_subject_name(pSignerCert.data()))); + } X509_set_issuer_name(x509.data(), name.data()); - if (!X509_sign(x509.data(), pPkey, EVP_sha256())) + if (!X509_sign(x509.data(), signer, EVP_sha256())) { qCCritical(settings) << "Cannot sign certificate"; return nullptr; diff --git a/src/settings/KeyPair.h b/src/settings/KeyPair.h index 0b2b67b43..7a7af06d5 100644 --- a/src/settings/KeyPair.h +++ b/src/settings/KeyPair.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -29,11 +29,15 @@ class KeyPair KeyPair(const QSslKey& pKey, const QSslCertificate& pCert); static QByteArray rewriteCertificate(X509* pX509); - static QSharedPointer createCertificate(EVP_PKEY* pPkey); - static EVP_PKEY* createKey(const char* pCurve); + static QSharedPointer createCertificate(EVP_PKEY* pPkey, const QSharedPointer& pSignerKey = nullptr, const QSharedPointer& pSignerCert = nullptr); + static EVP_PKEY* createKey(int pKeyCtxNid, const std::function& pFunc); + static QSharedPointer parseKey(const QByteArray& pData); + static QSharedPointer parseCertificate(const QByteArray& pData); + static KeyPair generatePair(EVP_PKEY* pKey, const QByteArray& pSignerKey, const QByteArray& pSignerCert); public: - static KeyPair generate(const char* pCurve = nullptr); + static KeyPair generate(const char* pCurve, const QByteArray& pSignerKey = QByteArray(), const QByteArray& pSignerCert = QByteArray()); + static KeyPair generate(int pKeySize = 2048, const QByteArray& pSignerKey = QByteArray(), const QByteArray& pSignerCert = QByteArray()); [[nodiscard]] const QSslKey& getKey() const; [[nodiscard]] const QSslCertificate& getCertificate() const; diff --git a/src/settings/PreVerificationSettings.cpp b/src/settings/PreVerificationSettings.cpp index 2de8a4cc7..6fddc3bf2 100644 --- a/src/settings/PreVerificationSettings.cpp +++ b/src/settings/PreVerificationSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PreVerificationSettings.h" diff --git a/src/settings/PreVerificationSettings.h b/src/settings/PreVerificationSettings.h index 82a17e5fe..97bc9cb74 100644 --- a/src/settings/PreVerificationSettings.h +++ b/src/settings/PreVerificationSettings.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/settings/RemoteServiceSettings.cpp b/src/settings/RemoteServiceSettings.cpp index 291ff8191..37596f45a 100644 --- a/src/settings/RemoteServiceSettings.cpp +++ b/src/settings/RemoteServiceSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteServiceSettings.h" @@ -22,11 +22,10 @@ Q_DECLARE_LOGGING_CATEGORY(settings) namespace { SETTINGS_NAME(SETTINGS_GROUP_NAME_REMOTEREADER, "remotereader") -SETTINGS_NAME(SETTINGS_NAME_DEVICE_NAME, "serverName") +SETTINGS_NAME(SETTINGS_NAME_DEVICE_NAME, "deviceName") SETTINGS_NAME(SETTINGS_NAME_PIN_PAD_MODE, "pinPadMode") SETTINGS_NAME(SETTINGS_NAME_SHOW_ACCESS_RIGHTS, "showAccessRights") -SETTINGS_NAME(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES, "trustedCertificates") -SETTINGS_NAME(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM, "certificate") +SETTINGS_NAME(SETTINGS_NAME_TRUSTED_CERTIFICATES, "trustedCAs") SETTINGS_NAME(SETTINGS_NAME_TRUSTED_REMOTE_INFO, "trustedRemoteInfo") SETTINGS_NAME(SETTINGS_NAME_KEY, "key") SETTINGS_NAME(SETTINGS_NAME_CERTIFICATE, "certificate") @@ -44,14 +43,41 @@ RemoteServiceSettings::RemoteServiceSettings() , mStore(getStore()) { mStore->beginGroup(SETTINGS_GROUP_NAME_REMOTEREADER()); - if (!mStore->contains(SETTINGS_NAME_DEVICE_NAME())) + + // With 2.1.0 serverName was renamed to deviceName + const QAnyStringView serverName("serverName"); +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + if (mStore->contains(serverName)) + { + setDeviceName(mStore->value(serverName).toString()); + } +#endif + mStore->remove(serverName); + + // With 2.1.0 "trustedCertificates" moved from custom array to "trustedCAs" bytearray + const QAnyStringView trustedCertificates("trustedCertificates"); + if (mStore->childGroups().contains(trustedCertificates)) { - setServerName(QString()); + const int itemCount = mStore->beginReadArray(trustedCertificates); + QSet certificates; + certificates.reserve(itemCount); + for (int i = 0; i < itemCount; ++i) + { + mStore->setArrayIndex(i); + const auto& cert = mStore->value(QAnyStringView("certificate"), QByteArray()).toByteArray(); + certificates << QSslCertificate(cert); + } + mStore->endArray(); + setUniqueTrustedCertificates(certificates); + + mStore->beginGroup(trustedCertificates); + mStore->remove(QString()); + mStore->endGroup(); } } -QString RemoteServiceSettings::getDefaultServerName() const +QString RemoteServiceSettings::getDefaultDeviceName() const { QString name = DeviceInfo::getName(); if (name.isEmpty()) @@ -64,16 +90,29 @@ QString RemoteServiceSettings::getDefaultServerName() const } -QString RemoteServiceSettings::getServerName() const +QString RemoteServiceSettings::getDeviceName() const { - return mStore->value(SETTINGS_NAME_DEVICE_NAME(), QString()).toString(); + + if (mStore->contains(SETTINGS_NAME_DEVICE_NAME())) + { + return mStore->value(SETTINGS_NAME_DEVICE_NAME(), QString()).toString(); + } + + return getDefaultDeviceName(); } -void RemoteServiceSettings::setServerName(const QString& pName) +void RemoteServiceSettings::setDeviceName(const QString& pName) { const QString serverName = pName.trimmed(); - mStore->setValue(SETTINGS_NAME_DEVICE_NAME(), serverName.isEmpty() ? getDefaultServerName() : serverName); + if (serverName.isEmpty() || serverName == getDefaultDeviceName()) + { + mStore->remove(SETTINGS_NAME_DEVICE_NAME()); + } + else + { + mStore->setValue(SETTINGS_NAME_DEVICE_NAME(), serverName); + } save(mStore); } @@ -106,38 +145,18 @@ void RemoteServiceSettings::setShowAccessRights(bool pShowAccessRights) QList RemoteServiceSettings::getTrustedCertificates() const { - const int itemCount = mStore->beginReadArray(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); - - QList certificates; - certificates.reserve(itemCount); - for (int i = 0; i < itemCount; ++i) - { - mStore->setArrayIndex(i); - const auto& cert = mStore->value(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM(), QByteArray()).toByteArray(); - certificates << QSslCertificate(cert); - } - - mStore->endArray(); - return certificates; + return QSslCertificate::fromData(mStore->value(SETTINGS_NAME_TRUSTED_CERTIFICATES(), QByteArray()).toByteArray()); } void RemoteServiceSettings::setUniqueTrustedCertificates(const QSet& pCertificates) { - mStore->beginGroup(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); - mStore->remove(QString()); - mStore->endGroup(); - - mStore->beginWriteArray(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); - int i = 0; + QByteArrayList data; for (const auto& cert : pCertificates) { - mStore->setArrayIndex(i); - ++i; - mStore->setValue(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM(), cert.toPem()); + data << cert.toPem(); } - mStore->endArray(); - save(mStore); + mStore->setValue(SETTINGS_NAME_TRUSTED_CERTIFICATES(), data.join()); syncRemoteInfos(pCertificates); Q_EMIT fireTrustedCertificatesChanged(); @@ -181,19 +200,22 @@ void RemoteServiceSettings::removeTrustedCertificate(const QString& pFingerprint } -bool RemoteServiceSettings::checkAndGenerateKey(bool pForceGeneration) const +bool RemoteServiceSettings::checkAndGenerateKey(int pCreateKeySize) const { + auto certs = getCertificates(); + const auto& currentCert = certs.isEmpty() ? QSslCertificate() : certs.at(0); if (getKey().isNull() - || getCertificate().isNull() - || getCertificate().expiryDate() < QDateTime::currentDateTime() - || pForceGeneration) + || currentCert.isNull() + || currentCert.expiryDate() < QDateTime::currentDateTime() + || currentCert.publicKey().length() < pCreateKeySize) { qCDebug(settings) << "Generate local keypair..."; - const auto& pair = KeyPair::generate(); + const auto& pair = KeyPair::generate(pCreateKeySize, getKey().toPem(), currentCert.toPem()); if (pair.isValid()) { + certs.prepend(pair.getCertificate()); setKey(pair.getKey()); - setCertificate(pair.getCertificate()); + setCertificates(certs); return true; } @@ -204,15 +226,20 @@ bool RemoteServiceSettings::checkAndGenerateKey(bool pForceGeneration) const } -QSslCertificate RemoteServiceSettings::getCertificate() const +QList RemoteServiceSettings::getCertificates() const { - return QSslCertificate(mStore->value(SETTINGS_NAME_CERTIFICATE(), QByteArray()).toByteArray()); + return QSslCertificate::fromData(mStore->value(SETTINGS_NAME_CERTIFICATE(), QByteArray()).toByteArray()); } -void RemoteServiceSettings::setCertificate(const QSslCertificate& pCert) const +void RemoteServiceSettings::setCertificates(const QList& pCertChain) const { - mStore->setValue(SETTINGS_NAME_CERTIFICATE(), pCert.toPem()); + QByteArrayList data; + for (const auto& cert : pCertChain) + { + data << cert.toPem(); + } + mStore->setValue(SETTINGS_NAME_CERTIFICATE(), data.join()); save(mStore); } @@ -266,9 +293,9 @@ RemoteServiceSettings::RemoteInfo RemoteServiceSettings::getRemoteInfo(const QSt } -QVector RemoteServiceSettings::getRemoteInfos() const +QList RemoteServiceSettings::getRemoteInfos() const { - QVector infos; + QList infos; const auto& data = mStore->value(SETTINGS_NAME_TRUSTED_REMOTE_INFO(), QByteArray()).toByteArray(); const auto& array = QJsonDocument::fromJson(data).array(); @@ -281,7 +308,7 @@ QVector RemoteServiceSettings::getRemoteInfos } -void RemoteServiceSettings::setRemoteInfos(const QVector& pInfos) +void RemoteServiceSettings::setRemoteInfos(const QList& pInfos) { QJsonArray array; for (const auto& item : pInfos) @@ -303,7 +330,7 @@ void RemoteServiceSettings::syncRemoteInfos(const QSet& pCertif trustedFingerprints << generateFingerprint(cert); } - QVector syncedInfo; + QList syncedInfo; // remove outdated entries const auto& infos = getRemoteInfos(); @@ -334,19 +361,14 @@ bool RemoteServiceSettings::updateRemoteInfo(const RemoteInfo& pInfo) } auto infos = getRemoteInfos(); - QMutableVectorIterator iter(infos); + QMutableListIterator iter(infos); while (iter.hasNext()) { iter.next(); if (iter.value().getFingerprint() == pInfo.getFingerprint()) { - const bool hadNoNameYet = iter.value().mName.isEmpty(); iter.setValue(pInfo); setRemoteInfos(infos); - if (hadNoNameYet) - { - Q_EMIT fireInitialDeviceNameSet(pInfo.getNameEscaped()); - } return true; } } diff --git a/src/settings/RemoteServiceSettings.h b/src/settings/RemoteServiceSettings.h index f75bae742..c26a157a2 100644 --- a/src/settings/RemoteServiceSettings.h +++ b/src/settings/RemoteServiceSettings.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,7 +16,6 @@ #include #include #include -#include class test_RemoteServiceSettings; class test_IfdConnector; @@ -72,19 +71,19 @@ class RemoteServiceSettings QSharedPointer mStore; RemoteServiceSettings(); - [[nodiscard]] QString getDefaultServerName() const; + [[nodiscard]] QString getDefaultDeviceName() const; void setTrustedCertificates(const QList& pCertificates); void setUniqueTrustedCertificates(const QSet& pCertificates); - void setRemoteInfos(const QVector& pInfos); + void setRemoteInfos(const QList& pInfos); void syncRemoteInfos(const QSet& pCertificates); public: static QString generateFingerprint(const QSslCertificate& pCert); ~RemoteServiceSettings() override = default; - [[nodiscard]] QString getServerName() const; - void setServerName(const QString& pName); + [[nodiscard]] QString getDeviceName() const; + void setDeviceName(const QString& pName); [[nodiscard]] bool getPinPadMode() const; void setPinPadMode(bool pPinPadMode); @@ -97,17 +96,17 @@ class RemoteServiceSettings void removeTrustedCertificate(const QSslCertificate& pCertificate); void removeTrustedCertificate(const QString& pFingerprint); - bool checkAndGenerateKey(bool pForceGeneration = false) const; + bool checkAndGenerateKey(int pCreateKeySize) const; - [[nodiscard]] QSslCertificate getCertificate() const; - void setCertificate(const QSslCertificate& pCert) const; + [[nodiscard]] QList getCertificates() const; + void setCertificates(const QList& pCertChain) const; [[nodiscard]] QSslKey getKey() const; void setKey(const QSslKey& pKey) const; [[nodiscard]] RemoteInfo getRemoteInfo(const QSslCertificate& pCertificate) const; [[nodiscard]] RemoteInfo getRemoteInfo(const QString& pFingerprint) const; - [[nodiscard]] QVector getRemoteInfos() const; + [[nodiscard]] QList getRemoteInfos() const; bool updateRemoteInfo(const RemoteInfo& pInfo); static QString escapeDeviceName(const QString& pDeviceNameUnescaped); @@ -115,7 +114,6 @@ class RemoteServiceSettings Q_SIGNALS: void fireTrustedCertificatesChanged(); void fireTrustedRemoteInfosChanged(); - void fireInitialDeviceNameSet(const QString& pName); }; diff --git a/src/settings/SimulatorSettings.cpp b/src/settings/SimulatorSettings.cpp new file mode 100644 index 000000000..3dfa976c0 --- /dev/null +++ b/src/settings/SimulatorSettings.cpp @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "SimulatorSettings.h" + + +using namespace governikus; + + +namespace +{ +SETTINGS_NAME(SETTINGS_GROUP_NAME_SIMULATOR, "simulator") +SETTINGS_NAME(SETTINGS_NAME_ENABLED, "enabled") +SETTINGS_NAME(SETTINGS_NAME_BASIC_READER, "basicReader") +} // namespace + + +SimulatorSettings::SimulatorSettings() + : AbstractSettings() + , mStore(getStore()) +{ + // With 2.2.0 the simulator got own settings + const QAnyStringView simulator("simulator"); + if (mStore->contains(simulator)) + { + const auto& value = mStore->value(simulator, false).toBool(); + mStore->remove(simulator); + mStore->beginGroup(SETTINGS_GROUP_NAME_SIMULATOR()); + mStore->setValue(SETTINGS_NAME_ENABLED(), value); + mStore->endGroup(); + } + + mStore->beginGroup(SETTINGS_GROUP_NAME_SIMULATOR()); +} + + +bool SimulatorSettings::isEnabled() const +{ + return mStore->value(SETTINGS_NAME_ENABLED(), false).toBool(); +} + + +void SimulatorSettings::setEnabled(bool pEnabled) +{ + if (pEnabled != isEnabled()) + { + mStore->setValue(SETTINGS_NAME_ENABLED(), pEnabled); + save(mStore); + Q_EMIT fireEnabledChanged(); + } +} + + +bool SimulatorSettings::isBasicReader() const +{ + return mStore->value(SETTINGS_NAME_BASIC_READER(), false).toBool(); +} + + +void SimulatorSettings::setBasicReader(bool pBasicReader) +{ + mStore->setValue(SETTINGS_NAME_BASIC_READER(), pBasicReader); + save(mStore); +} diff --git a/src/settings/SimulatorSettings.h b/src/settings/SimulatorSettings.h new file mode 100644 index 000000000..ab44ee7f0 --- /dev/null +++ b/src/settings/SimulatorSettings.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + + +#include "AbstractSettings.h" + + +namespace governikus +{ + +class SimulatorSettings + : public AbstractSettings +{ + Q_OBJECT + + friend class AppSettings; + + private: + QSharedPointer mStore; + + SimulatorSettings(); + + public: + ~SimulatorSettings() override = default; + + [[nodiscard]] bool isEnabled() const; + void setEnabled(bool pEnabled); + + [[nodiscard]] bool isBasicReader() const; + void setBasicReader(bool pBasicReader); + + Q_SIGNALS: + void fireEnabledChanged(); +}; + + +} // namespace governikus diff --git a/src/settings/VolatileSettings.cpp b/src/settings/VolatileSettings.cpp index 5ef60efe9..b9916c1a9 100644 --- a/src/settings/VolatileSettings.cpp +++ b/src/settings/VolatileSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "VolatileSettings.h" diff --git a/src/settings/VolatileSettings.h b/src/settings/VolatileSettings.h index 8c7a15d38..55ad63ef4 100644 --- a/src/settings/VolatileSettings.h +++ b/src/settings/VolatileSettings.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -61,7 +61,7 @@ class VolatileSettings static constexpr bool cHandleInterruptDefault = false; VolatileSettings(); - ~VolatileSettings() = default; + ~VolatileSettings() override = default; mutable QReadWriteLock mLock; bool mUsedAsSdk; diff --git a/src/ui/aidl/AidlBinder.java b/src/ui/aidl/AidlBinder.java index 6c4ee61cc..df1a89bbd 100644 --- a/src/ui/aidl/AidlBinder.java +++ b/src/ui/aidl/AidlBinder.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; diff --git a/src/ui/aidl/UIPlugInAidl.cpp b/src/ui/aidl/UiPluginAidl.cpp similarity index 69% rename from src/ui/aidl/UIPlugInAidl.cpp rename to src/ui/aidl/UiPluginAidl.cpp index 128e1fdde..cc060a33c 100644 --- a/src/ui/aidl/UIPlugInAidl.cpp +++ b/src/ui/aidl/UiPluginAidl.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInAidl.h" +#include "UiPluginAidl.h" #include "Env.h" #include "ReaderManager.h" -#include "UILoader.h" +#include "UiLoader.h" #include "WorkflowRequest.h" #ifdef Q_OS_ANDROID #include "Randomizer.h" @@ -30,10 +30,10 @@ Q_DECLARE_LOGGING_CATEGORY(aidl) using namespace governikus; -QAtomicPointer UIPlugInAidl::instance = nullptr; +QAtomicPointer UiPluginAidl::instance = nullptr; -UIPlugInAidl::UIPlugInAidl() - : UIPlugIn() +UiPluginAidl::UiPluginAidl() + : UiPlugin() , mJson(nullptr) , mContext() , mWorkflowIsActive() @@ -42,30 +42,30 @@ UIPlugInAidl::UIPlugInAidl() } -bool UIPlugInAidl::initialize() +bool UiPluginAidl::initialize() { if (mJson) { return true; } - if (!Env::getSingleton()->load()) + if (!Env::getSingleton()->load()) { qCWarning(aidl) << "Cannot start AIDL because JSON-API is missing"; return false; } - mJson = Env::getSingleton()->getLoaded(); - connect(mJson, &UIPlugInJson::fireMessage, this, &UIPlugInAidl::onToSend, Qt::QueuedConnection); + mJson = Env::getSingleton()->getLoaded(); + connect(mJson, &UiPluginJson::fireMessage, this, &UiPluginAidl::onToSend, Qt::QueuedConnection); mJson->setEnabled(); return true; } -UIPlugInAidl* UIPlugInAidl::getInstance(bool pBlock) +UiPluginAidl* UiPluginAidl::getInstance(bool pBlock) { // The Java interface thread is ready before our core has booted. - // Hence we delay access to the UIPlugInAidl. + // Hence we delay access to the UiPluginAidl. if (pBlock) { while (instance.loadRelaxed() == nullptr) @@ -78,22 +78,22 @@ UIPlugInAidl* UIPlugInAidl::getInstance(bool pBlock) } -bool UIPlugInAidl::isSuccessfullInitialized() const +bool UiPluginAidl::isSuccessfullInitialized() const { return mJson; } -void UIPlugInAidl::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginAidl::onWorkflowStarted(const QSharedPointer& pRequest) { mWorkflowIsActive.lock(); mContext = pRequest->getContext(); - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::NFC, ReaderManagerPlugInType::LOCAL_IFD, ReaderManagerPlugInType::SIMULATOR}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::NFC, ReaderManagerPluginType::LOCAL_IFD, ReaderManagerPluginType::SIMULATOR}); mContext->claim(this); } -void UIPlugInAidl::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginAidl::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) @@ -103,13 +103,13 @@ void UIPlugInAidl::onWorkflowFinished(const QSharedPointer& pRe } -void UIPlugInAidl::onReceived(const QByteArray& pMessage) +void UiPluginAidl::onReceived(const QByteArray& pMessage) { mJson->doMessageProcessing(pMessage); } -bool UIPlugInAidl::waitForWorkflowToFinish() +bool UiPluginAidl::waitForWorkflowToFinish() { const int fiveSeconds = 5000; bool success = mWorkflowIsActive.tryLock(fiveSeconds); @@ -121,7 +121,7 @@ bool UIPlugInAidl::waitForWorkflowToFinish() } -void UIPlugInAidl::reset() +void UiPluginAidl::reset() { if (mContext) { @@ -131,16 +131,16 @@ void UIPlugInAidl::reset() } -void UIPlugInAidl::startReaderManagerScans() const +void UiPluginAidl::startReaderManagerScans() const { - const auto readerManager = Env::getSingleton(); - readerManager->startScan(ReaderManagerPlugInType::NFC); - readerManager->startScan(ReaderManagerPlugInType::LOCAL_IFD); - readerManager->startScan(ReaderManagerPlugInType::SIMULATOR); + auto* readerManager = Env::getSingleton(); + readerManager->startScan(ReaderManagerPluginType::NFC); + readerManager->startScan(ReaderManagerPluginType::LOCAL_IFD); + readerManager->startScan(ReaderManagerPluginType::SIMULATOR); } -void UIPlugInAidl::onToSend(const QByteArray& pMessage) const +void UiPluginAidl::onToSend(const QByteArray& pMessage) const { #ifdef Q_OS_ANDROID const QString json = QString::fromUtf8(pMessage); @@ -155,7 +155,7 @@ void UIPlugInAidl::onToSend(const QByteArray& pMessage) const } -void UIPlugInAidl::doShutdown() +void UiPluginAidl::doShutdown() { } @@ -171,13 +171,13 @@ JNIEXPORT jstring JNICALL Java_com_governikus_ausweisapp2_AidlBinder_resetValidS { Q_UNUSED(pObj) - UIPlugInAidl* plugin = UIPlugInAidl::getInstance(); + UiPluginAidl* plugin = UiPluginAidl::getInstance(); if (!plugin->isSuccessfullInitialized()) { qCCritical(aidl) << "Cannot call AIDL plugin"; return pEnv->NewStringUTF(""); } - QMetaObject::invokeMethod(plugin, &UIPlugInAidl::reset, Qt::QueuedConnection); + QMetaObject::invokeMethod(plugin, &UiPluginAidl::reset, Qt::QueuedConnection); if (!plugin->waitForWorkflowToFinish()) { qCCritical(aidl) << "Cannot acquire workflow mutex"; @@ -203,14 +203,14 @@ JNIEXPORT jboolean JNICALL Java_com_governikus_ausweisapp2_AidlBinder_startReade Q_UNUSED(pEnv) Q_UNUSED(pObj) - UIPlugInAidl* plugin = UIPlugInAidl::getInstance(); + UiPluginAidl* plugin = UiPluginAidl::getInstance(); if (!plugin->isSuccessfullInitialized()) { qCCritical(aidl) << "Cannot call AIDL plugin"; return false; } - QMetaObject::invokeMethod(plugin, &UIPlugInAidl::startReaderManagerScans, Qt::QueuedConnection); + QMetaObject::invokeMethod(plugin, &UiPluginAidl::startReaderManagerScans, Qt::QueuedConnection); return true; } @@ -223,7 +223,7 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_AidlBinder_aidlSend(JNIEn const QString json = QString::fromUtf8(nativeString); pEnv->ReleaseStringUTFChars(pJson, nativeString); - UIPlugInAidl* plugin = UIPlugInAidl::getInstance(); + UiPluginAidl* plugin = UiPluginAidl::getInstance(); if (!plugin->isSuccessfullInitialized()) { qCCritical(aidl) << "Cannot call AIDL plugin"; diff --git a/src/ui/aidl/UIPlugInAidl.h b/src/ui/aidl/UiPluginAidl.h similarity index 61% rename from src/ui/aidl/UIPlugInAidl.h rename to src/ui/aidl/UiPluginAidl.h index 577c9e039..cfa699ddf 100644 --- a/src/ui/aidl/UIPlugInAidl.h +++ b/src/ui/aidl/UiPluginAidl.h @@ -1,15 +1,15 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the AIDL UI. + * \brief UiPlugin implementation of the AIDL UI. */ #pragma once -#include "UIPlugIn.h" -#include "UIPlugInJson.h" +#include "UiPlugin.h" +#include "UiPluginJson.h" #include #include @@ -17,25 +17,25 @@ namespace governikus { -class UIPlugInAidl - : public UIPlugIn +class UiPluginAidl + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) private: - QPointer mJson; + QPointer mJson; QSharedPointer mContext; QMutex mWorkflowIsActive; - static QAtomicPointer instance; + static QAtomicPointer instance; public: - UIPlugInAidl(); - ~UIPlugInAidl() override = default; + UiPluginAidl(); + ~UiPluginAidl() override = default; - static UIPlugInAidl* getInstance(bool pBlock = true); + static UiPluginAidl* getInstance(bool pBlock = true); [[nodiscard]] bool initialize() override; [[nodiscard]] bool isSuccessfullInitialized() const; Q_INVOKABLE void onReceived(const QByteArray& pMessage); diff --git a/src/ui/automatic/UIPlugInAutomatic.cpp b/src/ui/automatic/UiPluginAutomatic.cpp similarity index 75% rename from src/ui/automatic/UIPlugInAutomatic.cpp rename to src/ui/automatic/UiPluginAutomatic.cpp index eaa51cac3..dfe5b1e2a 100644 --- a/src/ui/automatic/UIPlugInAutomatic.cpp +++ b/src/ui/automatic/UiPluginAutomatic.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInAutomatic.h" +#include "UiPluginAutomatic.h" #include "Env.h" #include "ReaderManager.h" @@ -18,8 +18,8 @@ Q_DECLARE_LOGGING_CATEGORY(automatic) using namespace governikus; -UIPlugInAutomatic::UIPlugInAutomatic() - : UIPlugIn() +UiPluginAutomatic::UiPluginAutomatic() + : UiPlugin() , mContext() , mPrevUsedAsSDK() , mPrevUsedDeveloperMode() @@ -27,17 +27,17 @@ UIPlugInAutomatic::UIPlugInAutomatic() } -void UIPlugInAutomatic::onApplicationStarted() +void UiPluginAutomatic::onApplicationStarted() { } -void UIPlugInAutomatic::doShutdown() +void UiPluginAutomatic::doShutdown() { } -void UIPlugInAutomatic::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginAutomatic::onWorkflowStarted(const QSharedPointer& pRequest) { if (isDominated()) { @@ -51,8 +51,8 @@ void UIPlugInAutomatic::onWorkflowStarted(const QSharedPointer& qCDebug(automatic) << "Fallback to full automatic UI"; mContext = context; - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::SIMULATOR, ReaderManagerPlugInType::PCSC}); - connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UIPlugInAutomatic::onStateChanged); + mContext->setReaderPluginTypes({ReaderManagerPluginType::SIMULATOR, ReaderManagerPluginType::PCSC}); + connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UiPluginAutomatic::onStateChanged); mPrevUsedAsSDK = Env::getSingleton()->isUsedAsSDK(); mPrevUsedDeveloperMode = Env::getSingleton()->isDeveloperMode(); Env::getSingleton()->setUsedAsSDK(true); @@ -72,7 +72,7 @@ void UIPlugInAutomatic::onWorkflowStarted(const QSharedPointer& } -void UIPlugInAutomatic::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginAutomatic::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) @@ -88,7 +88,7 @@ void UIPlugInAutomatic::onWorkflowFinished(const QSharedPointer } -void UIPlugInAutomatic::onStateChanged(const QString& pState) +void UiPluginAutomatic::onStateChanged(const QString& pState) { if (mContext) { @@ -108,13 +108,30 @@ void UIPlugInAutomatic::onStateChanged(const QString& pState) } -bool UIPlugInAutomatic::isDominated() const +bool UiPluginAutomatic::isDominated() const { return !mDominator.isNull(); } -void UIPlugInAutomatic::handleInsertCard() +void UiPluginAutomatic::handleInsertCard() +{ + const auto* readerManager = Env::getSingleton(); + if (readerManager->isInitialScanFinished()) + { + handleInsertCardScanFinished(); + } + else + { + connect(readerManager, &ReaderManager::fireInitialScanFinished, this, [this]{ + Env::getSingleton()->disconnect(this); + handleInsertCardScanFinished(); + }); + } +} + + +void UiPluginAutomatic::handleInsertCardScanFinished() { const auto& infos = Env::getSingleton()->getReaderInfos(); @@ -144,10 +161,11 @@ void UIPlugInAutomatic::handleInsertCard() } -void UIPlugInAutomatic::handlePassword() +void UiPluginAutomatic::handlePassword() { if (mContext->getLastPaceResult() != CardReturnCode::OK - && mContext->getLastPaceResult() != CardReturnCode::OK_PUK) + && mContext->getLastPaceResult() != CardReturnCode::OK_PUK + && mContext->getLastPaceResult() != CardReturnCode::OK_CAN) { qCWarning(automatic) << "Previous PACE failed... abort automatic workflow"; mContext->killWorkflow(); @@ -200,7 +218,7 @@ void UIPlugInAutomatic::handlePassword() break; } } - else if (currentReaderInfo.getPlugInType() == ReaderManagerPlugInType::SIMULATOR) + else if (currentReaderInfo.getPluginType() == ReaderManagerPluginType::SIMULATOR) { mContext->setStateApproved(); return; @@ -211,7 +229,7 @@ void UIPlugInAutomatic::handlePassword() } -void UIPlugInAutomatic::onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) +void UiPluginAutomatic::onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) { if (pUi == this) { @@ -225,7 +243,7 @@ void UIPlugInAutomatic::onUiDomination(const UIPlugIn* pUi, const QString& pInfo } -void UIPlugInAutomatic::onUiDominationReleased() +void UiPluginAutomatic::onUiDominationReleased() { mDominator.clear(); } diff --git a/src/ui/automatic/UIPlugInAutomatic.h b/src/ui/automatic/UiPluginAutomatic.h similarity index 57% rename from src/ui/automatic/UIPlugInAutomatic.h rename to src/ui/automatic/UiPluginAutomatic.h index 664ee992f..19c5f22dd 100644 --- a/src/ui/automatic/UIPlugInAutomatic.h +++ b/src/ui/automatic/UiPluginAutomatic.h @@ -1,27 +1,27 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of full automatic authentication. + * \brief UiPlugin implementation of full automatic authentication. */ #pragma once -#include "UIPlugIn.h" +#include "UiPlugin.h" -class test_UIPlugInAutomatic; +class test_UiPluginAutomatic; namespace governikus { -class UIPlugInAutomatic - : public UIPlugIn +class UiPluginAutomatic + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) - friend class ::test_UIPlugInAutomatic; + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) + friend class ::test_UiPluginAutomatic; private: QSharedPointer mContext; @@ -31,6 +31,7 @@ class UIPlugInAutomatic [[nodiscard]] bool isDominated() const; void handleInsertCard(); + void handleInsertCardScanFinished(); void handlePassword(); private Q_SLOTS: @@ -38,13 +39,13 @@ class UIPlugInAutomatic void doShutdown() override; void onWorkflowStarted(const QSharedPointer& pRequest) override; void onWorkflowFinished(const QSharedPointer& pRequest) override; - void onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) override; + void onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) override; void onUiDominationReleased() override; void onStateChanged(const QString& pState); public: - UIPlugInAutomatic(); - ~UIPlugInAutomatic() override = default; + UiPluginAutomatic(); + ~UiPluginAutomatic() override = default; }; } // namespace governikus diff --git a/src/ui/base/CMakeLists.txt b/src/ui/base/CMakeLists.txt index 3a1c87461..4a2e8b0d2 100644 --- a/src/ui/base/CMakeLists.txt +++ b/src/ui/base/CMakeLists.txt @@ -1,3 +1,4 @@ ADD_PLATFORM_LIBRARY(AusweisAppUi) target_link_libraries(AusweisAppUi ${Qt}::Core ${Qt}::Network AusweisAppGlobal) +qt_extract_metatypes(AusweisAppUi) # QTBUG-123574 diff --git a/src/ui/base/UIPlugIn.cpp b/src/ui/base/UIPlugIn.cpp deleted file mode 100644 index 39e10ebf0..000000000 --- a/src/ui/base/UIPlugIn.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "UIPlugIn.h" - -using namespace governikus; - -void UIPlugIn::onApplicationInitialized() -{ -} - - -void UIPlugIn::onApplicationStarted() -{ -} - - -void UIPlugIn::onShowUi(UiModule pModule) -{ - Q_UNUSED(pModule) -} - - -bool UIPlugIn::initialize() -{ - return true; -} - - -void UIPlugIn::onWorkflowUnhandled(const QSharedPointer& pRequest) -{ - Q_UNUSED(pRequest) -} - - -void UIPlugIn::onHideUi() -{ -} - - -void UIPlugIn::onTranslationChanged() -{ -} - - -void UIPlugIn::onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) -{ - Q_UNUSED(pProxy) - Q_UNUSED(pAuthenticator) -} - - -void UIPlugIn::onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) -{ - Q_UNUSED(pUi) - Q_UNUSED(pInformation) - Q_UNUSED(pAccepted) -} - - -void UIPlugIn::onUiDominationReleased() -{ -} - - -void UIPlugIn::onShowUserInformation(const QString& pInformationMessage) -{ - Q_UNUSED(pInformationMessage) -} diff --git a/src/ui/base/UILoader.cpp b/src/ui/base/UiLoader.cpp similarity index 58% rename from src/ui/base/UILoader.cpp rename to src/ui/base/UiLoader.cpp index e09ae93d3..1c58ead98 100644 --- a/src/ui/base/UILoader.cpp +++ b/src/ui/base/UiLoader.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ -#include "UILoader.h" +#include "UiLoader.h" #include "BuildHelper.h" @@ -15,18 +15,18 @@ Q_DECLARE_LOGGING_CATEGORY(gui) using namespace governikus; -QStringList governikus::UILoader::cUserRequest; +QStringList governikus::UiLoader::cUserRequest; -UILoader::UILoader() - : mLoadedPlugIns() +UiLoader::UiLoader() + : mLoadedPlugins() { } -UILoader::~UILoader() +UiLoader::~UiLoader() { - if (!mLoadedPlugIns.isEmpty()) + if (!mLoadedPlugins.isEmpty()) { blockSignals(true); shutdown(); @@ -34,7 +34,7 @@ UILoader::~UILoader() } -QStringList UILoader::getInitialDefault() +QStringList UiLoader::getInitialDefault() { QStringList list; @@ -42,7 +42,7 @@ QStringList UILoader::getInitialDefault() for (auto& plugin : allPlugins) { const auto& metaData = plugin.metaData(); - if (isPlugIn(metaData) && isDefault(metaData)) + if (isPlugin(metaData) && isDefault(metaData)) { list << getName(metaData); } @@ -53,38 +53,38 @@ QStringList UILoader::getInitialDefault() } -bool UILoader::initialize() const +bool UiLoader::initialize() const { - return std::all_of(mLoadedPlugIns.begin(), mLoadedPlugIns.end(), [](UIPlugIn* pUi){ + return std::all_of(mLoadedPlugins.begin(), mLoadedPlugins.end(), [](UiPlugin* pUi){ return pUi->initialize(); }); } -bool UILoader::hasActiveUI() const +bool UiLoader::hasActiveUI() const { - return std::any_of(mLoadedPlugIns.begin(), mLoadedPlugIns.end(), [](const UIPlugIn* pUi){ + return std::any_of(mLoadedPlugins.begin(), mLoadedPlugins.end(), [](const UiPlugin* pUi){ return !pUi->property("passive").toBool(); }); } -bool UILoader::requiresReaderManager() const +bool UiLoader::requiresReaderManager() const { - return std::any_of(mLoadedPlugIns.begin(), mLoadedPlugIns.end(), [](const UIPlugIn* pUi){ + return std::any_of(mLoadedPlugins.begin(), mLoadedPlugins.end(), [](const UiPlugin* pUi){ const auto& property = pUi->property("readerManager"); return property.isNull() || property.toBool(); }); } -bool UILoader::isLoaded() const +bool UiLoader::isLoaded() const { - return !mLoadedPlugIns.isEmpty(); + return !mLoadedPlugins.isEmpty(); } -bool UILoader::load() +bool UiLoader::load() { bool any = false; const auto& list = getUserRequestOrDefault(); @@ -96,12 +96,12 @@ bool UILoader::load() } -bool UILoader::load(const QString& pUi) +bool UiLoader::load(const QString& pUi) { Q_ASSERT(QObject::thread() == QThread::currentThread()); const auto& requestedName = unify(pUi); - if (mLoadedPlugIns.contains(requestedName)) + if (mLoadedPlugins.contains(requestedName)) { return true; } @@ -112,7 +112,7 @@ bool UILoader::load(const QString& pUi) for (auto& plugin : allPlugins) { const auto& metaData = plugin.metaData(); - if (isPlugIn(metaData) && getName(metaData) == requestedName) + if (isPlugin(metaData) && getName(metaData) == requestedName) { if (!BuildHelper::isUserInteractive() && isUserInteractive(metaData)) { @@ -120,15 +120,16 @@ bool UILoader::load(const QString& pUi) continue; } + setEnvironment(metaData); qCDebug(gui) << "Load plugin:" << metaData; - auto instance = qobject_cast(plugin.instance()); + auto instance = qobject_cast(plugin.instance()); if (!instance) { qCWarning(gui) << "Cannot cast to plugin instance:" << plugin.instance(); continue; } - preparePlugIn(instance, metaData); + preparePlugin(instance, metaData); return true; } } @@ -138,17 +139,17 @@ bool UILoader::load(const QString& pUi) } -void UILoader::preparePlugIn(UIPlugIn* pUi, const QJsonObject& pMetaData) +void UiLoader::preparePlugin(UiPlugin* pUi, const QJsonObject& pMetaData) { setMetaDataProperties(pUi, pMetaData); const auto& key = getName(pUi->metaObject()); - mLoadedPlugIns.insert(key, pUi); + mLoadedPlugins.insert(key, pUi); connect(pUi, &QObject::destroyed, this, [this, key] { qCDebug(gui) << "Shutdown UI:" << key; - mLoadedPlugIns.remove(key); + mLoadedPlugins.remove(key); - if (mLoadedPlugIns.isEmpty()) + if (mLoadedPlugins.isEmpty()) { Q_EMIT fireRemovedAllPlugins(); } @@ -158,7 +159,7 @@ void UILoader::preparePlugIn(UIPlugIn* pUi, const QJsonObject& pMetaData) } -QStringList UILoader::getUserRequestOrDefault() +QStringList UiLoader::getUserRequestOrDefault() { if (!cUserRequest.isEmpty()) { @@ -169,7 +170,7 @@ QStringList UILoader::getUserRequestOrDefault() } -QString UILoader::getDefault() +QString UiLoader::getDefault() { const auto& list = getInitialDefault(); @@ -179,7 +180,7 @@ QString UILoader::getDefault() } -void UILoader::setUserRequest(const QStringList& pRequest) +void UiLoader::setUserRequest(const QStringList& pRequest) { if (pRequest.isEmpty()) { @@ -191,11 +192,11 @@ void UILoader::setUserRequest(const QStringList& pRequest) } -void UILoader::shutdown() +void UiLoader::shutdown() { - qCDebug(gui) << "Shutdown UILoader:" << mLoadedPlugIns.keys(); + qCDebug(gui) << "Shutdown UiLoader:" << mLoadedPlugins.keys(); - for (const auto& plugin : std::as_const(mLoadedPlugIns)) + for (const auto& plugin : std::as_const(mLoadedPlugins)) { // Plugins and therefore their members are not auto destructed due to a bug in Qt. // https://bugreports.qt.io/browse/QTBUG-17458 @@ -204,7 +205,7 @@ void UILoader::shutdown() } -void UILoader::setMetaDataProperties(UIPlugIn* pUi, const QJsonObject& pJson) +void UiLoader::setMetaDataProperties(UiPlugin* pUi, const QJsonObject& pJson) { const auto& fileContent = getMetaDataFileContent(pJson); const auto& iterEnd = fileContent.constEnd(); @@ -216,43 +217,55 @@ void UILoader::setMetaDataProperties(UIPlugIn* pUi, const QJsonObject& pJson) } -QJsonObject UILoader::getMetaDataFileContent(const QJsonObject& pJson) +QJsonObject UiLoader::getMetaDataFileContent(const QJsonObject& pJson) { return pJson.value(QLatin1String("MetaData")).toObject(); } -bool UILoader::isDefault(const QJsonObject& pJson) +bool UiLoader::isDefault(const QJsonObject& pJson) { return getMetaDataFileContent(pJson).value(QLatin1String("default")).toBool(); } -bool UILoader::isUserInteractive(const QJsonObject& pJson) +bool UiLoader::isUserInteractive(const QJsonObject& pJson) { return getMetaDataFileContent(pJson).value(QLatin1String("userInteractive")).toBool(); } -QString UILoader::getName(const QJsonObject& pJson) +QString UiLoader::getName(const QJsonObject& pJson) { return unify(pJson.value(QLatin1String("className")).toString()); } -QString UILoader::getName(const QMetaObject* pMeta) +QString UiLoader::getName(const QMetaObject* pMeta) { return unify(QString::fromLatin1(pMeta->className())); } -QString UILoader::unify(const QString& pName) +QString UiLoader::unify(const QString& pName) { return pName.toLower().remove(QLatin1String("governikus::")).remove(QLatin1String("uiplugin")); } -bool UILoader::isPlugIn(const QJsonObject& pJson) +bool UiLoader::isPlugin(const QJsonObject& pJson) { - return pJson.value(QLatin1String("IID")).toString() == QLatin1String("governikus.UIPlugIn"); + return pJson.value(QLatin1String("IID")).toString() == QLatin1String("governikus.UiPlugin"); +} + + +void UiLoader::setEnvironment(const QJsonObject& pJson) +{ + const auto& envMap = getMetaDataFileContent(pJson).value(QLatin1String("env")).toObject().toVariantMap(); + for (const auto [key, value] : envMap.asKeyValueRange()) + { + const auto stringValue = value.toString().toLatin1(); + qCDebug(gui) << "Set environment:" << key << "=" << stringValue; + qputenv(qPrintable(key), stringValue); + } } diff --git a/src/ui/base/UILoader.h b/src/ui/base/UiLoader.h similarity index 68% rename from src/ui/base/UILoader.h rename to src/ui/base/UiLoader.h index 2e8e50cd8..27a381164 100644 --- a/src/ui/base/UILoader.h +++ b/src/ui/base/UiLoader.h @@ -1,36 +1,36 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Loader to initialize UIPlugIns. + * \brief Loader to initialize UiPlugins. */ #pragma once #include "Env.h" -#include "UIPlugIn.h" +#include "UiPlugin.h" #include #include #include -class test_UILoader; +class test_UiLoader; namespace governikus { -class UILoader +class UiLoader : public QObject { Q_OBJECT friend class Env; - friend class ::test_UILoader; + friend class ::test_UiLoader; private: static QStringList cUserRequest; - QMap mLoadedPlugIns; + QMap mLoadedPlugins; [[nodiscard]] static QStringList getInitialDefault(); [[nodiscard]] static QString unify(const QString& pName); @@ -40,18 +40,19 @@ class UILoader [[nodiscard]] static inline bool isDefault(const QJsonObject& pJson); [[nodiscard]] static inline bool isUserInteractive(const QJsonObject& pJson); [[nodiscard]] static QStringList getUserRequestOrDefault(); - [[nodiscard]] static inline bool isPlugIn(const QJsonObject& pJson); - static inline void setMetaDataProperties(UIPlugIn* pUi, const QJsonObject& pJson); + [[nodiscard]] static inline bool isPlugin(const QJsonObject& pJson); + static void setEnvironment(const QJsonObject& pJson); + static inline void setMetaDataProperties(UiPlugin* pUi, const QJsonObject& pJson); #ifndef QT_NO_DEBUG public: #endif - UILoader(); - ~UILoader() override; + UiLoader(); + ~UiLoader() override; [[nodiscard]] bool load(const QString& pName); - void preparePlugIn(UIPlugIn* pUi, const QJsonObject& pMetaData); + void preparePlugin(UiPlugin* pUi, const QJsonObject& pMetaData); public: // do not make this non-static as the CommandLineParser spawns @@ -66,23 +67,23 @@ class UILoader [[nodiscard]] bool load(); template - [[nodiscard]] std::enable_if_t, bool> load() + [[nodiscard]] std::enable_if_t, bool> load() { return load(getName(&T::staticMetaObject)); } template - [[nodiscard]] std::enable_if_t, T*> getLoaded() const + [[nodiscard]] std::enable_if_t, T*> getLoaded() const { - return qobject_cast(mLoadedPlugIns.value(getName(&T::staticMetaObject))); + return qobject_cast(mLoadedPlugins.value(getName(&T::staticMetaObject))); } Q_INVOKABLE void shutdown(); Q_SIGNALS: - void fireLoadedPlugin(UIPlugIn* pPlugin); + void fireLoadedPlugin(UiPlugin* pPlugin); void fireRemovedAllPlugins(); }; diff --git a/src/ui/base/UiPlugin.cpp b/src/ui/base/UiPlugin.cpp new file mode 100644 index 000000000..2451189bc --- /dev/null +++ b/src/ui/base/UiPlugin.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiPlugin.h" + +using namespace governikus; + +void UiPlugin::onApplicationInitialized() +{ +} + + +void UiPlugin::onApplicationStarted() +{ +} + + +void UiPlugin::onShowUi(UiModule pModule) +{ + Q_UNUSED(pModule) +} + + +bool UiPlugin::initialize() +{ + return true; +} + + +void UiPlugin::onWorkflowUnhandled(const QSharedPointer& pRequest) +{ + Q_UNUSED(pRequest) +} + + +void UiPlugin::onHideUi() +{ +} + + +void UiPlugin::onTranslationChanged() +{ +} + + +void UiPlugin::onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) +{ + Q_UNUSED(pProxy) + Q_UNUSED(pAuthenticator) +} + + +void UiPlugin::onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) +{ + Q_UNUSED(pUi) + Q_UNUSED(pInformation) + Q_UNUSED(pAccepted) +} + + +void UiPlugin::onUiDominationReleased() +{ +} + + +void UiPlugin::onShowUserInformation(const QString& pInformationMessage) +{ + Q_UNUSED(pInformationMessage) +} diff --git a/src/ui/base/UIPlugIn.h b/src/ui/base/UiPlugin.h similarity index 83% rename from src/ui/base/UIPlugIn.h rename to src/ui/base/UiPlugin.h index a83db24cf..0a7f96795 100644 --- a/src/ui/base/UIPlugIn.h +++ b/src/ui/base/UiPlugin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -22,7 +22,7 @@ class WorkflowContext; /*! * UI modules that can be requested to show. */ -defineEnumType(UiModule, +defineEnumTypeQmlExposed(UiModule, CURRENT, DEFAULT, IDENTIFY, @@ -41,14 +41,14 @@ defineEnumType(UiModule, SMART_EID ) -class UIPlugIn +class UiPlugin : public QObject { Q_OBJECT public: - UIPlugIn() = default; - ~UIPlugIn() override = default; + UiPlugin() = default; + ~UiPlugin() override = default; [[nodiscard]] virtual bool initialize(); @@ -63,7 +63,7 @@ class UIPlugIn virtual void onHideUi(); virtual void onTranslationChanged(); virtual void onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator); - virtual void onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted); + virtual void onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted); virtual void onUiDominationReleased(); virtual void onShowUserInformation(const QString& pInformationMessage); @@ -75,11 +75,11 @@ class UIPlugIn void fireCloseReminderFinished(bool pDontRemindAgain); void fireApplicationActivated(); - void fireUiDominationRequest(const UIPlugIn* pUi, const QString& pInformation); + void fireUiDominationRequest(const UiPlugin* pUi, const QString& pInformation); void fireUiDominationRelease(); void fireRestartApplicationRequested(); }; } // namespace governikus -Q_DECLARE_INTERFACE(governikus::UIPlugIn, "governikus.UIPlugIn") +Q_DECLARE_INTERFACE(governikus::UiPlugin, "governikus.UiPlugin") diff --git a/src/ui/functional/AusweisApp2.cpp b/src/ui/functional/AusweisApp2.cpp index 612b6bb81..7c28fc704 100644 --- a/src/ui/functional/AusweisApp2.cpp +++ b/src/ui/functional/AusweisApp2.cpp @@ -1,16 +1,18 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "AusweisApp2_p.h" #include "Bootstrap.h" -#include "UILoader.h" -#include "UIPlugInFunctional.h" +#include "UiLoader.h" +#include "UiPluginFunctional.h" #include #include +#include +#include #include #include #include @@ -18,10 +20,11 @@ namespace { -static bool cInitialized = false; static bool cShutdownCalled = false; static AusweisApp2Callback cCallback = nullptr; static std::thread cThread; // clazy:exclude=non-pod-global-static +static std::future cStartedFuture; // clazy:exclude=non-pod-global-static +static std::promise cStartedPromise; // clazy:exclude=non-pod-global-static static std::mutex cMutex; } // namespace @@ -50,8 +53,7 @@ Q_DECL_EXPORT bool ausweisapp2_is_running_internal() Q_DECL_EXPORT void ausweisapp2_started_internal() { - const std::lock_guard lock(cMutex); - cInitialized = true; + cStartedPromise.set_value(); } @@ -105,6 +107,9 @@ Q_DECL_EXPORT bool ausweisapp2_init(AusweisApp2Callback pCallback, const char* p cCallback = pCallback; cShutdownCalled = false; + + cStartedPromise = std::promise(); + cStartedFuture = cStartedPromise.get_future(); cThread = std::thread(&ausweisapp2_init_internal, QByteArray(pCmdline)); return true; @@ -118,11 +123,14 @@ Q_DECL_EXPORT void ausweisapp2_shutdown(void) { if (!cShutdownCalled) { - cShutdownCalled = true; // do not request twice as the UILoader could be re-spawned after shutdown! + cShutdownCalled = true; // do not request twice as the UiLoader could be re-spawned after shutdown! + + cStartedFuture.wait(); + std::cout << "Send shutdown request" << std::endl; QMetaObject::invokeMethod(QCoreApplication::instance(), [] { - auto* j = Env::getSingleton()->getLoaded(); + auto* j = Env::getSingleton()->getLoaded(); if (j) { j->doQuitApplicationRequest(); @@ -147,14 +155,16 @@ Q_DECL_EXPORT void ausweisapp2_send(const char* pCmd) { const std::lock_guard lock(cMutex); - if (cShutdownCalled || !cInitialized || pCmd == nullptr) + using namespace std::chrono_literals; + const bool initialized = cStartedFuture.wait_for(0s) == std::future_status::ready; + if (cShutdownCalled || !initialized || pCmd == nullptr) { return; } const auto cmd = QByteArray(pCmd); QMetaObject::invokeMethod(QCoreApplication::instance(), [cmd] { - auto* j = Env::getSingleton()->getLoaded(); + auto* j = Env::getSingleton()->getLoaded(); if (j) { j->doMessageProcessing(cmd); diff --git a/src/ui/functional/AusweisApp2.h b/src/ui/functional/AusweisApp2.h index 8f78781c1..9bc780064 100644 --- a/src/ui/functional/AusweisApp2.h +++ b/src/ui/functional/AusweisApp2.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #ifndef AUSWEISAPP2_HEADER diff --git a/src/ui/functional/AusweisApp2_p.h b/src/ui/functional/AusweisApp2_p.h index 6387abbe8..8e803a4df 100644 --- a/src/ui/functional/AusweisApp2_p.h +++ b/src/ui/functional/AusweisApp2_p.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ui/functional/UIPlugInFunctional.cpp b/src/ui/functional/UiPluginFunctional.cpp similarity index 58% rename from src/ui/functional/UIPlugInFunctional.cpp rename to src/ui/functional/UiPluginFunctional.cpp index 1a21f4ae3..42a205a88 100644 --- a/src/ui/functional/UIPlugInFunctional.cpp +++ b/src/ui/functional/UiPluginFunctional.cpp @@ -1,15 +1,15 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInFunctional.h" +#include "UiPluginFunctional.h" #include "AusweisApp2_p.h" #include "AppSettings.h" #include "Env.h" #include "ReaderManager.h" -#include "UILoader.h" +#include "UiLoader.h" #include "WorkflowRequest.h" #include @@ -17,34 +17,34 @@ using namespace governikus; -UIPlugInFunctional::UIPlugInFunctional() - : UIPlugIn() +UiPluginFunctional::UiPluginFunctional() + : UiPlugin() , mJson(nullptr) , mContext() { } -bool UIPlugInFunctional::initialize() +bool UiPluginFunctional::initialize() { if (mJson) { return true; } - if (!Env::getSingleton()->load()) + if (!Env::getSingleton()->load()) { qWarning() << "Cannot start functional because JSON-API is missing"; return false; } - mJson = Env::getSingleton()->getLoaded(); - connect(mJson, &UIPlugInJson::fireMessage, this, &UIPlugInFunctional::onJsonMessage); + mJson = Env::getSingleton()->getLoaded(); + connect(mJson, &UiPluginJson::fireMessage, this, &UiPluginFunctional::onJsonMessage); return true; } -void UIPlugInFunctional::onApplicationStarted() +void UiPluginFunctional::onApplicationStarted() { ausweisapp2_started_internal(); auto callback = ausweisapp2_get_callback_internal(); @@ -57,19 +57,19 @@ void UIPlugInFunctional::onApplicationStarted() mJson->setEnabled(); callback(nullptr); - Env::getSingleton()->startScan(ReaderManagerPlugInType::SIMULATOR); + Env::getSingleton()->startScan(ReaderManagerPluginType::SIMULATOR); } -void UIPlugInFunctional::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginFunctional::onWorkflowStarted(const QSharedPointer& pRequest) { mContext = pRequest->getContext(); mContext->claim(this); #if defined(Q_OS_IOS) || defined(Q_OS_ANDROID) - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::NFC, ReaderManagerPlugInType::SIMULATOR}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::NFC, ReaderManagerPluginType::SIMULATOR}); #else - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::PCSC, ReaderManagerPlugInType::SIMULATOR}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::PCSC, ReaderManagerPluginType::SIMULATOR}); #endif #if !defined(Q_OS_IOS) @@ -78,7 +78,7 @@ void UIPlugInFunctional::onWorkflowStarted(const QSharedPointer } -void UIPlugInFunctional::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginFunctional::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) @@ -90,7 +90,7 @@ void UIPlugInFunctional::onWorkflowFinished(const QSharedPointerdoMessageProcessing(pMsg); } -void UIPlugInFunctional::doQuitApplicationRequest() +void UiPluginFunctional::doQuitApplicationRequest() { Q_EMIT fireQuitApplicationRequest(); } -void UIPlugInFunctional::doShutdown() +void UiPluginFunctional::doShutdown() { mJson->setEnabled(false); } diff --git a/src/ui/functional/UIPlugInFunctional.h b/src/ui/functional/UiPluginFunctional.h similarity index 60% rename from src/ui/functional/UIPlugInFunctional.h rename to src/ui/functional/UiPluginFunctional.h index 2cccc750e..86413b9e2 100644 --- a/src/ui/functional/UIPlugInFunctional.h +++ b/src/ui/functional/UiPluginFunctional.h @@ -1,28 +1,28 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the integrated SDK (C-API). + * \brief UiPlugin implementation of the integrated SDK (C-API). */ #pragma once -#include "UIPlugIn.h" -#include "UIPlugInJson.h" +#include "UiPlugin.h" +#include "UiPluginJson.h" namespace governikus { -class UIPlugInFunctional - : public UIPlugIn +class UiPluginFunctional + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) private: - QPointer mJson; + QPointer mJson; QSharedPointer mContext; private Q_SLOTS: @@ -37,8 +37,8 @@ class UIPlugInFunctional void doQuitApplicationRequest(); public: - UIPlugInFunctional(); - ~UIPlugInFunctional() override = default; + UiPluginFunctional(); + ~UiPluginFunctional() override = default; [[nodiscard]] bool initialize() override; }; diff --git a/src/ui/json/MessageDispatcher.cpp b/src/ui/json/MessageDispatcher.cpp index c65cfb7b5..223290740 100644 --- a/src/ui/json/MessageDispatcher.cpp +++ b/src/ui/json/MessageDispatcher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MessageDispatcher.h" @@ -20,6 +20,7 @@ #include "messages/MsgHandlerInternalError.h" #include "messages/MsgHandlerInvalid.h" #include "messages/MsgHandlerLog.h" +#include "messages/MsgHandlerPause.h" #include "messages/MsgHandlerReader.h" #include "messages/MsgHandlerReaderList.h" #include "messages/MsgHandlerStatus.h" @@ -165,9 +166,9 @@ Msg MessageDispatcher::processProgressChange() const } -QVector MessageDispatcher::processReaderChange(const ReaderInfo& pInfo) +QList MessageDispatcher::processReaderChange(const ReaderInfo& pInfo) { - QVector messages({MsgHandlerReader(pInfo)}); + QList messages({MsgHandlerReader(pInfo, mContext)}); const auto& lastStateMsg = mContext.getLastStateMsg(); if (lastStateMsg == MsgType::INSERT_CARD && !lastStateMsg) @@ -209,13 +210,27 @@ Msg MessageDispatcher::createForStateChange(MsgType pStateType) case MsgType::INSERT_CARD: return MsgHandlerInsertCard(mContext); + case MsgType::PAUSE: + if (getApiLevel() > MsgLevel::v2) + { + return MsgHandlerPause(); + } + Q_FALLTHROUGH(); + default: mContext.getContext()->setStateApproved(); + return MsgHandler::Void; } } +MsgLevel MessageDispatcher::getApiLevel() const +{ + return mContext.getApiLevel(); +} + + Msg MessageDispatcher::processCommand(const QByteArray& pMsg) { QJsonParseError jsonError {}; @@ -240,7 +255,7 @@ MsgHandler MessageDispatcher::createForCommand(const QJsonObject& pObj) return MsgHandlerInvalid(QLatin1String("Command cannot be undefined")); } - auto requestType = Enum::fromString(cmd, MsgCmdType::UNDEFINED); + const auto requestType = Enum::fromString(cmd, MsgCmdType::UNDEFINED); qCDebug(json) << "Process type:" << requestType; switch (requestType) { @@ -263,7 +278,7 @@ MsgHandler MessageDispatcher::createForCommand(const QJsonObject& pObj) return MsgHandlerApiLevel(pObj, mContext); case MsgCmdType::GET_READER: - return MsgHandlerReader(pObj); + return MsgHandlerReader(pObj, mContext); case MsgCmdType::GET_READER_LIST: return MsgHandlerReaderList(mContext); @@ -306,6 +321,9 @@ MsgHandler MessageDispatcher::createForCommand(const QJsonObject& pObj) } return HANDLE_CURRENT_STATE({MsgType::INSERT_CARD}, MsgHandlerInsertCard(pObj, mContext)); + case MsgCmdType::CONTINUE: + return HANDLE_CURRENT_STATE({MsgType::PAUSE}, MsgHandlerPause(mContext)); + case MsgCmdType::SET_PIN: return HANDLE_CURRENT_STATE({MsgType::ENTER_PIN}, MsgHandlerEnterPin(pObj, mContext)); @@ -387,17 +405,19 @@ MsgHandler MessageDispatcher::interrupt() #ifdef Q_OS_IOS { const auto allowedStates = {MsgType::ENTER_PIN, MsgType::ENTER_CAN, MsgType::ENTER_PUK, MsgType::ENTER_NEW_PIN}; - const auto lastPaceResult = mContext.getContext()->getLastPaceResult(); - return handleCurrentState(cmdType, allowedStates, [lastPaceResult] { - switch (lastPaceResult) + const auto& workflowContext = mContext.getContext(); + return handleCurrentState(cmdType, allowedStates, [&workflowContext] { + workflowContext->setInterruptRequested(true); + switch (workflowContext->getLastPaceResult()) { case CardReturnCode::OK: case CardReturnCode::OK_PUK: - Env::getSingleton()->stopScan(ReaderManagerPlugInType::NFC); // Null string is interpreted as 'success' + case CardReturnCode::OK_CAN: + Env::getSingleton()->stopScan(ReaderManagerPluginType::NFC); // Null string is interpreted as 'success' break; default: - Env::getSingleton()->stopScan(ReaderManagerPlugInType::NFC, Env::getSingleton()->getMessages().getSessionFailed()); + Env::getSingleton()->stopScan(ReaderManagerPluginType::NFC, Env::getSingleton()->getMessages().getSessionFailed()); } return MsgHandler::Void; diff --git a/src/ui/json/MessageDispatcher.h b/src/ui/json/MessageDispatcher.h index 9e9ff44f3..c62badead 100644 --- a/src/ui/json/MessageDispatcher.h +++ b/src/ui/json/MessageDispatcher.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -51,10 +51,11 @@ class MessageDispatcher [[nodiscard]] Msg init(const QSharedPointer& pWorkflowContext); [[nodiscard]] Msg finish(); void reset(); + [[nodiscard]] MsgLevel getApiLevel() const; [[nodiscard]] Msg processCommand(const QByteArray& pMsg); [[nodiscard]] Msg processStateChange(const QString& pState); [[nodiscard]] Msg processProgressChange() const; - [[nodiscard]] QVector processReaderChange(const ReaderInfo& pInfo); + [[nodiscard]] QList processReaderChange(const ReaderInfo& pInfo); #ifndef QT_NO_DEBUG void setSkipStateApprovedHook(const SkipStateApprovedHook& pHook); diff --git a/src/ui/json/UIPlugInJson.cpp b/src/ui/json/UiPluginJson.cpp similarity index 54% rename from src/ui/json/UIPlugInJson.cpp rename to src/ui/json/UiPluginJson.cpp index a7b577094..483c2ff84 100644 --- a/src/ui/json/UIPlugInJson.cpp +++ b/src/ui/json/UiPluginJson.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInJson.h" +#include "UiPluginJson.h" #include "ReaderManager.h" #include "WorkflowRequest.h" @@ -17,47 +17,47 @@ Q_DECLARE_LOGGING_CATEGORY(json) using namespace governikus; -UIPlugInJson::UIPlugInJson() - : UIPlugIn() +UiPluginJson::UiPluginJson() + : UiPlugin() , mMessageDispatcher() , mEnabled(false) { } -void UIPlugInJson::setEnabled(bool pEnable) +void UiPluginJson::setEnabled(bool pEnable) { + if (mEnabled == pEnable) + { + return; + } + mEnabled = pEnable; - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); if (mEnabled) { - connect(readerManager, &ReaderManager::fireReaderAdded, this, &UIPlugInJson::onReaderEvent); - connect(readerManager, &ReaderManager::fireReaderRemoved, this, &UIPlugInJson::onReaderEvent); - connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &UIPlugInJson::onReaderEvent); - connect(readerManager, &ReaderManager::fireCardInserted, this, &UIPlugInJson::onReaderEvent); - connect(readerManager, &ReaderManager::fireCardRemoved, this, &UIPlugInJson::onReaderEvent); - connect(readerManager, &ReaderManager::fireCardInfoChanged, this, &UIPlugInJson::onCardInfoChanged); + connect(readerManager, &ReaderManager::fireReaderAdded, this, &UiPluginJson::onReaderEvent); + connect(readerManager, &ReaderManager::fireReaderRemoved, this, &UiPluginJson::onReaderEvent); + connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &UiPluginJson::onReaderEvent); + connect(readerManager, &ReaderManager::fireCardInserted, this, &UiPluginJson::onCardInserted); + connect(readerManager, &ReaderManager::fireCardRemoved, this, &UiPluginJson::onReaderEvent); + connect(readerManager, &ReaderManager::fireCardInfoChanged, this, &UiPluginJson::onCardInfoChanged); } else { - disconnect(readerManager, &ReaderManager::fireReaderAdded, this, &UIPlugInJson::onReaderEvent); - disconnect(readerManager, &ReaderManager::fireReaderRemoved, this, &UIPlugInJson::onReaderEvent); - disconnect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &UIPlugInJson::onReaderEvent); - disconnect(readerManager, &ReaderManager::fireCardInserted, this, &UIPlugInJson::onReaderEvent); - disconnect(readerManager, &ReaderManager::fireCardRemoved, this, &UIPlugInJson::onReaderEvent); - disconnect(readerManager, &ReaderManager::fireCardInfoChanged, this, &UIPlugInJson::onCardInfoChanged); + readerManager->disconnect(this); } } -bool UIPlugInJson::isEnabled() const +bool UiPluginJson::isEnabled() const { return mEnabled; } -void UIPlugInJson::callFireMessage(const QByteArray& pMsg, bool pLogging) +void UiPluginJson::callFireMessage(const QByteArray& pMsg, bool pLogging) { if (!pMsg.isEmpty()) { @@ -70,7 +70,7 @@ void UIPlugInJson::callFireMessage(const QByteArray& pMsg, bool pLogging) } -void UIPlugInJson::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginJson::onWorkflowStarted(const QSharedPointer& pRequest) { if (!mEnabled) { @@ -80,15 +80,15 @@ void UIPlugInJson::onWorkflowStarted(const QSharedPointer& pReq const auto& context = pRequest->getContext(); if (context.objectCast() || context.objectCast()) { - connect(context.data(), &WorkflowContext::fireStateChanged, this, &UIPlugInJson::onStateChanged); - connect(context.data(), &WorkflowContext::fireProgressChanged, this, &UIPlugInJson::onProgressChanged); + connect(context.data(), &WorkflowContext::fireStateChanged, this, &UiPluginJson::onStateChanged); + connect(context.data(), &WorkflowContext::fireProgressChanged, this, &UiPluginJson::onProgressChanged); } callFireMessage(mMessageDispatcher.init(context)); } -void UIPlugInJson::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginJson::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) @@ -102,7 +102,7 @@ void UIPlugInJson::onWorkflowFinished(const QSharedPointer& pRe } -void UIPlugInJson::onCardInfoChanged(const ReaderInfo& pInfo) +void UiPluginJson::onCardInfoChanged(const ReaderInfo& pInfo) { if (pInfo.hasEid()) { @@ -111,7 +111,7 @@ void UIPlugInJson::onCardInfoChanged(const ReaderInfo& pInfo) } -void UIPlugInJson::onReaderEvent(const ReaderInfo& pInfo) +void UiPluginJson::onReaderEvent(const ReaderInfo& pInfo) { const auto& messages = mMessageDispatcher.processReaderChange(pInfo); for (const auto& msg : messages) @@ -121,19 +121,28 @@ void UIPlugInJson::onReaderEvent(const ReaderInfo& pInfo) } -void UIPlugInJson::onStateChanged(const QString& pNewState) +void UiPluginJson::onCardInserted(const ReaderInfo& pInfo) +{ + if (pInfo.hasEid() || (pInfo.hasCard() && mMessageDispatcher.getApiLevel() > MsgLevel::v2)) + { + onReaderEvent(pInfo); + } +} + + +void UiPluginJson::onStateChanged(const QString& pNewState) { callFireMessage(mMessageDispatcher.processStateChange(pNewState)); } -void UIPlugInJson::onProgressChanged() +void UiPluginJson::onProgressChanged() { callFireMessage(mMessageDispatcher.processProgressChange()); } -void UIPlugInJson::doMessageProcessing(const QByteArray& pMsg) +void UiPluginJson::doMessageProcessing(const QByteArray& pMsg) { if (!mEnabled) { @@ -145,6 +154,6 @@ void UIPlugInJson::doMessageProcessing(const QByteArray& pMsg) } -void UIPlugInJson::doShutdown() +void UiPluginJson::doShutdown() { } diff --git a/src/ui/json/UIPlugInJson.h b/src/ui/json/UiPluginJson.h similarity index 70% rename from src/ui/json/UIPlugInJson.h rename to src/ui/json/UiPluginJson.h index 2c7e058f6..a15af50e1 100644 --- a/src/ui/json/UIPlugInJson.h +++ b/src/ui/json/UiPluginJson.h @@ -1,29 +1,32 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the Json API. + * \brief UiPlugin implementation of the Json API. */ #pragma once #include "MessageDispatcher.h" -#include "UIPlugIn.h" -#include "context/WorkflowContext.h" +#include "UiPlugin.h" + +class test_UiPluginJson; class test_MsgHandlerAuth; class test_MsgHandlerPersonalization; + namespace governikus { -class UIPlugInJson - : public UIPlugIn +class UiPluginJson + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) + friend class ::test_UiPluginJson; friend class ::test_MsgHandlerAuth; friend class ::test_MsgHandlerPersonalization; @@ -34,8 +37,8 @@ class UIPlugInJson inline void callFireMessage(const QByteArray& pMsg, bool pLogging = true); public: - UIPlugInJson(); - ~UIPlugInJson() override = default; + UiPluginJson(); + ~UiPluginJson() override = default; void setEnabled(bool pEnable = true); [[nodiscard]] bool isEnabled() const; @@ -46,6 +49,7 @@ class UIPlugInJson void onWorkflowFinished(const QSharedPointer& pRequest) override; void onCardInfoChanged(const ReaderInfo& pInfo); void onReaderEvent(const ReaderInfo& pInfo); + void onCardInserted(const ReaderInfo& pInfo); void onStateChanged(const QString& pNewState); void onProgressChanged(); diff --git a/src/ui/json/messages/Msg.cpp b/src/ui/json/messages/Msg.cpp index 49f6109c0..af8cb2b76 100644 --- a/src/ui/json/messages/Msg.cpp +++ b/src/ui/json/messages/Msg.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "Msg.h" diff --git a/src/ui/json/messages/Msg.h b/src/ui/json/messages/Msg.h index 539e93f96..ce6e885fd 100644 --- a/src/ui/json/messages/Msg.h +++ b/src/ui/json/messages/Msg.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgContext.cpp b/src/ui/json/messages/MsgContext.cpp index 81593e92d..c93dabd9c 100644 --- a/src/ui/json/messages/MsgContext.cpp +++ b/src/ui/json/messages/MsgContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgContext.h" diff --git a/src/ui/json/messages/MsgContext.h b/src/ui/json/messages/MsgContext.h index 866799573..891f2630e 100644 --- a/src/ui/json/messages/MsgContext.h +++ b/src/ui/json/messages/MsgContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,7 +21,7 @@ class MsgContext private: MsgLevel mApiLevel; - QVector mStateMessages; + QList mStateMessages; bool mProgressStatus; QSharedPointer mContext; diff --git a/src/ui/json/messages/MsgHandler.cpp b/src/ui/json/messages/MsgHandler.cpp index 0e669553c..db4973077 100644 --- a/src/ui/json/messages/MsgHandler.cpp +++ b/src/ui/json/messages/MsgHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandler.h" @@ -8,12 +8,13 @@ #include "states/StateEnterNewPacePin.h" #include "states/StateEnterPacePassword.h" #include "states/StateSelectReader.h" +#include "states/StateUnfortunateCardPosition.h" #include using namespace governikus; -const MsgLevel MsgHandler::DEFAULT_MSG_LEVEL = MsgLevel::v2; +const MsgLevel MsgHandler::DEFAULT_MSG_LEVEL = MsgLevel::v3; const MsgHandler MsgHandler::Void = MsgHandler(); @@ -47,6 +48,10 @@ MsgType MsgHandler::getStateMsgType(const QString& pState, PacePasswordId pPassw { return MsgType::INSERT_CARD; } + else if (StateBuilder::isState(pState)) + { + return MsgType::PAUSE; + } return MsgType::VOID; } @@ -64,27 +69,27 @@ MsgHandler::MsgHandler(MsgType pType) , mVoid(false) , mJsonObject() { - mJsonObject[QLatin1String("msg")] = getEnumName(mType); + setValue(QLatin1String("msg"), getEnumName(mType)); } MsgHandler::MsgHandler(MsgType pType, const char* const pKey, const QString& pValue) : MsgHandler(pType) { - setValue(pKey, pValue); + setValue(QLatin1String(pKey), pValue); } MsgHandler::MsgHandler(MsgType pType, const char* const pKey, const QLatin1String pValue) : MsgHandler(pType) { - setValue(pKey, pValue); + setValue(QLatin1String(pKey), pValue); } QByteArray MsgHandler::toJson() const { - Q_ASSERT(mJsonObject[QLatin1String("msg")].isString()); + Q_ASSERT(isString(QLatin1String("msg"))); return QJsonDocument(mJsonObject).toJson(QJsonDocument::Compact); } @@ -119,47 +124,62 @@ void MsgHandler::setRequest(const QJsonObject& pRequest) const auto& requestValue = pRequest[requestName]; if (!requestValue.isUndefined()) { - mJsonObject[requestName] = requestValue; + setValue(requestName, requestValue); } } -void MsgHandler::setValue(const char* const pKey, const QString& pValue) +void MsgHandler::setVoid(bool pVoid) { - setValue(QLatin1String(pKey), pValue); + mVoid = pVoid; } -void MsgHandler::setValue(const QLatin1String pKey, const QLatin1String pValue) +void MsgHandler::setValue(const QLatin1String pKey, const QString& pValue) { - if (pValue.size()) + if (!pValue.isEmpty()) { - mJsonObject[pKey] = pValue; + setValue(pKey, QJsonValue(pValue)); } } -void MsgHandler::setValue(const char* const pKey, const QLatin1String pValue) +void MsgHandler::setValue(const QLatin1String pKey, const QLatin1String pValue) { - setValue(QLatin1String(pKey), pValue); + if (pValue.size()) + { + setValue(pKey, QJsonValue(pValue)); + } } -void MsgHandler::setVoid(bool pVoid) +void MsgHandler::setValue(const QLatin1String pKey, const QJsonValue& pValue) { - mVoid = pVoid; + mJsonObject[pKey] = pValue; } -void MsgHandler::setValue(const QLatin1String pKey, const QString& pValue) +void MsgHandler::insertJsonObject(const QJsonObject& pObject) { - if (!pValue.isEmpty()) + for (auto it = pObject.constBegin(); it != pObject.constEnd(); ++it) { - mJsonObject[pKey] = pValue; + mJsonObject.insert(it.key(), it.value()); } } +bool MsgHandler::contains(QLatin1StringView pKey) const +{ + return mJsonObject.contains(pKey); +} + + +bool MsgHandler::isString(const QLatin1String pKey) const +{ + return mJsonObject[pKey].isString(); +} + + MsgHandler::operator Msg() const { return Msg(getType(), getOutput()); diff --git a/src/ui/json/messages/MsgHandler.h b/src/ui/json/messages/MsgHandler.h index 47e6f7219..2ec5dff3d 100644 --- a/src/ui/json/messages/MsgHandler.h +++ b/src/ui/json/messages/MsgHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,22 +21,23 @@ class MsgHandler private: const MsgType mType; bool mVoid; + QJsonObject mJsonObject; MsgHandler(); protected: - QJsonObject mJsonObject; - explicit MsgHandler(MsgType pType); explicit MsgHandler(MsgType pType, const char* const pKey, const QString& pValue); explicit MsgHandler(MsgType pType, const char* const pKey, const QLatin1String pValue); + void setVoid(bool pVoid = true); void setValue(const QLatin1String pKey, const QString& pValue); - void setValue(const char* const pKey, const QString& pValue); void setValue(const QLatin1String pKey, const QLatin1String pValue); - void setValue(const char* const pKey, const QLatin1String pValue); + void setValue(const QLatin1String pKey, const QJsonValue& pValue); + void insertJsonObject(const QJsonObject& pObject); - void setVoid(bool pVoid = true); + bool contains(QLatin1StringView pKey) const; + bool isString(const QLatin1String pKey) const; public: static const MsgHandler Void; diff --git a/src/ui/json/messages/MsgHandlerAccessRights.cpp b/src/ui/json/messages/MsgHandlerAccessRights.cpp index 8e4317beb..d6fc0c2b3 100644 --- a/src/ui/json/messages/MsgHandlerAccessRights.cpp +++ b/src/ui/json/messages/MsgHandlerAccessRights.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerAccessRights.h" @@ -78,7 +78,7 @@ void MsgHandlerAccessRights::handleSetChatData(const QJsonArray& pChat, const QS setError(QLatin1String("No optional access rights available")); } - if (!mJsonObject.contains(QLatin1String("error"))) + if (!contains(QLatin1String("error"))) { *pContext->getAccessRightManager() = effectiveChat; } @@ -127,20 +127,20 @@ void MsgHandlerAccessRights::fillAccessRights(const QSharedPointergetRequiredAccessRights()); chat[QLatin1String("optional")] = getAccessRights(accessRightManager->getOptionalAccessRights()); chat[QLatin1String("effective")] = getAccessRights(accessRightManager->getEffectiveAccessRights()); - mJsonObject[QLatin1String("chat")] = chat; + setValue(QLatin1String("chat"), chat); #if __has_include("SmartManager.h") - mJsonObject[QLatin1String("acceptedEidTypes")] = getAcceptedEidTypes(pContext); + setValue(QLatin1String("acceptedEidTypes"), getAcceptedEidTypes(pContext)); #endif if (const auto& transactionInfo = pContext->getDidAuthenticateEac1()->getTransactionInfo(); !transactionInfo.isEmpty()) { - mJsonObject[QLatin1String("transactionInfo")] = transactionInfo; + setValue(QLatin1String("transactionInfo"), transactionInfo); } if (const QJsonObject& aux = getAuxiliaryData(pContext); !aux.isEmpty()) { - mJsonObject[QLatin1String("aux")] = aux; + setValue(QLatin1String("aux"), aux); } } @@ -178,5 +178,5 @@ QJsonObject MsgHandlerAccessRights::getAuxiliaryData(const QSharedPointer(pLevel); + setValue(QLatin1String("current"), static_cast(pLevel)); } @@ -64,5 +64,5 @@ void MsgHandlerApiLevel::setAvailableLevel() { availableApiLevel += static_cast(entry); } - mJsonObject[QLatin1String("available")] = availableApiLevel; + setValue(QLatin1String("available"), availableApiLevel); } diff --git a/src/ui/json/messages/MsgHandlerApiLevel.h b/src/ui/json/messages/MsgHandlerApiLevel.h index 3ae923b28..1e81baa08 100644 --- a/src/ui/json/messages/MsgHandlerApiLevel.h +++ b/src/ui/json/messages/MsgHandlerApiLevel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerAuth.cpp b/src/ui/json/messages/MsgHandlerAuth.cpp index ce52cc18b..39e11b8b6 100644 --- a/src/ui/json/messages/MsgHandlerAuth.cpp +++ b/src/ui/json/messages/MsgHandlerAuth.cpp @@ -1,11 +1,11 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerAuth.h" -#include "UILoader.h" -#include "UIPlugInJson.h" +#include "UiLoader.h" +#include "UiPluginJson.h" #include "controller/AuthController.h" #include @@ -41,7 +41,7 @@ MsgHandlerAuth::MsgHandlerAuth(const QJsonObject& pObj, MsgContext& pContext) setVoid(); return; } - Q_ASSERT(mJsonObject[QLatin1String("error")].isString()); + Q_ASSERT(isString(QLatin1String("error"))); } } @@ -51,7 +51,7 @@ MsgHandlerAuth::MsgHandlerAuth(const QSharedPointer& pContext) { Q_ASSERT(pContext); - mJsonObject[QLatin1String("result")] = ECardApiResult(pContext->getStatus(), pContext->getFailureCode()).toJson(); + setValue(QLatin1String("result"), ECardApiResult(pContext->getStatus(), pContext->getFailureCode()).toJson()); QString url; if (pContext->getRefreshUrl().isEmpty()) @@ -67,7 +67,7 @@ MsgHandlerAuth::MsgHandlerAuth(const QSharedPointer& pContext) url = pContext->getRefreshUrl().toString(); } - setValue("url", url); + setValue(QLatin1String("url"), url); } @@ -91,7 +91,7 @@ QUrl MsgHandlerAuth::createUrl(const QString& pUrl) void MsgHandlerAuth::initAuth(const QUrl& pTcTokenUrl) const { - auto* ui = Env::getSingleton()->getLoaded(); + auto* ui = Env::getSingleton()->getLoaded(); Q_ASSERT(ui); Q_EMIT ui->fireWorkflowRequested(AuthController::createWorkflowRequest(pTcTokenUrl)); } diff --git a/src/ui/json/messages/MsgHandlerAuth.h b/src/ui/json/messages/MsgHandlerAuth.h index 63d5b80f0..c14570420 100644 --- a/src/ui/json/messages/MsgHandlerAuth.h +++ b/src/ui/json/messages/MsgHandlerAuth.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerBadState.cpp b/src/ui/json/messages/MsgHandlerBadState.cpp index 31cfcf2fd..a377bbe5d 100644 --- a/src/ui/json/messages/MsgHandlerBadState.cpp +++ b/src/ui/json/messages/MsgHandlerBadState.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerBadState.h" @@ -11,6 +11,6 @@ MsgHandlerBadState::MsgHandlerBadState(MsgCmdType pType) { if (pType != MsgCmdType::UNDEFINED) { - mJsonObject[QLatin1String("error")] = getEnumName(pType); + setValue(QLatin1String("error"), getEnumName(pType)); } } diff --git a/src/ui/json/messages/MsgHandlerBadState.h b/src/ui/json/messages/MsgHandlerBadState.h index 6b3fc628f..fa0cc8a88 100644 --- a/src/ui/json/messages/MsgHandlerBadState.h +++ b/src/ui/json/messages/MsgHandlerBadState.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerCertificate.cpp b/src/ui/json/messages/MsgHandlerCertificate.cpp index 40d2a6fcd..016f654c7 100644 --- a/src/ui/json/messages/MsgHandlerCertificate.cpp +++ b/src/ui/json/messages/MsgHandlerCertificate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerCertificate.h" @@ -34,6 +34,6 @@ MsgHandlerCertificate::MsgHandlerCertificate(const MsgContext& pContext) validity[QLatin1String("effectiveDate")] = body.getCertificateEffectiveDate().toString(Qt::ISODate); validity[QLatin1String("expirationDate")] = body.getCertificateExpirationDate().toString(Qt::ISODate); - mJsonObject[QLatin1String("description")] = desc; - mJsonObject[QLatin1String("validity")] = validity; + setValue(QLatin1String("description"), desc); + setValue(QLatin1String("validity"), validity); } diff --git a/src/ui/json/messages/MsgHandlerCertificate.h b/src/ui/json/messages/MsgHandlerCertificate.h index 95f3a1cef..6fe7457ea 100644 --- a/src/ui/json/messages/MsgHandlerCertificate.h +++ b/src/ui/json/messages/MsgHandlerCertificate.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerChangePin.cpp b/src/ui/json/messages/MsgHandlerChangePin.cpp index f01b2c08b..a08f9b943 100644 --- a/src/ui/json/messages/MsgHandlerChangePin.cpp +++ b/src/ui/json/messages/MsgHandlerChangePin.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerChangePin.h" #include "Env.h" -#include "UILoader.h" -#include "UIPlugInJson.h" +#include "UiLoader.h" +#include "UiPluginJson.h" #include "controller/ChangePinController.h" using namespace governikus; @@ -24,7 +24,7 @@ MsgHandlerChangePin::MsgHandlerChangePin(const QJsonObject& pObj, MsgContext& pC setVoid(); handleWorkflowProperties(pObj, pContext); - auto* ui = Env::getSingleton()->getLoaded(); + auto* ui = Env::getSingleton()->getLoaded(); Q_ASSERT(ui); Q_EMIT ui->fireWorkflowRequested(ChangePinController::createWorkflowRequest()); } @@ -35,11 +35,11 @@ MsgHandlerChangePin::MsgHandlerChangePin(const QSharedPointergetLastPaceResult() == CardReturnCode::OK && !pContext->isWorkflowCancelled(); + setValue(QLatin1String("success"), pContext->getLastPaceResult() == CardReturnCode::OK && !pContext->isWorkflowCancelled()); const auto& failureCode = pContext->getFailureCode(); if (failureCode.has_value()) { - mJsonObject[QLatin1String("reason")] = Enum::getName(failureCode.value().getReason()); + setValue(QLatin1String("reason"), Enum::getName(failureCode.value().getReason())); } } diff --git a/src/ui/json/messages/MsgHandlerChangePin.h b/src/ui/json/messages/MsgHandlerChangePin.h index cf7b08e92..8e7ff4011 100644 --- a/src/ui/json/messages/MsgHandlerChangePin.h +++ b/src/ui/json/messages/MsgHandlerChangePin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerEnterCan.cpp b/src/ui/json/messages/MsgHandlerEnterCan.cpp index 7a849a4aa..9c23fe4ac 100644 --- a/src/ui/json/messages/MsgHandlerEnterCan.cpp +++ b/src/ui/json/messages/MsgHandlerEnterCan.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterCan.h" diff --git a/src/ui/json/messages/MsgHandlerEnterCan.h b/src/ui/json/messages/MsgHandlerEnterCan.h index f7ae59cef..a86b3c559 100644 --- a/src/ui/json/messages/MsgHandlerEnterCan.h +++ b/src/ui/json/messages/MsgHandlerEnterCan.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerEnterNewPin.cpp b/src/ui/json/messages/MsgHandlerEnterNewPin.cpp index 7dc2e17e4..6a8402fbe 100644 --- a/src/ui/json/messages/MsgHandlerEnterNewPin.cpp +++ b/src/ui/json/messages/MsgHandlerEnterNewPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterNewPin.h" diff --git a/src/ui/json/messages/MsgHandlerEnterNewPin.h b/src/ui/json/messages/MsgHandlerEnterNewPin.h index 7f6c50037..4556705bf 100644 --- a/src/ui/json/messages/MsgHandlerEnterNewPin.h +++ b/src/ui/json/messages/MsgHandlerEnterNewPin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerEnterNumber.cpp b/src/ui/json/messages/MsgHandlerEnterNumber.cpp index a73a48e35..cbcc7ce04 100644 --- a/src/ui/json/messages/MsgHandlerEnterNumber.cpp +++ b/src/ui/json/messages/MsgHandlerEnterNumber.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterNumber.h" @@ -14,23 +14,30 @@ using namespace governikus; MsgHandlerEnterNumber::MsgHandlerEnterNumber(MsgType pType, const MsgContext& pContext) : MsgHandler(pType) { - Q_ASSERT(pContext.getContext()); - setReader(pContext.getContext()); + setReader(pContext); +} + + +void MsgHandlerEnterNumber::setError(const QLatin1String pError) +{ + setValue(QLatin1String("error"), pError); } void MsgHandlerEnterNumber::setError(const QString& pError) { - mJsonObject[QLatin1String("error")] = pError; + setValue(QLatin1String("error"), pError); } -void MsgHandlerEnterNumber::setReader(const QSharedPointer& pContext) +void MsgHandlerEnterNumber::setReader(const MsgContext& pContext) { - const auto& info = pContext->getExpectedReader(); + Q_ASSERT(pContext.getContext()); + + const auto& info = pContext.getContext()->getExpectedReader(); if (!info.getName().isEmpty()) { - mJsonObject[QLatin1String("reader")] = MsgHandlerReader::createReaderInfo(info); + setValue(QLatin1String("reader"), MsgHandlerReader::createReaderInfo(info, pContext)); } } @@ -42,7 +49,7 @@ void MsgHandlerEnterNumber::parseValue(const QJsonObject& pObj, const auto& reader = pContext.getContext()->getReaderName(); if (reader.isEmpty()) { - setError(QStringLiteral("No card inserted")); + setError(QLatin1String("No card inserted")); return; } @@ -52,13 +59,13 @@ void MsgHandlerEnterNumber::parseValue(const QJsonObject& pObj, { if (value.isUndefined()) { - setError(QStringLiteral("Value cannot be undefined")); + setError(QLatin1String("Value cannot be undefined")); return; } if (!value.isString()) { - setError(QStringLiteral("Invalid value")); + setError(QLatin1String("Invalid value")); return; } @@ -88,7 +95,7 @@ void MsgHandlerEnterNumber::parseValue(const QJsonObject& pObj, } else { - setError(QStringLiteral("Value cannot be defined")); + setError(QLatin1String("Value cannot be defined")); } } } diff --git a/src/ui/json/messages/MsgHandlerEnterNumber.h b/src/ui/json/messages/MsgHandlerEnterNumber.h index 75d6e9c2f..1c35a54e0 100644 --- a/src/ui/json/messages/MsgHandlerEnterNumber.h +++ b/src/ui/json/messages/MsgHandlerEnterNumber.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -22,8 +22,9 @@ class MsgHandlerEnterNumber : public MsgHandler { private: + void setError(const QLatin1String pError); void setError(const QString& pError); - void setReader(const QSharedPointer& pContext); + void setReader(const MsgContext& pContext); protected: explicit MsgHandlerEnterNumber(MsgType pType, const MsgContext& pContext); diff --git a/src/ui/json/messages/MsgHandlerEnterPin.cpp b/src/ui/json/messages/MsgHandlerEnterPin.cpp index 9ba124d31..3a970c0fb 100644 --- a/src/ui/json/messages/MsgHandlerEnterPin.cpp +++ b/src/ui/json/messages/MsgHandlerEnterPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterPin.h" diff --git a/src/ui/json/messages/MsgHandlerEnterPin.h b/src/ui/json/messages/MsgHandlerEnterPin.h index 04d5f99a4..29313f497 100644 --- a/src/ui/json/messages/MsgHandlerEnterPin.h +++ b/src/ui/json/messages/MsgHandlerEnterPin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerEnterPuk.cpp b/src/ui/json/messages/MsgHandlerEnterPuk.cpp index a0453f290..d0f73bff6 100644 --- a/src/ui/json/messages/MsgHandlerEnterPuk.cpp +++ b/src/ui/json/messages/MsgHandlerEnterPuk.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterPuk.h" diff --git a/src/ui/json/messages/MsgHandlerEnterPuk.h b/src/ui/json/messages/MsgHandlerEnterPuk.h index 9c041acf4..6f8e89a95 100644 --- a/src/ui/json/messages/MsgHandlerEnterPuk.h +++ b/src/ui/json/messages/MsgHandlerEnterPuk.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerInfo.cpp b/src/ui/json/messages/MsgHandlerInfo.cpp index cf1d98241..2b806467c 100644 --- a/src/ui/json/messages/MsgHandlerInfo.cpp +++ b/src/ui/json/messages/MsgHandlerInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerInfo.h" @@ -16,16 +16,5 @@ using namespace governikus; MsgHandlerInfo::MsgHandlerInfo() : MsgHandler(MsgType::INFO) { - mJsonObject[QLatin1String("VersionInfo")] = VersionInfo::getInstance().toJsonObject(); - - QString localIfd = QStringLiteral("UNKNOWN"); -#ifdef Q_OS_ANDROID - const auto& localIfdInfo = Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::LOCAL_IFD); - if (localIfdInfo.hasValue(ReaderManagerPlugInInfo::Key::LOCAL_IFD_STATE)) - { - localIfd = localIfdInfo.getValue(ReaderManagerPlugInInfo::Key::LOCAL_IFD_STATE).toString(); - } -#endif - - mJsonObject[QLatin1String("AusweisApp")] = localIfd; + setValue(QLatin1String("VersionInfo"), VersionInfo::getInstance().toJsonObject()); } diff --git a/src/ui/json/messages/MsgHandlerInfo.h b/src/ui/json/messages/MsgHandlerInfo.h index 19d8c33be..ced9f5d12 100644 --- a/src/ui/json/messages/MsgHandlerInfo.h +++ b/src/ui/json/messages/MsgHandlerInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerInsertCard.cpp b/src/ui/json/messages/MsgHandlerInsertCard.cpp index ffc1581ae..e9cc5f6eb 100644 --- a/src/ui/json/messages/MsgHandlerInsertCard.cpp +++ b/src/ui/json/messages/MsgHandlerInsertCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerInsertCard.h" @@ -42,13 +42,13 @@ MsgHandlerInsertCard::MsgHandlerInsertCard(const QJsonObject& pObj, MsgContext& if (value.isUndefined()) { - setError(QStringLiteral("Name cannot be undefined")); + setError(QLatin1String("Name cannot be undefined")); return; } if (!value.isString()) { - setError(QStringLiteral("Invalid name")); + setError(QLatin1String("Invalid name")); return; } @@ -56,23 +56,23 @@ MsgHandlerInsertCard::MsgHandlerInsertCard(const QJsonObject& pObj, MsgContext& const auto& readerInfo = Env::getSingleton()->getReaderInfo(value.toString()); if (!readerInfo.isValid()) { - setError(QStringLiteral("Unknown reader name")); + setError(QLatin1String("Unknown reader name")); return; } if (!readerInfo.isInsertable()) { - setError(QStringLiteral("Card is not insertable")); + setError(QLatin1String("Card is not insertable")); return; } QVariant data; - if (readerInfo.getPlugInType() == ReaderManagerPlugInType::SIMULATOR) + if (readerInfo.getPluginType() == ReaderManagerPluginType::SIMULATOR) { const auto& filesValue = pObj[QLatin1String("simulator")]; if (!filesValue.isUndefined() && !filesValue.isObject()) { - setError(QStringLiteral("Parameter 'simulator' is invalid")); + setError(QLatin1String("Parameter 'simulator' is invalid")); return; } data = filesValue.toObject(); @@ -83,7 +83,7 @@ MsgHandlerInsertCard::MsgHandlerInsertCard(const QJsonObject& pObj, MsgContext& } -void MsgHandlerInsertCard::setError(const QString& pError) +void MsgHandlerInsertCard::setError(const QLatin1String pError) { - setValue("error", pError); + setValue(QLatin1String("error"), pError); } diff --git a/src/ui/json/messages/MsgHandlerInsertCard.h b/src/ui/json/messages/MsgHandlerInsertCard.h index f07860556..8e44f3c2a 100644 --- a/src/ui/json/messages/MsgHandlerInsertCard.h +++ b/src/ui/json/messages/MsgHandlerInsertCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,7 +18,7 @@ class MsgHandlerInsertCard : public MsgHandler { private: - void setError(const QString& pError); + void setError(const QLatin1String pError); public: MsgHandlerInsertCard(); diff --git a/src/ui/json/messages/MsgHandlerInternalError.cpp b/src/ui/json/messages/MsgHandlerInternalError.cpp index c755dee55..7521caef3 100644 --- a/src/ui/json/messages/MsgHandlerInternalError.cpp +++ b/src/ui/json/messages/MsgHandlerInternalError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerInternalError.h" diff --git a/src/ui/json/messages/MsgHandlerInternalError.h b/src/ui/json/messages/MsgHandlerInternalError.h index 872c96057..660af873b 100644 --- a/src/ui/json/messages/MsgHandlerInternalError.h +++ b/src/ui/json/messages/MsgHandlerInternalError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerInvalid.cpp b/src/ui/json/messages/MsgHandlerInvalid.cpp index 4edcf1145..96b942a1e 100644 --- a/src/ui/json/messages/MsgHandlerInvalid.cpp +++ b/src/ui/json/messages/MsgHandlerInvalid.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerInvalid.h" diff --git a/src/ui/json/messages/MsgHandlerInvalid.h b/src/ui/json/messages/MsgHandlerInvalid.h index be2f9fe9c..684f690e0 100644 --- a/src/ui/json/messages/MsgHandlerInvalid.h +++ b/src/ui/json/messages/MsgHandlerInvalid.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerLog.cpp b/src/ui/json/messages/MsgHandlerLog.cpp index b2c1e3ee9..b6408e54e 100644 --- a/src/ui/json/messages/MsgHandlerLog.cpp +++ b/src/ui/json/messages/MsgHandlerLog.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerLog.h" @@ -13,5 +13,5 @@ MsgHandlerLog::MsgHandlerLog() : MsgHandler(MsgType::LOG) { const auto& data = Env::getSingleton()->getBacklog(); - mJsonObject[QLatin1String("data")] = QString::fromUtf8(data); + setValue(QLatin1String("data"), QString::fromUtf8(data)); } diff --git a/src/ui/json/messages/MsgHandlerLog.h b/src/ui/json/messages/MsgHandlerLog.h index 2b0225ad7..5c1c5c584 100644 --- a/src/ui/json/messages/MsgHandlerLog.h +++ b/src/ui/json/messages/MsgHandlerLog.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerPause.cpp b/src/ui/json/messages/MsgHandlerPause.cpp new file mode 100644 index 000000000..10c0269ff --- /dev/null +++ b/src/ui/json/messages/MsgHandlerPause.cpp @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "MsgHandlerPause.h" + +#include + +using namespace governikus; + + +MsgHandlerPause::MsgHandlerPause() + : MsgHandler(MsgType::PAUSE) +{ + setCause(QLatin1String("BadCardPosition")); +} + + +MsgHandlerPause::MsgHandlerPause(MsgContext& pContext) + : MsgHandlerPause() +{ + Q_ASSERT(pContext.getContext()); + + pContext.getContext()->setStateApproved(); + setVoid(); +} + + +void MsgHandlerPause::setCause(const QLatin1String pCause) +{ + setValue(QLatin1String("cause"), pCause); +} diff --git a/src/ui/json/messages/MsgHandlerPause.h b/src/ui/json/messages/MsgHandlerPause.h new file mode 100644 index 000000000..2285a3550 --- /dev/null +++ b/src/ui/json/messages/MsgHandlerPause.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +/*! + * \brief Message PAUSE of JSON API. + */ + +#pragma once + +#include "MsgContext.h" +#include "MsgHandler.h" + +namespace governikus +{ + +class MsgHandlerPause + : public MsgHandler +{ + private: + void setCause(const QLatin1String pCause); + + public: + explicit MsgHandlerPause(); + explicit MsgHandlerPause(MsgContext& pContext); +}; + +} // namespace governikus diff --git a/src/ui/json/messages/MsgHandlerPersonalization.cpp b/src/ui/json/messages/MsgHandlerPersonalization.cpp index 8e840e7d0..c040cebab 100644 --- a/src/ui/json/messages/MsgHandlerPersonalization.cpp +++ b/src/ui/json/messages/MsgHandlerPersonalization.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerPersonalization.h" #if __has_include("controller/PersonalizationController.h") - #include "UILoader.h" - #include "UIPlugInJson.h" + #include "UiLoader.h" + #include "UiPluginJson.h" #include "controller/PersonalizationController.h" using namespace governikus; @@ -39,7 +39,7 @@ MsgHandlerPersonalization::MsgHandlerPersonalization(const QJsonObject& pObj, Ms setVoid(); return; } - Q_ASSERT(mJsonObject[QLatin1String("error")].isString()); + Q_ASSERT(isString(QLatin1String("error"))); } } @@ -48,7 +48,7 @@ MsgHandlerPersonalization::MsgHandlerPersonalization(const QSharedPointergetStatus()).toJson(); + setValue(QLatin1String("result"), ECardApiResult(pContext->getStatus()).toJson()); } @@ -66,7 +66,7 @@ QString MsgHandlerPersonalization::createUrl(const QString& pUrl) void MsgHandlerPersonalization::initPersonalization(const QString& pAppletServiceURL) { - auto* ui = Env::getSingleton()->getLoaded(); + auto* ui = Env::getSingleton()->getLoaded(); Q_ASSERT(ui); Q_EMIT ui->fireWorkflowRequested(PersonalizationController::createWorkflowRequest(pAppletServiceURL)); } diff --git a/src/ui/json/messages/MsgHandlerPersonalization.h b/src/ui/json/messages/MsgHandlerPersonalization.h index 9c3089e2c..879d099bf 100644 --- a/src/ui/json/messages/MsgHandlerPersonalization.h +++ b/src/ui/json/messages/MsgHandlerPersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerReader.cpp b/src/ui/json/messages/MsgHandlerReader.cpp index 86138c415..d9bfc4329 100644 --- a/src/ui/json/messages/MsgHandlerReader.cpp +++ b/src/ui/json/messages/MsgHandlerReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerReader.h" @@ -8,7 +8,7 @@ using namespace governikus; -MsgHandlerReader::MsgHandlerReader(const QJsonObject& pObj) +MsgHandlerReader::MsgHandlerReader(const QJsonObject& pObj, const MsgContext& pContext) : MsgHandler(MsgType::READER) { const auto& jsonName = pObj[QLatin1String("name")]; @@ -22,64 +22,63 @@ MsgHandlerReader::MsgHandlerReader(const QJsonObject& pObj) } else { - setReaderInfo(Env::getSingleton()->getReaderInfo(jsonName.toString())); + setReaderInfo(Env::getSingleton()->getReaderInfo(jsonName.toString()), pContext); } } -MsgHandlerReader::MsgHandlerReader(const ReaderInfo& pInfo) +MsgHandlerReader::MsgHandlerReader(const ReaderInfo& pInfo, const MsgContext& pContext) : MsgHandler(MsgType::READER) { Q_ASSERT(!pInfo.getName().isEmpty()); - setReaderInfo(pInfo); + setReaderInfo(pInfo, pContext); } void MsgHandlerReader::setError(const QLatin1String pError) { - mJsonObject[QLatin1String("error")] = pError; + setValue(QLatin1String("error"), pError); } -void MsgHandlerReader::setReaderInfo(const ReaderInfo& pInfo) +void MsgHandlerReader::setReaderInfo(const ReaderInfo& pInfo, const MsgContext& pContext) { - setReaderInfo(mJsonObject, pInfo); + insertJsonObject(createReaderInfo(pInfo, pContext)); } -QJsonObject MsgHandlerReader::createReaderInfo(const ReaderInfo& pInfo) +QJsonObject MsgHandlerReader::createReaderInfo(const ReaderInfo& pInfo, const MsgContext& pContext) { Q_ASSERT(!pInfo.getName().isEmpty()); QJsonObject obj; - setReaderInfo(obj, pInfo); - return obj; -} - -void MsgHandlerReader::setReaderInfo(QJsonObject& pObj, const ReaderInfo& pInfo) -{ const bool known = pInfo.isValid(); - pObj[QLatin1String("name")] = pInfo.getName(); - pObj[QLatin1String("attached")] = known; + obj[QLatin1String("name")] = pInfo.getName(); + obj[QLatin1String("attached")] = known; if (known) { - pObj[QLatin1String("insertable")] = pInfo.isInsertable(); - pObj[QLatin1String("keypad")] = !pInfo.isBasicReader(); + obj[QLatin1String("insertable")] = pInfo.isInsertable(); + obj[QLatin1String("keypad")] = !pInfo.isBasicReader(); - if (pInfo.hasEid()) + if (pInfo.hasEid() || (pInfo.hasCard() && pContext.getApiLevel() > MsgLevel::v2)) { QJsonObject card; + if (pInfo.hasEid()) + { #if __has_include("SmartManager.h") - card[QLatin1String("eidType")] = Enum::getName(static_cast(pInfo.getCardInfo().getMobileEidType())); + card[QLatin1String("eidType")] = Enum::getName(static_cast(pInfo.getCardInfo().getMobileEidType())); #endif - card[QLatin1String("deactivated")] = pInfo.isPinDeactivated(); - card[QLatin1String("inoperative")] = pInfo.isPukInoperative(); - card[QLatin1String("retryCounter")] = pInfo.getRetryCounter(); - pObj[QLatin1String("card")] = card; + card[QLatin1String("deactivated")] = pInfo.isPinDeactivated(); + card[QLatin1String("inoperative")] = pInfo.isPukInoperative(); + card[QLatin1String("retryCounter")] = pInfo.getRetryCounter(); + } + obj[QLatin1String("card")] = card; } else { - pObj[QLatin1String("card")] = QJsonValue::Null; + obj[QLatin1String("card")] = QJsonValue::Null; } } + + return obj; } diff --git a/src/ui/json/messages/MsgHandlerReader.h b/src/ui/json/messages/MsgHandlerReader.h index 163113858..c2f6d4966 100644 --- a/src/ui/json/messages/MsgHandlerReader.h +++ b/src/ui/json/messages/MsgHandlerReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,6 +8,7 @@ #pragma once +#include "MsgContext.h" #include "MsgHandler.h" #include "ReaderInfo.h" @@ -18,16 +19,14 @@ class MsgHandlerReader : public MsgHandler { private: - static void setReaderInfo(QJsonObject& pObj, const ReaderInfo& pInfo); - void setError(const QLatin1String pError); - void setReaderInfo(const ReaderInfo& pInfo); + void setReaderInfo(const ReaderInfo& pInfo, const MsgContext& pContext); public: - static QJsonObject createReaderInfo(const ReaderInfo& pInfo); + static QJsonObject createReaderInfo(const ReaderInfo& pInfo, const MsgContext& pContext); - explicit MsgHandlerReader(const QJsonObject& pObj); - explicit MsgHandlerReader(const ReaderInfo& pInfo); + explicit MsgHandlerReader(const QJsonObject& pObj, const MsgContext& pContext); + explicit MsgHandlerReader(const ReaderInfo& pInfo, const MsgContext& pContext); }; diff --git a/src/ui/json/messages/MsgHandlerReaderList.cpp b/src/ui/json/messages/MsgHandlerReaderList.cpp index dd26fa662..438670418 100644 --- a/src/ui/json/messages/MsgHandlerReaderList.cpp +++ b/src/ui/json/messages/MsgHandlerReaderList.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerReaderList.h" @@ -18,9 +18,9 @@ MsgHandlerReaderList::MsgHandlerReaderList(const MsgContext& pContext) const auto& infoList = Env::getSingleton()->getReaderInfos(); for (const auto& info : infoList) { - reader += MsgHandlerReader::createReaderInfo(info); + reader += MsgHandlerReader::createReaderInfo(info, pContext); } const QLatin1String parameterName = pContext.getApiLevel() >= MsgLevel::v2 ? QLatin1String("readers") : QLatin1String("reader"); - mJsonObject[parameterName] = reader; + setValue(parameterName, reader); } diff --git a/src/ui/json/messages/MsgHandlerReaderList.h b/src/ui/json/messages/MsgHandlerReaderList.h index 176a90ad0..e27a22516 100644 --- a/src/ui/json/messages/MsgHandlerReaderList.h +++ b/src/ui/json/messages/MsgHandlerReaderList.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerStatus.cpp b/src/ui/json/messages/MsgHandlerStatus.cpp index 81fae2d12..b17a2c7df 100644 --- a/src/ui/json/messages/MsgHandlerStatus.cpp +++ b/src/ui/json/messages/MsgHandlerStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerStatus.h" @@ -9,9 +9,9 @@ using namespace governikus; MsgHandlerStatus::MsgHandlerStatus(const MsgContext& pContext) : MsgHandler(MsgType::STATUS) { - mJsonObject[QLatin1String("workflow")] = getWorkflow(pContext); - mJsonObject[QLatin1String("progress")] = getProgress(pContext); - mJsonObject[QLatin1String("state")] = getState(pContext); + setValue(QLatin1String("workflow"), getWorkflow(pContext)); + setValue(QLatin1String("progress"), getProgress(pContext)); + setValue(QLatin1String("state"), getState(pContext)); } diff --git a/src/ui/json/messages/MsgHandlerStatus.h b/src/ui/json/messages/MsgHandlerStatus.h index 119b7b386..78855aa15 100644 --- a/src/ui/json/messages/MsgHandlerStatus.h +++ b/src/ui/json/messages/MsgHandlerStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerUnknownCommand.cpp b/src/ui/json/messages/MsgHandlerUnknownCommand.cpp index 86aea6e45..aa169728b 100644 --- a/src/ui/json/messages/MsgHandlerUnknownCommand.cpp +++ b/src/ui/json/messages/MsgHandlerUnknownCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerUnknownCommand.h" diff --git a/src/ui/json/messages/MsgHandlerUnknownCommand.h b/src/ui/json/messages/MsgHandlerUnknownCommand.h index 9bed67175..4283003a7 100644 --- a/src/ui/json/messages/MsgHandlerUnknownCommand.h +++ b/src/ui/json/messages/MsgHandlerUnknownCommand.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgHandlerWorkflows.cpp b/src/ui/json/messages/MsgHandlerWorkflows.cpp index e167b587c..a3169d509 100644 --- a/src/ui/json/messages/MsgHandlerWorkflows.cpp +++ b/src/ui/json/messages/MsgHandlerWorkflows.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerWorkflows.h" @@ -62,5 +62,5 @@ void MsgHandlerWorkflows::initProgressStatus(const QJsonValue& pValue, MsgContex void MsgHandlerWorkflows::setError(const QLatin1String pError) { - setValue("error", pError); + setValue(QLatin1String("error"), pError); } diff --git a/src/ui/json/messages/MsgHandlerWorkflows.h b/src/ui/json/messages/MsgHandlerWorkflows.h index c8b9dd326..7876edc1c 100644 --- a/src/ui/json/messages/MsgHandlerWorkflows.h +++ b/src/ui/json/messages/MsgHandlerWorkflows.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/json/messages/MsgTypes.cpp b/src/ui/json/messages/MsgTypes.cpp index c474e635d..71e040c92 100644 --- a/src/ui/json/messages/MsgTypes.cpp +++ b/src/ui/json/messages/MsgTypes.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgTypes.h" diff --git a/src/ui/json/messages/MsgTypes.h b/src/ui/json/messages/MsgTypes.h index ad5df9c7c..7eb483e58 100644 --- a/src/ui/json/messages/MsgTypes.h +++ b/src/ui/json/messages/MsgTypes.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,6 +15,7 @@ namespace governikus defineEnumType(MsgLevel // See MsgHandler::DEFAULT_MSG_LEVEL , v1 = 1 , v2 = 2 + , v3 = 3 ) defineEnumType(MsgType, @@ -38,12 +39,14 @@ defineEnumType(MsgType, ENTER_PIN, ENTER_NEW_PIN, ENTER_CAN, - ENTER_PUK) + ENTER_PUK, + PAUSE) defineEnumType(MsgCmdType, UNDEFINED, ACCEPT, CANCEL, + CONTINUE, INTERRUPT, GET_STATUS, GET_LOG, diff --git a/src/ui/local_ifd/UIPlugInLocalIfd.cpp b/src/ui/local_ifd/UiPluginLocalIfd.cpp similarity index 73% rename from src/ui/local_ifd/UIPlugInLocalIfd.cpp rename to src/ui/local_ifd/UiPluginLocalIfd.cpp index 372c25242..95a42e1f1 100644 --- a/src/ui/local_ifd/UIPlugInLocalIfd.cpp +++ b/src/ui/local_ifd/UiPluginLocalIfd.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInLocalIfd.h" +#include "UiPluginLocalIfd.h" #include "Env.h" #include "LocalIfdServer.h" @@ -12,7 +12,7 @@ #ifdef Q_OS_ANDROID #include "AppSettings.h" - #include "UILoader.h" + #include "UiLoader.h" #include #include @@ -23,7 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(ifd) using namespace governikus; -void UIPlugInLocalIfd::onStateChanged(const QString& pNewState) +void UiPluginLocalIfd::onStateChanged(const QString& pNewState) { Q_UNUSED(pNewState) if (mContext) @@ -33,7 +33,7 @@ void UIPlugInLocalIfd::onStateChanged(const QString& pNewState) } -void UIPlugInLocalIfd::onConnectedChanged(bool pConnected) +void UiPluginLocalIfd::onConnectedChanged(bool pConnected) { if (!pConnected) { @@ -42,44 +42,44 @@ void UIPlugInLocalIfd::onConnectedChanged(bool pConnected) } -void UIPlugInLocalIfd::onSocketError(QAbstractSocket::SocketError pSocketError) +void UiPluginLocalIfd::onSocketError(QAbstractSocket::SocketError pSocketError) { Q_UNUSED(pSocketError) Q_EMIT fireQuitApplicationRequest(EXIT_FAILURE); } -UIPlugInLocalIfd::UIPlugInLocalIfd() - : UIPlugIn() +UiPluginLocalIfd::UiPluginLocalIfd() + : UiPlugin() , mContext() { } -void UIPlugInLocalIfd::doShutdown() +void UiPluginLocalIfd::doShutdown() { } -void UIPlugInLocalIfd::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginLocalIfd::onWorkflowStarted(const QSharedPointer& pRequest) { mContext = pRequest->getContext(); mContext->claim(this); - connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UIPlugInLocalIfd::onStateChanged); + connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UiPluginLocalIfd::onStateChanged); } -void UIPlugInLocalIfd::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginLocalIfd::onWorkflowFinished(const QSharedPointer& pRequest) { Q_ASSERT(mContext == pRequest->getContext()); - disconnect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UIPlugInLocalIfd::onStateChanged); + disconnect(mContext.data(), &WorkflowContext::fireStateChanged, this, &UiPluginLocalIfd::onStateChanged); mContext.reset(); } -bool UIPlugInLocalIfd::onStartWorkflowRequested(const QString& pPsk) +bool UiPluginLocalIfd::onStartWorkflowRequested(const QString& pPsk) { if (const auto minPskSize = Env::getSingleton()->getLocalIfdMinPskSize(); (pPsk.toUtf8().size() * CHAR_BIT) < minPskSize) @@ -95,15 +95,15 @@ bool UIPlugInLocalIfd::onStartWorkflowRequested(const QString& pPsk) return false; } - connect(localIfdServer.data(), &IfdServer::fireConnectedChanged, this, &UIPlugInLocalIfd::onConnectedChanged); - connect(localIfdServer.data(), &IfdServer::fireSocketError, this, &UIPlugInLocalIfd::onSocketError); + connect(localIfdServer.data(), &IfdServer::fireConnectedChanged, this, &UiPluginLocalIfd::onConnectedChanged); + connect(localIfdServer.data(), &IfdServer::fireSocketError, this, &UiPluginLocalIfd::onSocketError); Q_EMIT fireWorkflowRequested(WorkflowRequest::create(localIfdServer)); return localIfdServer->isRunning(); } -void UIPlugInLocalIfd::onAbortWorkflowRequested() +void UiPluginLocalIfd::onAbortWorkflowRequested() { if (mContext) { @@ -126,10 +126,10 @@ JNIEXPORT jboolean JNICALL Java_com_governikus_ausweisapp2_AusweisApp2LocalIfdSe bool initialized = false; QMetaObject::invokeMethod(QCoreApplication::instance(), [psk] { - UIPlugInLocalIfd* const uiPlugIn = Env::getSingleton()->getLoaded(); - if (uiPlugIn) + UiPluginLocalIfd* const uiPlugin = Env::getSingleton()->getLoaded(); + if (uiPlugin) { - return uiPlugIn->onStartWorkflowRequested(psk); + return uiPlugin->onStartWorkflowRequested(psk); } return false; }, Qt::BlockingQueuedConnection, &initialized); @@ -144,10 +144,10 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_AusweisApp2LocalIfdServic Q_UNUSED(pEnv) QMetaObject::invokeMethod(QCoreApplication::instance(), [] { - UIPlugInLocalIfd* const uiPlugIn = Env::getSingleton()->getLoaded(); - if (uiPlugIn) + UiPluginLocalIfd* const uiPlugin = Env::getSingleton()->getLoaded(); + if (uiPlugin) { - uiPlugIn->onAbortWorkflowRequested(); + uiPlugin->onAbortWorkflowRequested(); } }, Qt::BlockingQueuedConnection); } diff --git a/src/ui/local_ifd/UIPlugInLocalIfd.h b/src/ui/local_ifd/UiPluginLocalIfd.h similarity index 74% rename from src/ui/local_ifd/UIPlugInLocalIfd.h rename to src/ui/local_ifd/UiPluginLocalIfd.h index ddfd29733..60eb2a865 100644 --- a/src/ui/local_ifd/UIPlugInLocalIfd.h +++ b/src/ui/local_ifd/UiPluginLocalIfd.h @@ -1,10 +1,10 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "UIPlugIn.h" +#include "UiPlugin.h" #include "context/WorkflowContext.h" #include @@ -12,12 +12,12 @@ namespace governikus { -class UIPlugInLocalIfd - : public UIPlugIn +class UiPluginLocalIfd + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) private: QSharedPointer mContext; @@ -28,7 +28,7 @@ class UIPlugInLocalIfd void onSocketError(QAbstractSocket::SocketError pSocketError); public: - UIPlugInLocalIfd(); + UiPluginLocalIfd(); void doShutdown() override; void onWorkflowStarted(const QSharedPointer& pRequest) override; diff --git a/src/ui/proxy/PortWrapper.h b/src/ui/proxy/PortWrapper.h index f476258f8..cc049eb58 100644 --- a/src/ui/proxy/PortWrapper.h +++ b/src/ui/proxy/PortWrapper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -30,9 +30,9 @@ class PortWrapper #ifdef Q_OS_WIN static QString getUserOfProcessID(DWORD pPid); static QString getExecutableOfProcessID(DWORD pPid); - static quint16 getPortOfRunningProcess(const QVector& pConnections, const QString& pUser, quint16 pSelfPort, const in_addr& pRemoteAddr); - static QString getUserOfConnection(const QVector& pConnections, quint16 pLocalPort, quint16 pRemotePort, const in_addr& pProxyAddr); - static QVector getConnections(); + static quint16 getPortOfRunningProcess(const QList& pConnections, const QString& pUser, quint16 pSelfPort, const in_addr& pRemoteAddr); + static QString getUserOfConnection(const QList& pConnections, quint16 pLocalPort, quint16 pRemotePort, const in_addr& pProxyAddr); + static QList getConnections(); static quint16 getProcessPort(quint16 pLocalPort, quint16 pRemotePort); #else static quint16 readPortFile(const QString& pFile); diff --git a/src/ui/proxy/PortWrapper_generic.cpp b/src/ui/proxy/PortWrapper_generic.cpp index 147580cd9..130c33611 100644 --- a/src/ui/proxy/PortWrapper_generic.cpp +++ b/src/ui/proxy/PortWrapper_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "PortWrapper.h" diff --git a/src/ui/proxy/PortWrapper_win.cpp b/src/ui/proxy/PortWrapper_win.cpp index 8376285ad..c3d66368b 100644 --- a/src/ui/proxy/PortWrapper_win.cpp +++ b/src/ui/proxy/PortWrapper_win.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "PortWrapper.h" @@ -147,7 +147,7 @@ QString PortWrapper::getExecutableOfProcessID(DWORD pPid) } -quint16 PortWrapper::getPortOfRunningProcess(const QVector& pConnections, const QString& pUser, quint16 pSelfPort, const in_addr& pProxyAddr) +quint16 PortWrapper::getPortOfRunningProcess(const QList& pConnections, const QString& pUser, quint16 pSelfPort, const in_addr& pProxyAddr) { for (const auto& connection : pConnections) { @@ -180,7 +180,7 @@ quint16 PortWrapper::getPortOfRunningProcess(const QVector } -QString PortWrapper::getUserOfConnection(const QVector& pConnections, quint16 pLocalPort, quint16 pRemotePort, const in_addr& pRemoteAddr) +QString PortWrapper::getUserOfConnection(const QList& pConnections, quint16 pLocalPort, quint16 pRemotePort, const in_addr& pRemoteAddr) { for (const auto& connection : pConnections) { @@ -202,7 +202,7 @@ QString PortWrapper::getUserOfConnection(const QVector& pC } -QVector PortWrapper::getConnections() +QList PortWrapper::getConnections() { DWORD size = 0; DWORD dwResult = NO_ERROR; @@ -210,7 +210,7 @@ QVector PortWrapper::getConnections() if (dwResult != ERROR_INSUFFICIENT_BUFFER) { qCWarning(rproxy) << "Cannot get IP table size"; - return QVector(); + return QList(); } auto* tcpInfo = static_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)); @@ -222,10 +222,10 @@ QVector PortWrapper::getConnections() if (dwResult != NO_ERROR) { qCWarning(rproxy) << "Cannot get IP table:" << dwResult; - return QVector(); + return QList(); } - QVector result; + QList result; for (DWORD dwLoop = 0; dwLoop < tcpInfo->dwNumEntries; ++dwLoop) { result += tcpInfo->table[dwLoop]; diff --git a/src/ui/proxy/RedirectRequest.cpp b/src/ui/proxy/RedirectRequest.cpp index 9245f9bb3..857fe8d86 100644 --- a/src/ui/proxy/RedirectRequest.cpp +++ b/src/ui/proxy/RedirectRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "RedirectRequest.h" diff --git a/src/ui/proxy/RedirectRequest.h b/src/ui/proxy/RedirectRequest.h index f6adc0f45..7163d326f 100644 --- a/src/ui/proxy/RedirectRequest.h +++ b/src/ui/proxy/RedirectRequest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ui/proxy/UIPlugInProxy.cpp b/src/ui/proxy/UiPluginProxy.cpp similarity index 61% rename from src/ui/proxy/UIPlugInProxy.cpp rename to src/ui/proxy/UiPluginProxy.cpp index 801a144ec..31de7f5cc 100644 --- a/src/ui/proxy/UIPlugInProxy.cpp +++ b/src/ui/proxy/UiPluginProxy.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInProxy.h" +#include "UiPluginProxy.h" #include "Env.h" #include "RedirectRequest.h" @@ -15,21 +15,21 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(rproxy) -UIPlugInProxy::UIPlugInProxy() - : UIPlugIn() +UiPluginProxy::UiPluginProxy() + : UiPlugin() , HttpHandler() , mServer() { } -bool UIPlugInProxy::initialize() +bool UiPluginProxy::initialize() { return (mServer && mServer->isListening()) || listen(); } -bool UIPlugInProxy::listen() +bool UiPluginProxy::listen() { mServer = Env::getShared(); @@ -44,66 +44,66 @@ bool UIPlugInProxy::listen() } -void UIPlugInProxy::onNewRequest(const QSharedPointer& pRequest) +void UiPluginProxy::onNewRequest(const QSharedPointer& pRequest) { handle(pRequest); } -void UIPlugInProxy::onNewWebSocketRequest(const QSharedPointer& pRequest) +void UiPluginProxy::onNewWebSocketRequest(const QSharedPointer& pRequest) { new RedirectRequest(pRequest, this); } -void UIPlugInProxy::handleWorkflowRequest(const QSharedPointer& pRequest) +void UiPluginProxy::handleWorkflowRequest(const QSharedPointer& pRequest) { new RedirectRequest(pRequest, this); } -void UIPlugInProxy::handleShowUiRequest(const QString& pUiModule, const QSharedPointer& pRequest) +void UiPluginProxy::handleShowUiRequest(const QString& pUiModule, const QSharedPointer& pRequest) { Q_UNUSED(pUiModule) new RedirectRequest(pRequest, this); } -void UIPlugInProxy::onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) +void UiPluginProxy::onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) { Q_UNUSED(pInformation) if (pUi == this && pAccepted) { - connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UIPlugInProxy::onNewRequest); - connect(mServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UIPlugInProxy::onNewWebSocketRequest); + connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UiPluginProxy::onNewRequest); + connect(mServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UiPluginProxy::onNewWebSocketRequest); qCDebug(rproxy) << "Reverse proxy enabled"; return; } } -void UIPlugInProxy::onUiDominationReleased() +void UiPluginProxy::onUiDominationReleased() { - disconnect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UIPlugInProxy::onNewRequest); - disconnect(mServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UIPlugInProxy::onNewWebSocketRequest); + disconnect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UiPluginProxy::onNewRequest); + disconnect(mServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UiPluginProxy::onNewWebSocketRequest); qCDebug(rproxy) << "Reverse proxy disabled"; } -void UIPlugInProxy::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginProxy::onWorkflowStarted(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) } -void UIPlugInProxy::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginProxy::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) } -void UIPlugInProxy::doShutdown() +void UiPluginProxy::doShutdown() { if (mServer) { diff --git a/src/ui/proxy/UIPlugInProxy.h b/src/ui/proxy/UiPluginProxy.h similarity index 67% rename from src/ui/proxy/UIPlugInProxy.h rename to src/ui/proxy/UiPluginProxy.h index 3a1fccb3f..5046a5b3b 100644 --- a/src/ui/proxy/UIPlugInProxy.h +++ b/src/ui/proxy/UiPluginProxy.h @@ -1,9 +1,9 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the UIPlugInProxy. + * \brief UiPlugin implementation of the UiPluginProxy. */ #pragma once @@ -11,20 +11,20 @@ #include "HttpHandler.h" #include "HttpRequest.h" #include "HttpServer.h" -#include "UIPlugIn.h" +#include "UiPlugin.h" -class test_UIPlugInProxy; +class test_UiPluginProxy; namespace governikus { -class UIPlugInProxy - : public UIPlugIn +class UiPluginProxy + : public UiPlugin , private HttpHandler { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) - friend class ::test_UIPlugInProxy; + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) + friend class ::test_UiPluginProxy; private: QSharedPointer mServer; @@ -38,14 +38,14 @@ class UIPlugInProxy void doShutdown() override; void onWorkflowStarted(const QSharedPointer& pRequest) override; void onWorkflowFinished(const QSharedPointer& pRequest) override; - void onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) override; + void onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) override; void onUiDominationReleased() override; void onNewRequest(const QSharedPointer& pRequest); void onNewWebSocketRequest(const QSharedPointer& pRequest); public: - UIPlugInProxy(); - ~UIPlugInProxy() override = default; + UiPluginProxy(); + ~UiPluginProxy() override = default; [[nodiscard]] bool initialize() override; }; diff --git a/src/ui/qml/AppUpdateDataModel.cpp b/src/ui/qml/AppUpdateDataModel.cpp index 49647e8d6..3e836d7a5 100644 --- a/src/ui/qml/AppUpdateDataModel.cpp +++ b/src/ui/qml/AppUpdateDataModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "AppUpdateDataModel.h" @@ -169,15 +169,6 @@ const QString& AppUpdateDataModel::getNotes() const } -void AppUpdateDataModel::skipUpdate() const -{ - if (isValid()) - { - Env::getSingleton()->skipVersion(getVersion()); - } -} - - bool AppUpdateDataModel::download() { mDownloadProgress = 0; diff --git a/src/ui/qml/AppUpdateDataModel.h b/src/ui/qml/AppUpdateDataModel.h index 8024b3844..11fa3d132 100644 --- a/src/ui/qml/AppUpdateDataModel.h +++ b/src/ui/qml/AppUpdateDataModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -9,6 +9,7 @@ #include #include +#include namespace governikus @@ -17,6 +18,8 @@ class AppUpdateDataModel : public QObject { Q_OBJECT + QML_UNCREATABLE("Used by SettingsModel only") + QML_ELEMENT friend class Env; Q_PROPERTY(bool updateAvailable READ isUpdateAvailable NOTIFY fireAppUpdateDataChanged) @@ -64,7 +67,6 @@ class AppUpdateDataModel [[nodiscard]] const QUrl& getChecksumUrl() const; [[nodiscard]] const QUrl& getNotesUrl() const; [[nodiscard]] const QString& getNotes() const; - Q_INVOKABLE void skipUpdate() const; [[nodiscard]] Q_INVOKABLE bool download(); [[nodiscard]] Q_INVOKABLE bool abortDownload(); diff --git a/src/ui/qml/ApplicationModel.cpp b/src/ui/qml/ApplicationModel.cpp index 6e8070c18..26cfa46a3 100644 --- a/src/ui/qml/ApplicationModel.cpp +++ b/src/ui/qml/ApplicationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationModel.h" @@ -29,11 +29,6 @@ #include #include -#ifdef Q_OS_ANDROID - #include - #include -#endif - using namespace governikus; @@ -42,9 +37,9 @@ Q_DECLARE_LOGGING_CATEGORY(qml) Q_DECLARE_LOGGING_CATEGORY(feedback) -void ApplicationModel::onStatusChanged(const ReaderManagerPlugInInfo& pInfo) +void ApplicationModel::onStatusChanged(const ReaderManagerPluginInfo& pInfo) { - if (pInfo.getPlugInType() == ReaderManagerPlugInType::NFC) + if (pInfo.getPluginType() == ReaderManagerPluginType::NFC) { Q_EMIT fireNfcStateChanged(); } @@ -63,7 +58,7 @@ ApplicationModel::ApplicationModel() , mPrivate(new Private()) #endif { - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &ApplicationModel::fireReaderPropertiesUpdated); connect(readerManager, &ReaderManager::fireStatusChanged, this, &ApplicationModel::onStatusChanged); connect(readerManager, &ReaderManager::fireReaderAdded, this, &ApplicationModel::fireAvailableReaderChanged); @@ -84,12 +79,12 @@ void ApplicationModel::resetContext(const QSharedPointer& pCont { if (mContext) { - disconnect(mContext.data(), &WorkflowContext::fireReaderPlugInTypesChanged, this, &ApplicationModel::fireAvailableReaderChanged); + disconnect(mContext.data(), &WorkflowContext::fireReaderPluginTypesChanged, this, &ApplicationModel::fireAvailableReaderChanged); } if ((mContext = pContext)) { - connect(mContext.data(), &WorkflowContext::fireReaderPlugInTypesChanged, this, &ApplicationModel::fireAvailableReaderChanged); + connect(mContext.data(), &WorkflowContext::fireReaderPluginTypesChanged, this, &ApplicationModel::fireAvailableReaderChanged); connect(mContext.data(), &WorkflowContext::fireReaderNameChanged, this, &ApplicationModel::fireAvailableReaderChanged); connect(mContext.data(), &WorkflowContext::fireReaderNameChanged, this, &ApplicationModel::fireReaderPropertiesUpdated); connect(mContext.data(), &WorkflowContext::fireReaderInfoChanged, this, &ApplicationModel::fireReaderPropertiesUpdated); @@ -128,38 +123,38 @@ QString ApplicationModel::getStoreUrl() const QUrl ApplicationModel::getReleaseNotesUrl() const { - const auto storage = Env::getSingleton(); + const auto* storage = Env::getSingleton(); const auto& url = VersionNumber::getApplicationVersion().isBetaVersion() ? storage->getAppcastBetaUpdateUrl() : storage->getAppcastUpdateUrl(); return url.adjusted(QUrl::RemoveFilename).toString() + QStringLiteral("ReleaseNotes.html"); } -ApplicationModel::QmlNfcState ApplicationModel::getNfcState() const +ApplicationModel::NfcState ApplicationModel::getNfcState() const { #if !defined(QT_NO_DEBUG) && !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WINRT) - const ReaderManagerPlugInType type = ReaderManagerPlugInType::PCSC; + const ReaderManagerPluginType type = ReaderManagerPluginType::PCSC; #else - const ReaderManagerPlugInType type = ReaderManagerPlugInType::NFC; + const ReaderManagerPluginType type = ReaderManagerPluginType::NFC; #endif - const auto& pluginInfo = Env::getSingleton()->getPlugInInfo(type); + const auto& pluginInfo = Env::getSingleton()->getPluginInfo(type); if (!pluginInfo.isAvailable()) { - return QmlNfcState::NFC_UNAVAILABLE; + return NfcState::UNAVAILABLE; } if (!pluginInfo.isEnabled()) { - return QmlNfcState::NFC_DISABLED; + return NfcState::DISABLED; } if (!pluginInfo.isScanRunning()) { - return QmlNfcState::NFC_INACTIVE; + return NfcState::INACTIVE; } - return QmlNfcState::NFC_READY; + return NfcState::READY; } @@ -181,6 +176,19 @@ bool ApplicationModel::isExtendedLengthApdusUnsupported() const } +bool ApplicationModel::isSmartSupported() const +{ +#if __has_include("SmartManager.h") + return true; + +#else + return false; + +#endif + +} + + bool ApplicationModel::isWifiEnabled() const { return mWifiEnabled; @@ -191,27 +199,27 @@ ApplicationModel::Workflow ApplicationModel::getCurrentWorkflow() const { if (mContext.objectCast()) { - return Workflow::WORKFLOW_CHANGE_PIN; + return Workflow::CHANGE_PIN; } if (mContext.objectCast()) { - return Workflow::WORKFLOW_SELF_AUTHENTICATION; + return Workflow::SELF_AUTHENTICATION; } #if __has_include("context/PersonalizationContext.h") if (mContext.objectCast()) { - return Workflow::WORKFLOW_SMART; + return Workflow::SMART; } #endif if (mContext.objectCast()) { - return Workflow::WORKFLOW_AUTHENTICATION; + return Workflow::AUTHENTICATION; } if (mContext.objectCast()) { - return Workflow::WORKFLOW_REMOTE_SERVICE; + return Workflow::REMOTE_SERVICE; } - return Workflow::WORKFLOW_NONE; + return Workflow::NONE; } @@ -222,44 +230,37 @@ qsizetype ApplicationModel::getAvailableReader() const return 0; } - return Env::getSingleton()->getReaderInfos(ReaderFilter(mContext->getReaderPlugInTypes())).size(); + return Env::getSingleton()->getReaderInfos(ReaderFilter(mContext->getReaderPluginTypes())).size(); } -bool ApplicationModel::isReaderTypeAvailable(ReaderManagerPlugInType pPlugInType) const +qsizetype ApplicationModel::getAvailablePcscReader() const { if (!mContext) { - return false; - } - - if (!mContext->getReaderName().isEmpty()) - { - return Env::getSingleton()->getReaderInfo(mContext->getReaderName()).getPlugInType() == pPlugInType; + return 0; } - return !Env::getSingleton()->getReaderInfos(ReaderFilter({pPlugInType})).isEmpty(); + return Env::getSingleton()->getReaderInfos(ReaderFilter({ReaderManagerPluginType::PCSC})).size(); } -#ifndef Q_OS_IOS -bool ApplicationModel::isScreenReaderRunning() const +bool ApplicationModel::isReaderTypeAvailable(ReaderManagerPluginType pPluginType) const { - #ifdef Q_OS_ANDROID - QJniObject context = QNativeInterface::QAndroidApplication::context(); - const jboolean result = context.callMethod("isScreenReaderRunning", "()Z"); - return result != JNI_FALSE; + if (!mContext) + { + return false; + } - #else - qCWarning(qml) << "NOT IMPLEMENTED"; - return false; + if (!mContext->getReaderName().isEmpty()) + { + return Env::getSingleton()->getReaderInfo(mContext->getReaderName()).getPluginType() == pPluginType; + } - #endif + return !Env::getSingleton()->getReaderInfos(ReaderFilter({pPluginType})).isEmpty(); } -#endif - QString ApplicationModel::getFeedback() const { return mFeedback.isEmpty() ? QString() : mFeedback.first(); @@ -284,42 +285,11 @@ void ApplicationModel::setClipboardText(const QString& pText) const } +#ifndef Q_OS_ANDROID void ApplicationModel::showFeedback(const QString& pMessage, bool pReplaceExisting) { qCInfo(feedback).noquote() << pMessage; -#if defined(Q_OS_ANDROID) - QNativeInterface::QAndroidApplication::runOnAndroidMainThread([pMessage, pReplaceExisting](){ - QJniEnvironment env; - static thread_local QJniObject toast; - - if (toast.isValid() && pReplaceExisting) - { - toast.callMethod("cancel"); - } - - QJniObject context = QNativeInterface::QAndroidApplication::context(); - const QJniObject& jMessage = QJniObject::fromString(pMessage); - toast = QJniObject::callStaticObjectMethod( - "android/widget/Toast", - "makeText", - "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;", - context.object(), - jMessage.object(), - jint(1)); - toast.callMethod("show"); - - if (env->ExceptionCheck()) - { - qCCritical(qml) << "Suppressing an unexpected exception."; - env->ExceptionDescribe(); - env->ExceptionClear(); - // The toast was probably not displayed (e.g. DeadObjectException). We halt on error - // since it is used to display information to the user as required by the TR. - Q_ASSERT(false); - } - }); -#else if (pReplaceExisting) { mFeedbackTimer.stop(); @@ -336,29 +306,16 @@ void ApplicationModel::showFeedback(const QString& pMessage, bool pReplaceExisti } Q_EMIT fireFeedbackChanged(); } -#endif } -#ifndef Q_OS_IOS +#endif + + +#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID) void ApplicationModel::keepScreenOn(bool pActive) const { - #if defined(Q_OS_ANDROID) - QNativeInterface::QAndroidApplication::runOnAndroidMainThread([pActive](){ - QJniObject context = QNativeInterface::QAndroidApplication::context(); - context.callMethod("keepScreenOn", "(Z)V", pActive); - QJniEnvironment env; - if (env->ExceptionCheck()) - { - qCCritical(qml) << "Exception calling java native function."; - env->ExceptionDescribe(); - env->ExceptionClear(); - } - }); - - #else qCWarning(qml) << "NOT IMPLEMENTED:" << pActive; - #endif } @@ -390,10 +347,7 @@ QStringList ApplicationModel::getLicenseText() const #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) QUrl ApplicationModel::getCustomConfigPath() const { - QFileInfo info(Env::getSingleton()->getCustomConfig()); - QUrl url(info.absolutePath()); - url.setScheme(QStringLiteral("file")); - return url; + return Env::getSingleton()->getCustomConfigPath(); } @@ -443,7 +397,7 @@ void ApplicationModel::onTranslationChanged() void ApplicationModel::enableWifi() const { #ifdef Q_OS_ANDROID - showSettings(Settings::SETTING_WIFI); + showSettings(Settings::WIFI); #endif } diff --git a/src/ui/qml/ApplicationModel.h b/src/ui/qml/ApplicationModel.h index edc496fcc..d89eb89a6 100644 --- a/src/ui/qml/ApplicationModel.h +++ b/src/ui/qml/ApplicationModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,7 +9,8 @@ #pragma once #include "Env.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" +#include "SingletonCreator.h" #include "WifiInfo.h" #include "context/WorkflowContext.h" @@ -18,12 +19,13 @@ #include #include #include +#include #ifdef Q_OS_IOS Q_FORWARD_DECLARE_OBJC_CLASS(VoiceOverObserver); #endif -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -31,21 +33,31 @@ namespace governikus class ApplicationModel : public QObject + , public SingletonCreator { Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(QString storeUrl READ getStoreUrl NOTIFY fireStoreUrlChanged) Q_PROPERTY(QUrl releaseNotesUrl READ getReleaseNotesUrl CONSTANT) - Q_PROPERTY(QmlNfcState nfcState READ getNfcState NOTIFY fireNfcStateChanged) + Q_PROPERTY(NfcState nfcState READ getNfcState NOTIFY fireNfcStateChanged) Q_PROPERTY(bool extendedLengthApdusUnsupported READ isExtendedLengthApdusUnsupported NOTIFY fireReaderPropertiesUpdated) + Q_PROPERTY(bool isSmartSupported READ isSmartSupported CONSTANT) + Q_PROPERTY(bool wifiEnabled READ isWifiEnabled NOTIFY fireWifiEnabledChanged) Q_PROPERTY(Workflow currentWorkflow READ getCurrentWorkflow NOTIFY fireCurrentWorkflowChanged) - Q_PROPERTY(qsizetype availableReader READ getAvailableReader NOTIFY fireAvailableReaderChanged) + + // QT_VERSION_CHECK(6, 8, 0) qint64 to qsizetype + Q_PROPERTY(qint64 availableReader READ getAvailableReader NOTIFY fireAvailableReaderChanged) + Q_PROPERTY(qint64 availablePcscReader READ getAvailablePcscReader NOTIFY fireAvailableReaderChanged) Q_PROPERTY(QString feedback READ getFeedback NOTIFY fireFeedbackChanged) @@ -73,7 +85,7 @@ class ApplicationModel ApplicationModel(); ~ApplicationModel() override = default; - void onStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void onStatusChanged(const ReaderManagerPluginInfo& pInfo); private Q_SLOTS: void onApplicationStateChanged(Qt::ApplicationState pState); @@ -85,32 +97,32 @@ class ApplicationModel public: enum class Settings { - SETTING_WIFI, - SETTING_NETWORK, - SETTING_NFC, - SETTING_APP + WIFI, + NETWORK, + NFC, + APP }; Q_ENUM(Settings) enum class Workflow { - WORKFLOW_CHANGE_PIN, - WORKFLOW_SELF_AUTHENTICATION, - WORKFLOW_AUTHENTICATION, - WORKFLOW_SMART, - WORKFLOW_REMOTE_SERVICE, - WORKFLOW_NONE + CHANGE_PIN, + SELF_AUTHENTICATION, + AUTHENTICATION, + SMART, + REMOTE_SERVICE, + NONE }; Q_ENUM(Workflow) - enum class QmlNfcState + enum class NfcState { - NFC_UNAVAILABLE, - NFC_DISABLED, - NFC_INACTIVE, - NFC_READY + UNAVAILABLE, + DISABLED, + INACTIVE, + READY }; - Q_ENUM(QmlNfcState) + Q_ENUM(NfcState) void resetContext(const QSharedPointer& pContext = QSharedPointer()); @@ -119,18 +131,21 @@ class ApplicationModel [[nodiscard]] QString getStoreUrl() const; [[nodiscard]] QUrl getReleaseNotesUrl() const; - [[nodiscard]] QmlNfcState getNfcState() const; + [[nodiscard]] NfcState getNfcState() const; [[nodiscard]] bool isExtendedLengthApdusUnsupported() const; + [[nodiscard]] bool isSmartSupported() const; + [[nodiscard]] bool isWifiEnabled() const; [[nodiscard]] Workflow getCurrentWorkflow() const; [[nodiscard]] qsizetype getAvailableReader() const; + [[nodiscard]] qsizetype getAvailablePcscReader() const; [[nodiscard]] QString getFeedback() const; [[nodiscard]] Q_INVOKABLE bool isScreenReaderRunning() const; - [[nodiscard]] Q_INVOKABLE bool isReaderTypeAvailable(ReaderManagerPlugInType pPlugInType) const; + [[nodiscard]] Q_INVOKABLE bool isReaderTypeAvailable(ReaderManagerPluginType pPluginType) const; Q_INVOKABLE void enableWifi()const; diff --git a/src/ui/qml/ApplicationModel_android.cpp b/src/ui/qml/ApplicationModel_android.cpp index 653d95c75..46867f099 100644 --- a/src/ui/qml/ApplicationModel_android.cpp +++ b/src/ui/qml/ApplicationModel_android.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationModel.h" @@ -11,6 +11,7 @@ using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(feedback) Q_DECLARE_LOGGING_CATEGORY(qml) static void showSystemSettings(const QString& pAction) @@ -24,7 +25,7 @@ static void showSystemSettings(const QString& pAction) if (intent.isValid()) { - qCCritical(qml) << "Call action:" << pAction; + qCDebug(qml) << "Call action:" << pAction; QtAndroidPrivate::startActivity(intent, 0); } @@ -43,7 +44,7 @@ void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) c switch (pAction) { - case Settings::SETTING_WIFI: + case Settings::WIFI: if (QOperatingSystemVersion::current() >= androidQ) { showSystemSettings(QStringLiteral("android.settings.panel.action.WIFI")); @@ -54,7 +55,7 @@ void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) c } break; - case Settings::SETTING_NETWORK: + case Settings::NETWORK: if (QOperatingSystemVersion::current() >= androidQ) { showSystemSettings(QStringLiteral("android.settings.panel.action.INTERNET_CONNECTIVITY")); @@ -65,7 +66,7 @@ void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) c } break; - case Settings::SETTING_NFC: + case Settings::NFC: if (QOperatingSystemVersion::current() >= androidQ) { showSystemSettings(QStringLiteral("android.settings.panel.action.NFC")); @@ -77,8 +78,70 @@ void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) c break; - case Settings::SETTING_APP: + case Settings::APP: qCWarning(qml) << "NOT IMPLEMENTED:" << pAction; break; } } + + +bool ApplicationModel::isScreenReaderRunning() const +{ + QJniObject context = QNativeInterface::QAndroidApplication::context(); + const jboolean result = context.callMethod("isScreenReaderRunning", "()Z"); + return result != JNI_FALSE; +} + + +void ApplicationModel::showFeedback(const QString& pMessage, bool pReplaceExisting) +{ + qCInfo(feedback).noquote() << pMessage; + + QNativeInterface::QAndroidApplication::runOnAndroidMainThread([pMessage, pReplaceExisting](){ + QJniEnvironment env; + static thread_local QJniObject toast; + + if (toast.isValid() && pReplaceExisting) + { + toast.callMethod("cancel"); + } + + QJniObject context = QNativeInterface::QAndroidApplication::context(); + const QJniObject& jMessage = QJniObject::fromString(pMessage); + toast = QJniObject::callStaticObjectMethod( + "android/widget/Toast", + "makeText", + "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;", + context.object(), + jMessage.object(), + jint(1)); + toast.callMethod("show"); + + if (env->ExceptionCheck()) + { + qCCritical(qml) << "Suppressing an unexpected exception."; + env->ExceptionDescribe(); + env->ExceptionClear(); + // The toast was probably not displayed (e.g. DeadObjectException). We halt on error + // since it is used to display information to the user as required by the TR. + Q_ASSERT(false); + } + }); +} + + +void ApplicationModel::keepScreenOn(bool pActive) const +{ + QNativeInterface::QAndroidApplication::runOnAndroidMainThread([pActive](){ + QJniObject context = QNativeInterface::QAndroidApplication::context(); + context.callMethod("keepScreenOn", "(Z)V", pActive); + QJniEnvironment env; + if (env->ExceptionCheck()) + { + qCCritical(qml) << "Exception calling java native function."; + env->ExceptionDescribe(); + env->ExceptionClear(); + } + }); + +} diff --git a/src/ui/qml/ApplicationModel_generic.cpp b/src/ui/qml/ApplicationModel_generic.cpp index ee86e5cc6..c743a9382 100644 --- a/src/ui/qml/ApplicationModel_generic.cpp +++ b/src/ui/qml/ApplicationModel_generic.cpp @@ -1,9 +1,11 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationModel.h" +#include + using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(qml) @@ -12,3 +14,10 @@ void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) c { qCWarning(qml) << "NOT IMPLEMENTED:" << pAction; } + + +bool ApplicationModel::isScreenReaderRunning() const +{ + qCWarning(qml) << "NOT IMPLEMENTED"; + return false; +} diff --git a/src/ui/qml/ApplicationModel_ios.mm b/src/ui/qml/ApplicationModel_ios.mm index fc8a8d2f1..0d4c4a51e 100644 --- a/src/ui/qml/ApplicationModel_ios.mm +++ b/src/ui/qml/ApplicationModel_ios.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "ApplicationModel.h" @@ -98,7 +98,7 @@ - (void)receiveNotification:(NSNotification*)notification { void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) const { - if (pAction == Settings::SETTING_APP) + if (pAction == Settings::APP) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; } diff --git a/src/ui/qml/ApplicationModel_osx.mm b/src/ui/qml/ApplicationModel_osx.mm new file mode 100644 index 000000000..c43349b25 --- /dev/null +++ b/src/ui/qml/ApplicationModel_osx.mm @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "ApplicationModel.h" + +#include + +using namespace governikus; + + +Q_DECLARE_LOGGING_CATEGORY(qml) + + +bool ApplicationModel::isScreenReaderRunning() const +{ + return NSWorkspace.sharedWorkspace.voiceOverEnabled; +} + + +void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) const +{ + qCWarning(qml) << "NOT IMPLEMENTED:" << pAction; +} diff --git a/src/ui/qml/ApplicationModel_win.cpp b/src/ui/qml/ApplicationModel_win.cpp new file mode 100644 index 000000000..7b9a7958e --- /dev/null +++ b/src/ui/qml/ApplicationModel_win.cpp @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "ApplicationModel.h" + +#include + +#include + +using namespace governikus; + + +Q_DECLARE_LOGGING_CATEGORY(qml) + + +bool ApplicationModel::isScreenReaderRunning() const +{ + BOOL screenReaderRunning = false; + const BOOL success = SystemParametersInfo(SPI_GETSCREENREADER, 0, &screenReaderRunning, 0); + return success && screenReaderRunning; +} + + +void ApplicationModel::showSettings(const ApplicationModel::Settings& pAction) const +{ + qCWarning(qml) << "NOT IMPLEMENTED:" << pAction; +} diff --git a/src/ui/qml/AuthModel.cpp b/src/ui/qml/AuthModel.cpp index bc1cbbe5c..63071e429 100644 --- a/src/ui/qml/AuthModel.cpp +++ b/src/ui/qml/AuthModel.cpp @@ -1,8 +1,9 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "AuthModel.h" +#include "context/SelfAuthContext.h" using namespace governikus; @@ -77,6 +78,30 @@ bool AuthModel::getShowChangePinView() const } +QString AuthModel::getResultHeader() const +{ + if (!mContext) + { + return QString(); + } + + if (mContext->getStatus().getStatusCode() == GlobalStatus::Code::Workflow_Browser_Transmission_Error) + { + //: LABEL ALL_PLATFORMS + return tr("Redirect failed"); + } + + if (mContext->getStatus().isError()) + { + //: LABEL ALL_PLATFORMS + return tr("Authentication failed"); + } + + //: LABEL ALL_PLATFORMS + return tr("Authentication successful"); +} + + QString AuthModel::getErrorHeader() const { if (!mContext || mContext->getTcTokenUrl().isEmpty()) @@ -122,6 +147,48 @@ QString AuthModel::getStatusCodeString() const } +QString AuthModel::getResultViewButtonIcon() const +{ + if (!mContext) + { + return QString(); + } + + if (mContext->getStatus().getStatusCode() == GlobalStatus::Code::Workflow_Browser_Transmission_Error) + { + return QStringLiteral("qrc:///images/open_website.svg"); + } + + return QString(); +} + + +QString AuthModel::getResultViewButtonText() const +{ + if (!mContext) + { + return QString(); + } + if (mContext.objectCast()) + { + //: LABEL ALL_PLATFORMS + return tr("Back to start page"); + } + //: LABEL ALL_PLATFORMS + return tr("Return to provider"); +} + + +QUrl AuthModel::getResultViewButtonLink() const +{ + if (mContext && mContext->isReceivedBrowserSendFailed()) + { + return mContext->getRefreshUrl(); + } + return QUrl(); +} + + void AuthModel::cancelWorkflowToChangePin() { if (mContext) @@ -138,7 +205,7 @@ void AuthModel::onDidAuthenticateEac1Changed() if (mContext) { const QSharedPointer& didAuthenticateEAC1 = mContext->getDidAuthenticateEac1(); - const QString newTransactionInfo = didAuthenticateEAC1.isNull() ? QString() : didAuthenticateEAC1->getTransactionInfo(); + const QString newTransactionInfo = didAuthenticateEAC1.isNull() ? QString() : didAuthenticateEAC1->getTransactionInfo().toHtmlEscaped(); if (newTransactionInfo != mTransactionInfo) { mTransactionInfo = newTransactionInfo; diff --git a/src/ui/qml/AuthModel.h b/src/ui/qml/AuthModel.h index be428b23e..dffb25c3d 100644 --- a/src/ui/qml/AuthModel.h +++ b/src/ui/qml/AuthModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,7 @@ #pragma once #include "Env.h" +#include "SingletonCreator.h" #include "WorkflowModel.h" #include "context/AuthContext.h" @@ -16,9 +17,10 @@ #include #include #include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -26,18 +28,26 @@ namespace governikus class AuthModel : public WorkflowModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(QString transactionInfo READ getTransactionInfo NOTIFY fireTransactionInfoChanged) Q_PROPERTY(int progressValue READ getProgressValue NOTIFY fireProgressChanged) Q_PROPERTY(QString progressMessage READ getProgressMessage NOTIFY fireProgressChanged) Q_PROPERTY(bool showChangePinView READ getShowChangePinView NOTIFY fireShowChangePinViewChanged) + Q_PROPERTY(QString resultHeader READ getResultHeader NOTIFY fireResultChanged) Q_PROPERTY(QString errorHeader READ getErrorHeader NOTIFY fireResultChanged) Q_PROPERTY(QString errorText READ getErrorText NOTIFY fireResultChanged) Q_PROPERTY(QString statusCodeString READ getStatusCodeString NOTIFY fireResultChanged) + Q_PROPERTY(QString resultViewButtonIcon READ getResultViewButtonIcon NOTIFY fireResultChanged) + Q_PROPERTY(QString resultViewButtonText READ getResultViewButtonText NOTIFY fireResultChanged) + Q_PROPERTY(QUrl resultViewButtonLink READ getResultViewButtonLink NOTIFY fireResultChanged) private: QSharedPointer mContext; @@ -54,9 +64,13 @@ class AuthModel [[nodiscard]] int getProgressValue() const; [[nodiscard]] QString getProgressMessage() const; [[nodiscard]] bool getShowChangePinView() const; + [[nodiscard]] QString getResultHeader() const; [[nodiscard]] QString getErrorHeader() const; [[nodiscard]] QString getErrorText() const; [[nodiscard]] QString getStatusCodeString() const; + [[nodiscard]] QString getResultViewButtonIcon() const; + [[nodiscard]] QString getResultViewButtonText() const; + [[nodiscard]] QUrl getResultViewButtonLink() const; Q_INVOKABLE void cancelWorkflowToChangePin(); diff --git a/src/ui/qml/CMakeLists.txt b/src/ui/qml/CMakeLists.txt index 405130625..f9dec3264 100644 --- a/src/ui/qml/CMakeLists.txt +++ b/src/ui/qml/CMakeLists.txt @@ -1,46 +1,71 @@ -##################################################################### -# The qml plugin implements the ui interface for mobile systems. -##################################################################### +############################################################################ +# The qml plugin implements the ui interface for desktop and mobile systems. +############################################################################ -ADD_PLATFORM_LIBRARY(AusweisAppUiQml) +add_subdirectory(modules) -target_link_libraries(AusweisAppUiQml ${Qt}::Core ${Qt}::Svg ${Qt}::Qml ${Qt}::Quick ${Qt}::QuickControls2) -target_link_libraries(AusweisAppUiQml AusweisAppGlobal AusweisAppUi AusweisAppIfdRemote AusweisAppServices AusweisAppWorkflowsSelfAuth) +ADD_PLATFORM_LIBRARY(AusweisAppUiQml EXCLUDE "/modules/") -target_link_libraries(AusweisAppUiQml ${Qt}::CorePrivate) +target_link_libraries(AusweisAppUiQml PUBLIC ${Qt}::Core ${Qt}::Svg ${Qt}::Qml ${Qt}::Quick ${Qt}::QuickControls2) +target_link_libraries(AusweisAppUiQml PUBLIC AusweisAppGlobal AusweisAppUi AusweisAppIfdRemote AusweisAppServices AusweisAppWorkflowsSelfAuth AusweisAppUiQmlModules) + +target_link_libraries(AusweisAppUiQml PUBLIC ${Qt}::CorePrivate) if(TARGET ${Qt}::Widgets) - target_link_libraries(AusweisAppUiQml ${Qt}::Widgets) # QSystemTrayIcon + target_link_libraries(AusweisAppUiQml PUBLIC ${Qt}::Widgets) # QSystemTrayIcon endif() if(TARGET ${Qt}::QmlWorkerScript) - target_link_libraries(AusweisAppUiQml ${Qt}::QmlWorkerScript) + target_link_libraries(AusweisAppUiQml PUBLIC ${Qt}::QmlWorkerScript) endif() if(TARGET AusweisAppDiagnosis) - target_link_libraries(AusweisAppUiQml AusweisAppDiagnosis) + target_link_libraries(AusweisAppUiQml PUBLIC AusweisAppDiagnosis) endif() if(TARGET ${Qt}::WebSockets) - target_link_libraries(AusweisAppUiQml AusweisAppWorkflowsIfd) -endif() - -if(ANDROID) - target_link_libraries(AusweisAppUiQml AusweisAppWhitelistClient) -else() - target_link_libraries(AusweisAppUiQml debug AusweisAppWhitelistClient) + target_link_libraries(AusweisAppUiQml PUBLIC AusweisAppWorkflowsIfd) endif() if(MAC) - target_link_libraries(AusweisAppUiQml ${OSX_USERNOTIFICATIONS}) + target_link_libraries(AusweisAppUiQml PUBLIC ${OSX_USERNOTIFICATIONS}) endif() if(TARGET AusweisAppWorkflowsPersonalization) if((ANDROID OR IOS) AND NOT INTEGRATED_SDK) - target_link_libraries(AusweisAppUiQml AusweisAppWorkflowsPersonalization) + target_link_libraries(AusweisAppUiQml PUBLIC AusweisAppWorkflowsPersonalization) else() - target_link_libraries(AusweisAppUiQml debug AusweisAppWorkflowsPersonalization) + target_link_libraries(AusweisAppUiQml PUBLIC debug AusweisAppWorkflowsPersonalization) endif() endif() target_compile_definitions(AusweisAppUiQml PRIVATE QT_STATICPLUGIN) + + +qt_add_qml_module(AusweisAppUiQml + URI "Governikus.Type" + VERSION "${PROJECT_VERSION}" + OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules/common/Governikus/Type + RESOURCE_PREFIX /qml + NO_CACHEGEN + NO_IMPORT_SCAN + DEPENDENCIES QtQml QtQml.Models QtQuick +) + +get_target_property(target_type AusweisAppUiQmlplugin TYPE) +if(target_type STREQUAL STATIC_LIBRARY) + target_link_libraries(AusweisAppUiQml PRIVATE AusweisAppUiQmlplugin) +endif() + +if(QT_VERSION VERSION_GREATER_EQUAL "6.7.1" + OR (QT_VERSION VERSION_GREATER_EQUAL "6.5.6" AND QT_VERSION VERSION_LESS "6.6") + ) + if(TARGET AusweisAppDiagnosis) + qt_generate_foreign_qml_types(AusweisAppDiagnosis AusweisAppUiQml) + endif() + qt_generate_foreign_qml_types(AusweisAppGlobal AusweisAppUiQml) + qt_generate_foreign_qml_types(AusweisAppUi AusweisAppUiQml) + qt_generate_foreign_qml_types(AusweisAppCard AusweisAppUiQml) +else() + set_property(SOURCE UiPluginQml.cpp PROPERTY COMPILE_DEFINITIONS USE_CUSTOM_REGISTRATION) +endif() diff --git a/src/ui/qml/CardPosition.cpp b/src/ui/qml/CardPosition.cpp index 5a7ebe6ae..b52da2d36 100644 --- a/src/ui/qml/CardPosition.cpp +++ b/src/ui/qml/CardPosition.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "CardPosition.h" diff --git a/src/ui/qml/CardPosition.h b/src/ui/qml/CardPosition.h index 195cc3a67..c2a1c3804 100644 --- a/src/ui/qml/CardPosition.h +++ b/src/ui/qml/CardPosition.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,7 @@ #pragma once #include +#include namespace governikus { @@ -17,6 +18,7 @@ class CardPosition : public QObject { Q_OBJECT + QML_ELEMENT Q_PROPERTY(double x MEMBER mXPosition CONSTANT) Q_PROPERTY(double y MEMBER mYPosition CONSTANT) diff --git a/src/ui/qml/CardPositionModel.cpp b/src/ui/qml/CardPositionModel.cpp index 65c15f2f2..ca1f9d376 100644 --- a/src/ui/qml/CardPositionModel.cpp +++ b/src/ui/qml/CardPositionModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "CardPositionModel.h" diff --git a/src/ui/qml/CardPositionModel.h b/src/ui/qml/CardPositionModel.h index 1303884b6..86b23b981 100644 --- a/src/ui/qml/CardPositionModel.h +++ b/src/ui/qml/CardPositionModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,9 +10,10 @@ #include "CardPosition.h" +#include #include #include -#include +#include class test_CardPositionModel; @@ -23,6 +24,8 @@ class CardPositionModel : public QObject { Q_OBJECT + QML_ELEMENT + friend class ::test_CardPositionModel; Q_PROPERTY(int count READ getCardPositionCount CONSTANT) @@ -33,7 +36,7 @@ class CardPositionModel int mCyclingClock; qsizetype mCurrentIndex; QTimer mCyclingTimer; - const QVector mCardPositions; + const QList mCardPositions; void startTimer(); void stopTimer(); diff --git a/src/ui/qml/CertificateDescriptionModel.cpp b/src/ui/qml/CertificateDescriptionModel.cpp index fb3747de1..c54a85e30 100644 --- a/src/ui/qml/CertificateDescriptionModel.cpp +++ b/src/ui/qml/CertificateDescriptionModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "CertificateDescriptionModel.h" @@ -155,14 +155,14 @@ QVariant CertificateDescriptionModel::data(const QModelIndex& pIndex, int pRole) { if (pIndex.isValid() && pIndex.row() < rowCount()) { - auto entry = mData[pIndex.row()]; + const auto& [label, text] = mData[pIndex.row()]; if (pRole == LABEL) { - return entry.first; + return label; } if (pRole == TEXT) { - return entry.second; + return text; } } return QVariant(); diff --git a/src/ui/qml/CertificateDescriptionModel.h b/src/ui/qml/CertificateDescriptionModel.h index cb631f11a..87225e43d 100644 --- a/src/ui/qml/CertificateDescriptionModel.h +++ b/src/ui/qml/CertificateDescriptionModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,17 +9,19 @@ #pragma once #include "Env.h" +#include "SingletonCreator.h" #include "asn1/CertificateDescription.h" #include "context/WorkflowContext.h" #include +#include #include #include #include -#include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -27,16 +29,20 @@ namespace governikus class CertificateDescriptionModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(QString subjectName READ getSubjectName NOTIFY fireChanged) Q_PROPERTY(QString purpose READ getPurpose NOTIFY fireChanged) private: - QVector> mData; + QList> mData; QSharedPointer mContext; CertificateDescriptionModel(); diff --git a/src/ui/qml/ChangePinModel.cpp b/src/ui/qml/ChangePinModel.cpp index 1380528b5..634e93ff5 100644 --- a/src/ui/qml/ChangePinModel.cpp +++ b/src/ui/qml/ChangePinModel.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ChangePinModel.h" #include "controller/ChangePinController.h" + using namespace governikus; @@ -17,9 +18,8 @@ void ChangePinModel::resetChangePinContext(const QSharedPointer ChangePinModel::getSupportedReaderPlugInTypes() const +QList ChangePinModel::getSupportedReaderPluginTypes() const { - auto plugins = WorkflowModel::getSupportedReaderPlugInTypes(); + auto plugins = WorkflowModel::getSupportedReaderPluginTypes(); if (mContext && mContext->isRequestTransportPin()) { - plugins.removeOne(ReaderManagerPlugInType::SMART); + plugins.removeOne(ReaderManagerPluginType::SMART); } return plugins; } @@ -61,12 +61,3 @@ bool ChangePinModel::isRequestTransportPin() const } return mContext->isRequestTransportPin(); } - - -void ChangePinModel::onPaceResultUpdated() -{ - if (mContext->getLastPaceResult() == CardReturnCode::OK_PUK) - { - Q_EMIT fireOnPinUnlocked(); - } -} diff --git a/src/ui/qml/ChangePinModel.h b/src/ui/qml/ChangePinModel.h index 439d105fa..6f695ddd7 100644 --- a/src/ui/qml/ChangePinModel.h +++ b/src/ui/qml/ChangePinModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,7 @@ #pragma once #include "Env.h" +#include "SingletonCreator.h" #include "WorkflowModel.h" #include "WorkflowRequest.h" #include "context/ChangePinContext.h" @@ -17,9 +18,10 @@ #include #include #include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -27,10 +29,14 @@ namespace governikus class ChangePinModel : public WorkflowModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(bool requestTransportPin READ isRequestTransportPin NOTIFY fireWorkflowStarted) private: @@ -43,15 +49,11 @@ class ChangePinModel Q_INVOKABLE void startWorkflow(bool pRequestTransportPin, bool pActivateUi = true); [[nodiscard]] QString getResultString() const override; - [[nodiscard]] QVector getSupportedReaderPlugInTypes() const override; + [[nodiscard]] QList getSupportedReaderPluginTypes() const override; [[nodiscard]] bool isRequestTransportPin() const; - private Q_SLOTS: - void onPaceResultUpdated(); - Q_SIGNALS: void fireStartWorkflow(const QSharedPointer& pRequest); - void fireOnPinUnlocked(); }; diff --git a/src/ui/qml/ChatModel.cpp b/src/ui/qml/ChatModel.cpp index 5317d5783..015619acb 100644 --- a/src/ui/qml/ChatModel.cpp +++ b/src/ui/qml/ChatModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -188,7 +188,7 @@ bool ChatModel::setData(const QModelIndex& pIndex, const QVariant& pValue, int p return false; } - Q_EMIT dataChanged(pIndex, pIndex, QVector({SELECTED_ROLE})); + Q_EMIT dataChanged(pIndex, pIndex, QList({SELECTED_ROLE})); return true; } diff --git a/src/ui/qml/ChatModel.h b/src/ui/qml/ChatModel.h index d84351167..96b267ef8 100644 --- a/src/ui/qml/ChatModel.h +++ b/src/ui/qml/ChatModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,19 +8,21 @@ #pragma once +#include "Env.h" +#include "SingletonCreator.h" +#include "context/AccessRightManager.h" +#include "context/WorkflowContext.h" + #include #include #include #include #include - -#include "Env.h" -#include "context/AccessRightManager.h" -#include "context/WorkflowContext.h" +#include class test_ChatModel; -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -30,11 +32,15 @@ struct cvcertificate_st; class ChatModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; friend class ::test_ChatModel; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(QSortFilterProxyModel * optional READ getFilterOptionalModel CONSTANT) Q_PROPERTY(QSortFilterProxyModel * required READ getFilterRequiredModel CONSTANT) diff --git a/src/ui/qml/CheckIDCardModel.cpp b/src/ui/qml/CheckIDCardModel.cpp index 21545da95..c348e1b7f 100644 --- a/src/ui/qml/CheckIDCardModel.cpp +++ b/src/ui/qml/CheckIDCardModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "CheckIDCardModel.h" @@ -11,7 +11,7 @@ using namespace governikus; CheckIDCardModel::CheckIDCardModel(QObject* pParent) : QObject(pParent) , mIsRunning(false) - , mResult(CheckIDCardResult::UNKNOWN) + , mResult(Result::UNKNOWN) { } @@ -34,33 +34,33 @@ void CheckIDCardModel::onCardInserted(const ReaderInfo& pInfo) if (pInfo.hasEid()) { - mResult = CheckIDCardResult::ID_CARD_DETECTED; + mResult = Result::ID_CARD_DETECTED; Q_EMIT fireResultChanged(); if (pInfo.insufficientApduLength()) { - stopScanWithResult(CheckIDCardResult::INSUFFICIENT_APDU_LENGTH); + stopScanWithResult(Result::INSUFFICIENT_APDU_LENGTH); } else if (pInfo.isPinDeactivated()) { - stopScanWithResult(CheckIDCardResult::PIN_DEACTIVATED); + stopScanWithResult(Result::PIN_DEACTIVATED); } else if (pInfo.getRetryCounter() == 1) { - stopScanWithResult(CheckIDCardResult::PIN_SUSPENDED); + stopScanWithResult(Result::PIN_SUSPENDED); } else if (pInfo.getRetryCounter() == 0) { - stopScanWithResult(CheckIDCardResult::PIN_BLOCKED); + stopScanWithResult(Result::PIN_BLOCKED); } else { - stopScanWithResult(CheckIDCardResult::SUCCESS); + stopScanWithResult(Result::SUCCESS); } } else if (pInfo.hasCard()) { - stopScanWithResult(CheckIDCardResult::UNKNOWN_CARD_DETECTED); + stopScanWithResult(Result::UNKNOWN_CARD_DETECTED); } } @@ -72,7 +72,7 @@ void CheckIDCardModel::onCardRemoved(const ReaderInfo& pInfo) return; } - stopScanWithResult(CheckIDCardResult::CARD_ACCESS_FAILED); + stopScanWithResult(Result::CARD_ACCESS_FAILED); } @@ -100,12 +100,12 @@ void CheckIDCardModel::onReaderPropertiesUpdated(const ReaderInfo& pInfo) { if (pInfo.insufficientApduLength()) { - stopScanWithResult(CheckIDCardResult::INSUFFICIENT_APDU_LENGTH); + stopScanWithResult(Result::INSUFFICIENT_APDU_LENGTH); } } -void CheckIDCardModel::stopScanWithResult(CheckIDCardResult result) +void CheckIDCardModel::stopScanWithResult(Result result) { qDebug() << "Finish with status" << result; @@ -126,7 +126,7 @@ void CheckIDCardModel::startScan() mIsRunning = true; - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::fireCardInserted, this, &CheckIDCardModel::onCardInserted); connect(readerManager, &ReaderManager::fireCardRemoved, this, &CheckIDCardModel::onCardRemoved); connect(readerManager, &ReaderManager::fireReaderAdded, this, &CheckIDCardModel::onReaderAdded); @@ -144,19 +144,19 @@ void CheckIDCardModel::startScanIfNecessary() return; } - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); - if (readerManager->getPlugInInfo(ReaderManagerPlugInType::NFC).isScanRunning()) + if (readerManager->getPluginInfo(ReaderManagerPluginType::NFC).isScanRunning()) { return; } mReaderWithCard.clear(); - readerManager->startScan(ReaderManagerPlugInType::NFC); + readerManager->startScan(ReaderManagerPluginType::NFC); - const auto nfcReaderInfos = readerManager->getReaderInfos(ReaderFilter({ReaderManagerPlugInType::NFC})); - mResult = nfcReaderInfos.empty() ? CheckIDCardResult::NO_NFC : CheckIDCardResult::CARD_NOT_DETECTED; + const auto nfcReaderInfos = readerManager->getReaderInfos(ReaderFilter({ReaderManagerPluginType::NFC})); + mResult = nfcReaderInfos.empty() ? Result::NO_NFC : Result::CARD_NOT_DETECTED; // Directly check all NFC readers if an id card is already present for (const auto& info : nfcReaderInfos) @@ -179,21 +179,21 @@ void CheckIDCardModel::stopScan() return; } - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); disconnect(readerManager, &ReaderManager::fireCardInserted, this, &CheckIDCardModel::onCardInserted); disconnect(readerManager, &ReaderManager::fireCardRemoved, this, &CheckIDCardModel::onCardRemoved); disconnect(readerManager, &ReaderManager::fireReaderAdded, this, &CheckIDCardModel::onReaderAdded); disconnect(readerManager, &ReaderManager::fireReaderRemoved, this, &CheckIDCardModel::onReaderRemoved); disconnect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &CheckIDCardModel::onReaderPropertiesUpdated); - readerManager->stopScan(ReaderManagerPlugInType::NFC); + readerManager->stopScan(ReaderManagerPluginType::NFC); mIsRunning = false; mReaderWithCard.clear(); } -CheckIDCardModel::CheckIDCardResult CheckIDCardModel::getResult() const +CheckIDCardModel::Result CheckIDCardModel::getResult() const { return mResult; } diff --git a/src/ui/qml/CheckIDCardModel.h b/src/ui/qml/CheckIDCardModel.h index e3f6b9196..a07efa680 100644 --- a/src/ui/qml/CheckIDCardModel.h +++ b/src/ui/qml/CheckIDCardModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #include "ReaderInfo.h" #include +#include namespace governikus @@ -20,11 +21,12 @@ class CheckIDCardModel : public QObject { Q_OBJECT - - Q_PROPERTY(CheckIDCardResult result READ getResult NOTIFY fireResultChanged) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + Q_PROPERTY(Result result READ getResult NOTIFY fireResultChanged) + QML_ELEMENT public: - enum class CheckIDCardResult + enum class Result { UNKNOWN, NO_NFC, @@ -38,7 +40,7 @@ class CheckIDCardModel PIN_BLOCKED, SUCCESS }; - Q_ENUM(CheckIDCardResult) + Q_ENUM(Result) explicit CheckIDCardModel(QObject* pParent = nullptr); ~CheckIDCardModel() override; @@ -47,11 +49,11 @@ class CheckIDCardModel Q_INVOKABLE void startScanIfNecessary(); Q_INVOKABLE void stopScan(); - [[nodiscard]] CheckIDCardResult getResult() const; + [[nodiscard]] Result getResult() const; private: bool mIsRunning; - CheckIDCardResult mResult; + Result mResult; QString mReaderWithCard; private Q_SLOTS: @@ -61,7 +63,7 @@ class CheckIDCardModel void onReaderRemoved(const ReaderInfo& pInfo); void onReaderPropertiesUpdated(const ReaderInfo& pInfo); - void stopScanWithResult(CheckIDCardResult result); + void stopScanWithResult(Result result); Q_SIGNALS: void fireResultChanged(); diff --git a/src/ui/qml/ConnectivityManager.cpp b/src/ui/qml/ConnectivityManager.cpp index 9018ff1b2..2bd36be24 100644 --- a/src/ui/qml/ConnectivityManager.cpp +++ b/src/ui/qml/ConnectivityManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "ConnectivityManager.h" diff --git a/src/ui/qml/ConnectivityManager.h b/src/ui/qml/ConnectivityManager.h index 89c10ec5b..eb3d28bd9 100644 --- a/src/ui/qml/ConnectivityManager.h +++ b/src/ui/qml/ConnectivityManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #include #include #include +#include class test_ConnectivityManager; @@ -22,6 +23,8 @@ class ConnectivityManager : public QObject { Q_OBJECT + QML_ELEMENT + friend class ::test_ConnectivityManager; Q_PROPERTY(bool watching READ isWatching WRITE setWatching NOTIFY fireWatchingChanged) diff --git a/src/ui/qml/Email.cpp b/src/ui/qml/Email.cpp index 8c95585d8..63490dfcb 100644 --- a/src/ui/qml/Email.cpp +++ b/src/ui/qml/Email.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "Email.h" @@ -13,8 +13,8 @@ namespace governikus QString generateMailBody(const GlobalStatus& pStatus, const QUrl& pServiceUrl, bool pPercentEncoding, bool pAddLogNotice) { - const auto& logHandler = Env::getSingleton(); - QStringList mailBody(QObject::tr("Please describe the error that occurred.")); + auto* logHandler = Env::getSingleton(); + QStringList mailBody(QObject::tr("Please describe the error that occurs. Our support is available to you in German and English.")); if (logHandler->useLogFile() && pAddLogNotice) { @@ -25,17 +25,16 @@ QString generateMailBody(const GlobalStatus& pStatus, const QUrl& pServiceUrl, b mailBody << newLine; const auto& systemInfo = BuildHelper::getInformationHeader(); - for (const auto& info : systemInfo) + for (const auto& [key, value] : systemInfo) { - QString first = info.first; - QString second = info.second; if (pPercentEncoding) { - first = QString::fromUtf8(QUrl::toPercentEncoding(first)); - second = QString::fromUtf8(QUrl::toPercentEncoding(second)); - + const auto& encKey = QString::fromUtf8(QUrl::toPercentEncoding(key)); + const auto& encValue = QString::fromUtf8(QUrl::toPercentEncoding(value)); + mailBody << encKey + QStringLiteral(": ") + encValue; + continue; } - mailBody << first + QStringLiteral(": ") + second; + mailBody << key + QStringLiteral(": ") + value; } mailBody << newLine + QObject::tr("Error code") + QLatin1Char(':'); diff --git a/src/ui/qml/Email.h b/src/ui/qml/Email.h index 82a32a150..655702e9f 100644 --- a/src/ui/qml/Email.h +++ b/src/ui/qml/Email.h @@ -1,12 +1,15 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once +#include "GlobalStatus.h" + #include #include + namespace governikus { diff --git a/src/ui/qml/FormattedTextModel.cpp b/src/ui/qml/FormattedTextModel.cpp index f288d9a71..7a9fb3327 100644 --- a/src/ui/qml/FormattedTextModel.cpp +++ b/src/ui/qml/FormattedTextModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "FormattedTextModel.h" @@ -41,14 +41,14 @@ QVariant FormattedTextModel::data(const QModelIndex& pIndex, int pRole) const return QVariant(); } - const auto& line = mLines.at(row); + const auto& [content, line] = mLines.at(row); switch (pRole) { case ContentRole: - return line.first; + return content; case LineTypeRole: - return line.second; + return QVariant::fromValue(line); default: return QVariant(); @@ -93,7 +93,7 @@ bool FormattedTextModel::loadSeveral(const QStringList& pFilepaths) bool FormattedTextModel::isFormattingLine(FormattedTextModel::LineType pType) { - static const QList formattingLineTypes({HEADER, SECTION, SUBSECTION}); + static const QList formattingLineTypes({LineType::HEADER, LineType::SECTION, LineType::SUBSECTION}); return formattingLineTypes.contains(pType); } @@ -103,28 +103,28 @@ FormattedTextModel::LineType FormattedTextModel::lineType(const QString& pLine) const auto trimmedLine = pLine.trimmed(); if (trimmedLine.isEmpty()) { - return EMPTY; + return LineType::EMPTY; } if (pLine.count(QLatin1Char('*')) == trimmedLine.size()) { - return HEADER; + return LineType::HEADER; } if (pLine.count(QLatin1Char('=')) == trimmedLine.size()) { - return SECTION; + return LineType::SECTION; } if (pLine.count(QLatin1Char('-')) == trimmedLine.size()) { - return SUBSECTION; + return LineType::SUBSECTION; } const QRegularExpression reListElement(QStringLiteral("^\\s*\\*{1}\\s?\\w+")); if (reListElement.match(trimmedLine).hasMatch()) { - return LISTITEM; + return LineType::LISTITEM; } - return REGULARTEXT; + return LineType::REGULARTEXT; } @@ -132,7 +132,7 @@ FormattedTextModel::LineType FormattedTextModel::lineType(const QString& pLine) QString FormattedTextModel::stripFormattingCharacters(const QString& pLine, LineType pType) { QString workingCopy = pLine; - if (pType == LISTITEM) + if (pType == LineType::LISTITEM) { workingCopy.remove(QRegularExpression(QStringLiteral("^\\s*\\*{1}\\s?"))); } @@ -194,7 +194,7 @@ void FormattedTextModel::processLine(const QString& pLine) const auto strippedLine = stripFormattingCharacters(pLine, type); const auto htmlLine = replaceControlCharactersWithHtml(strippedLine); - if ((lastLineIsEmpty() && !isFormattingLine(type)) || type == EMPTY) + if ((lastLineIsEmpty() && !isFormattingLine(type)) || type == LineType::EMPTY) { mLines << qMakePair(htmlLine, type); return; @@ -214,5 +214,5 @@ void FormattedTextModel::processLine(const QString& pLine) bool FormattedTextModel::lastLineIsEmpty() const { - return mLines.isEmpty() || mLines.last().second == EMPTY; + return mLines.isEmpty() || mLines.last().second == LineType::EMPTY; } diff --git a/src/ui/qml/FormattedTextModel.h b/src/ui/qml/FormattedTextModel.h index 420677a59..fc9963894 100644 --- a/src/ui/qml/FormattedTextModel.h +++ b/src/ui/qml/FormattedTextModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,9 @@ #include #include #include +#include + +class test_FormattedTextModel; namespace governikus { @@ -21,9 +24,13 @@ class FormattedTextModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Used by ReleaseInformationModel only") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + friend class ::test_FormattedTextModel; public: - enum LineType + enum class LineType { EMPTY, HEADER, @@ -48,10 +55,7 @@ class FormattedTextModel [[nodiscard]] Q_INVOKABLE bool loadSeveral(const QStringList& pFilepaths); -#if defined(QT_NO_DEBUG) - private: -#endif struct ReadLinesResult { bool mSuccess; diff --git a/src/ui/qml/LogFilterModel.cpp b/src/ui/qml/LogFilterModel.cpp index c9f7030c7..ce4f52916 100644 --- a/src/ui/qml/LogFilterModel.cpp +++ b/src/ui/qml/LogFilterModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "LogFilterModel.h" @@ -12,7 +12,7 @@ using namespace governikus; void LogFilterModel::onLevelsChanged() { - mSelectedLevels.intersect(getLevels()); + mSelectedLevels.intersect(Env::getSingleton()->getLevels()); invalidateFilter(); Q_EMIT fireLevelsChanged(); } @@ -20,7 +20,7 @@ void LogFilterModel::onLevelsChanged() void LogFilterModel::onCategoriesChanged() { - mSelectedCategories.intersect(getCategories()); + mSelectedCategories.intersect(Env::getSingleton()->getCategories()); invalidateFilter(); Q_EMIT fireCategoriesChanged(); } @@ -61,27 +61,33 @@ LogFilterModel::LogFilterModel() } -const QSet& LogFilterModel::getLevels() const +QStringList LogFilterModel::getLevels() const { - return Env::getSingleton()->getLevels(); + const auto& level = Env::getSingleton()->getLevels(); + QStringList list(level.constBegin(), level.constEnd()); + list.sort(Qt::CaseInsensitive); + return list; } -const QSet& LogFilterModel::getSelectedLevels() const +QStringList LogFilterModel::getSelectedLevels() const { - return mSelectedLevels; + return QStringList(mSelectedLevels.constBegin(), mSelectedLevels.constEnd()); } -const QSet& LogFilterModel::getCategories() const +QStringList LogFilterModel::getCategories() const { - return Env::getSingleton()->getCategories(); + const auto& categories = Env::getSingleton()->getCategories(); + QStringList list(categories.constBegin(), categories.constEnd()); + list.sort(Qt::CaseInsensitive); + return list; } -const QSet& LogFilterModel::getSelectedCategories() const +QStringList LogFilterModel::getSelectedCategories() const { - return mSelectedCategories; + return QStringList(mSelectedCategories.constBegin(), mSelectedCategories.constEnd()); } diff --git a/src/ui/qml/LogFilterModel.h b/src/ui/qml/LogFilterModel.h index a2fa8a99c..5d74cbbef 100644 --- a/src/ui/qml/LogFilterModel.h +++ b/src/ui/qml/LogFilterModel.h @@ -1,12 +1,13 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include #include -#include +#include +#include namespace governikus @@ -16,10 +17,12 @@ class LogFilterModel : public QSortFilterProxyModel { Q_OBJECT - Q_PROPERTY(QSet levels READ getLevels NOTIFY fireLevelsChanged) - Q_PROPERTY(QSet selectedLevels READ getSelectedLevels NOTIFY fireLevelsChanged) - Q_PROPERTY(QSet categories READ getCategories NOTIFY fireCategoriesChanged) - Q_PROPERTY(QSet selectedCategories READ getSelectedCategories NOTIFY fireCategoriesChanged) + QML_ELEMENT + + Q_PROPERTY(QStringList levels READ getLevels NOTIFY fireLevelsChanged) + Q_PROPERTY(QStringList selectedLevels READ getSelectedLevels NOTIFY fireLevelsChanged) + Q_PROPERTY(QStringList categories READ getCategories NOTIFY fireCategoriesChanged) + Q_PROPERTY(QStringList selectedCategories READ getSelectedCategories NOTIFY fireCategoriesChanged) private: QSet mSelectedLevels; @@ -36,10 +39,10 @@ class LogFilterModel LogFilterModel(); ~LogFilterModel() override = default; - [[nodiscard]] const QSet& getLevels() const; - [[nodiscard]] const QSet& getSelectedLevels() const; - [[nodiscard]] const QSet& getCategories() const; - [[nodiscard]] const QSet& getSelectedCategories() const; + [[nodiscard]] QStringList getLevels() const; + [[nodiscard]] QStringList getSelectedLevels() const; + [[nodiscard]] QStringList getCategories() const; + [[nodiscard]] QStringList getSelectedCategories() const; Q_INVOKABLE void configureLevel(const QString& pLevel, bool pEnabled); Q_INVOKABLE void configureCategory(const QString& pCategory, bool pEnabled); diff --git a/src/ui/qml/LogModel.cpp b/src/ui/qml/LogModel.cpp index 397a5da5b..21407435b 100644 --- a/src/ui/qml/LogModel.cpp +++ b/src/ui/qml/LogModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "LogModel.h" @@ -51,7 +51,7 @@ void LogModel::addLogEntry(const QString& pEntry) const QString re = QStringLiteral(R"(^[a-z\._ ]{%1} \d{4}\.\d{2}\.\d{2} \d{2}:\d{2}:\d{2}\.\d{3} \d{3,} )").arg(LogHandler::MAX_CATEGORY_LENGTH); if (!QRegularExpression(re).match(pEntry).hasMatch() && !mLogEntries.isEmpty()) { - mLogEntries.last().append(QLatin1String("\n")).append(pEntry); + mLogEntries.last().append(QLatin1String("\n")).append(pEntry); // clazy:exclude=detaching-member return; } @@ -168,24 +168,6 @@ void LogModel::removeOtherLogFiles() } -void LogModel::removeCurrentLogFile() -{ - if (mSelectedLogFile == 0) - { - return; - } - - if (!QFile::remove(mLogFiles[mSelectedLogFile])) - { - qDebug() << mLogFiles[mSelectedLogFile] << "could not be removed"; - return; - } - - mLogFiles.removeAt(mSelectedLogFile); - Q_EMIT fireLogFileNamesChanged(); -} - - void LogModel::setLogFile(int pIndex) { if (pIndex < 0 || pIndex >= mLogFiles.size()) @@ -200,7 +182,7 @@ void LogModel::setLogFile(int pIndex) } mSelectedLogFile = pIndex; - const auto logHandler = Env::getSingleton(); + auto* logHandler = Env::getSingleton(); if (pIndex == 0) { @@ -211,7 +193,7 @@ void LogModel::setLogFile(int pIndex) else { disconnect(logHandler->getEventHandler(), &LogEventHandler::fireLog, this, &LogModel::onNewLogMsg); - QFile inputFile(mLogFiles[pIndex]); + QFile inputFile(mLogFiles.value(pIndex)); if (inputFile.open(QIODevice::ReadOnly)) { QTextStream in(&inputFile); @@ -234,7 +216,7 @@ void LogModel::saveCurrentLogFile(const QUrl& pFilename) const success = Env::getSingleton()->copyOther(logfilePath, pFilename.toLocalFile()); } - const auto applicationModel = Env::getSingleton(); + auto* applicationModel = Env::getSingleton(); applicationModel->showFeedback((success ? tr("Successfully saved logfile to \"%1\"") : tr("Error while saving logfile to \"%1\"")).arg(pFilename.toLocalFile())); } @@ -244,7 +226,7 @@ void LogModel::saveDummyLogFile(const QDateTime& pTimestamp) { auto& generator = Randomizer::getInstance().getGenerator(); std::uniform_int_distribution dist; - const auto logHandler = Env::getSingleton(); + const auto* logHandler = Env::getSingleton(); const auto& copyFilename = QDir::temp().filePath(QStringLiteral("%1.%2.log").arg(QCoreApplication::applicationName()).arg(dist(generator))); if (logHandler->copy(copyFilename) && pTimestamp.isValid()) { @@ -329,7 +311,7 @@ QVariant LogModel::data(const QModelIndex& pIndex, int pRole) const QString LogModel::createLogFileName(const QDateTime& pDateTime) { - QString dateFormat = QStringLiteral("yyyy-MM-dd_HH-mm"); + auto dateFormat = QStringLiteral("yyyy-MM-dd_HH-mm"); QString logFileDate = pDateTime.toString(dateFormat); return QStringLiteral("%1-%2.log").arg(QCoreApplication::applicationName(), logFileDate); } diff --git a/src/ui/qml/LogModel.h b/src/ui/qml/LogModel.h index f963b9ee2..0ca177e80 100644 --- a/src/ui/qml/LogModel.h +++ b/src/ui/qml/LogModel.h @@ -1,10 +1,11 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "Env.h" +#include "SingletonCreator.h" #include #include @@ -15,6 +16,7 @@ #include #include #include +#include class test_LogModel; @@ -23,8 +25,12 @@ namespace governikus class LogModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; friend class ::test_LogModel; @@ -65,7 +71,6 @@ class LogModel [[nodiscard]] const QSet& getCategories() const; Q_INVOKABLE QDateTime getCurrentLogFileDate() const; Q_INVOKABLE void removeOtherLogFiles(); - Q_INVOKABLE void removeCurrentLogFile(); Q_INVOKABLE void setLogFile(int pIndex); Q_INVOKABLE void saveCurrentLogFile(const QUrl& pFilename) const; #ifndef QT_NO_DEBUG diff --git a/src/ui/qml/LogModel_android.cpp b/src/ui/qml/LogModel_android.cpp index 180327ce6..1432b6a01 100644 --- a/src/ui/qml/LogModel_android.cpp +++ b/src/ui/qml/LogModel_android.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "LogModel.h" @@ -91,7 +91,7 @@ void LogModel::shareLog(const QPoint /*popupPosition*/) const return; } - const auto& logHandler = Env::getSingleton(); + const auto* logHandler = Env::getSingleton(); QString publicLogFile; if (mSelectedLogFile == 0) diff --git a/src/ui/qml/LogModel_generic.cpp b/src/ui/qml/LogModel_generic.cpp index 1fa848046..8401ea894 100644 --- a/src/ui/qml/LogModel_generic.cpp +++ b/src/ui/qml/LogModel_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "LogModel.h" diff --git a/src/ui/qml/LogModel_ios.mm b/src/ui/qml/LogModel_ios.mm index 986596934..d3a579565 100644 --- a/src/ui/qml/LogModel_ios.mm +++ b/src/ui/qml/LogModel_ios.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "LogModel.h" diff --git a/src/ui/qml/NotificationModel.cpp b/src/ui/qml/NotificationModel.cpp index d6cf6a602..d2396bde7 100644 --- a/src/ui/qml/NotificationModel.cpp +++ b/src/ui/qml/NotificationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "NotificationModel.h" diff --git a/src/ui/qml/NotificationModel.h b/src/ui/qml/NotificationModel.h index e2a6cb7f5..d242868ca 100644 --- a/src/ui/qml/NotificationModel.h +++ b/src/ui/qml/NotificationModel.h @@ -1,10 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include "Env.h" +#include "SingletonCreator.h" #include #include @@ -12,6 +13,7 @@ #include #include #include +#include class test_NotificationModel; @@ -20,8 +22,12 @@ namespace governikus class NotificationModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; friend class ::test_NotificationModel; diff --git a/src/ui/qml/NumberModel.cpp b/src/ui/qml/NumberModel.cpp index bafde9f5e..521f068ea 100644 --- a/src/ui/qml/NumberModel.cpp +++ b/src/ui/qml/NumberModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "NumberModel.h" @@ -20,7 +20,7 @@ NumberModel::NumberModel() , mNewPin() , mNewPinConfirmation() { - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &NumberModel::onReaderInfoChanged); connect(readerManager, &ReaderManager::fireCardInfoChanged, this, &NumberModel::onReaderInfoChanged); connect(readerManager, &ReaderManager::fireReaderRemoved, this, &NumberModel::onReaderInfoChanged); @@ -69,6 +69,7 @@ void NumberModel::resetContext(const QSharedPointer& pContext) connect(mContext.data(), &WorkflowContext::fireReaderNameChanged, this, &NumberModel::fireReaderInfoChanged); connect(mContext.data(), &WorkflowContext::fireReaderNameChanged, this, &NumberModel::fireInputErrorChanged); connect(mContext.data(), &WorkflowContext::firePaceResultUpdated, this, &NumberModel::fireInputErrorChanged); + connect(mContext.data(), &WorkflowContext::fireInitialInputErrorShownChanged, this, &NumberModel::firePasswordTypeChanged); } Q_EMIT fireCanChanged(); @@ -82,7 +83,7 @@ void NumberModel::resetContext(const QSharedPointer& pContext) } -PasswordType NumberModel::getPasswordType() const +NumberModel::PasswordType NumberModel::getPasswordType() const { if (!mContext) { @@ -248,6 +249,16 @@ bool NumberModel::commitNewPin() } +void NumberModel::resetInputError() +{ + if (mContext) + { + mContext->resetLastPaceResult(); + Q_EMIT fireInputErrorChanged(); + } +} + + QString NumberModel::getPuk() const { return mContext ? mContext->getPuk() : QString(); @@ -263,16 +274,12 @@ void NumberModel::setPuk(const QString& pPuk) } -bool NumberModel::hasPasswordError() const -{ - return CardReturnCodeUtil::equalsWrongPacePassword(getInputErrorCode()); -} - - CardReturnCode NumberModel::getInputErrorCode() const { if (mContext.isNull() || mContext->getLastPaceResult() == CardReturnCode::OK + || mContext->getLastPaceResult() == CardReturnCode::OK_PUK + || mContext->getLastPaceResult() == CardReturnCode::OK_CAN || mContext->getLastPaceResult() == CardReturnCode::CANCELLATION_BY_USER || mContext->getCardConnection().isNull()) { @@ -296,6 +303,42 @@ bool NumberModel::newPinAndConfirmationMatch() const } +QString NumberModel::getInitialInputError() const +{ + if (mContext && !mContext->isInitialInputErrorShown()) + { + + if (getPasswordType() == PasswordType::CAN && !isCanAllowedMode()) + { + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 1/2 + tr("An incorrect PIN has been entered 2 times at the last use of your ID card."), + //: INFO ALL_PLATFORMS Once per workflow info text shown when an ID card with one PIN attempt left has been detected. Part 2/2 + tr("For a 3rd attempt, the 6-digit Card Access Number (CAN) must be entered first. You can find your CAN in the bottom right on the front of your ID card.")); + } + if (getPasswordType() == PasswordType::PUK) + { + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 1/2 + tr("An incorrect PIN has been entered 3 times at the last use of your ID card."), + //: INFO ALL_PLATFORMS Once per workflow info text shown when a blocked ID card has been detected. Part 2/2 + tr("Therefor you have to enter the PUK first to unlock the ID card PIN.")); + } + } + return QString(); +} + + +void NumberModel::setInitialInputErrorShown() +{ + if (mContext && !mContext->isInitialInputErrorShown()) + { + mContext->setInitialInputErrorShown(); + Q_EMIT firePasswordTypeChanged(); + } +} + + QString NumberModel::getInputError() const { const CardReturnCode paceResult = getInputErrorCode(); @@ -323,72 +366,86 @@ QString NumberModel::getInputError() const case CardReturnCode::INVALID_PIN: if (isRequestTransportPin) { - //: INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. - return tr("You have entered an incorrect, five-digit Transport PIN. " - "You have two further attempts to enter the correct Transport PIN."); + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt. Part 1/2 + tr("You have entered an incorrect, 5-digit Transport PIN."), + //: INFO ALL_PLATFORMS The wrong Transport PIN was entered on the first attempt.Part 2/2 + tr("You have 2 further attempts to enter the correct Transport PIN. " + "The 5-digit Transport PIN may be found on the bottom left of your PIN letter.")); } else if (isSmartCard) { //: INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered on the first attempt. - return tr("You have entered an incorrect, six-digit Smart-eID PIN. You have two further attempts to enter the correct Smart-eID PIN."); + return tr("You have entered an incorrect, 6-digit Smart-eID PIN. You have 2 further attempts to enter the correct Smart-eID PIN."); } else { - //: INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. - return tr("You have entered an incorrect, six-digit ID card PIN. You have two further attempts to enter the correct ID card PIN."); + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 1/2 + tr("You have entered an incorrect, 6-digit ID card PIN."), + //: INFO ALL_PLATFORMS The wrong ID card PIN was entered on the first attempt. Part 2/2 + tr("You have 2 further attempts to enter the correct ID card PIN.")); } case CardReturnCode::INVALID_PIN_2: if (isRequestTransportPin) { - //: INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. - return tr("You have entered an incorrect, five-digit Transport PIN twice. " - "For a third attempt, the six-digit Card Access Number (CAN) must be entered first. " - "You can find your CAN in the bottom right on the front of your ID card."); + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + tr("You have entered an incorrect, 5-digit Transport PIN 2 times."), + //: INFO ALL_PLATFORMS The wrong Transport PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 + tr("For a 3rd attempt, the 6-digit Card Access Number (CAN) must be entered first. " + "You can find your CAN in the bottom right on the front of your ID card.")); } else if (isSmartCard) { - //: INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a third wrong attempt could invalidate the Smart-eID. - return tr("You have entered an incorrect, six-digit Smart-eID PIN twice. " + //: INFO ANDROID IOS The wrong Smart-eID PIN was entered twice, a 3rd wrong attempt could invalidate the Smart-eID. + return tr("You have entered an incorrect, 6-digit Smart-eID PIN 2 times. " "After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again."); } else { - //: INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. - return tr("You have entered an incorrect, six-digit ID card PIN twice. " - "For a third attempt, the six-digit Card Access Number (CAN) must be entered first. " - "You can find your CAN in the bottom right on the front of your ID card."); + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 1/2 + tr("You have entered an incorrect, 6-digit ID card PIN 2 times."), + //: INFO ALL_PLATFORMS The wrong ID card PIN was entered twice, the next attempt requires the CAN for additional verification. Part 2/2 + tr("For a 3rd attempt, the 6-digit Card Access Number (CAN) must be entered first. " + "You can find your CAN in the bottom right on the front of your ID card.")); } case CardReturnCode::INVALID_PIN_3: if (isRequestTransportPin) { //: INFO ALL_PLATFORMS The Transport PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - return tr("You have entered an incorrect, five-digit Transport PIN thrice, your Transport PIN is now blocked. " - "To remove the block, the ten-digit PUK must be entered first."); + return tr("You have entered an incorrect, 5-digit Transport PIN 3 times, your Transport PIN is now blocked. " + "To remove the block, the 10-digit PUK must be entered first."); } else if (isSmartCard) { //: INFO ANDROID IOS The Smart-eID PIN was entered wrongfully three times, the Smart-eID has been invalidated. - return tr("You have entered an incorrect, six-digit Smart-eID PIN thrice. " + return tr("You have entered an incorrect, 6-digit Smart-eID PIN 3 times. " "Your Smart-eID is now invalidated. " "To use a Smart-eID again you have to set one up in the guided setup on the start page."); } else { - //: INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. - return tr("You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. " - "To remove the block, the ten-digit PUK must be entered first."); + return QStringLiteral("%1

%2").arg( + //: INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 1/2 + tr("You have entered an incorrect, 6-digit ID card PIN 3 times. Your ID card PIN is now blocked."), + //: INFO ALL_PLATFORMS The ID card PIN was entered wrongfully three times, the ID card needs to be unlocked using the PUK. Part 2/2 + tr("To remove the block, the 10-digit PUK must be entered first. " + "You can find the PUK in the bottom right next to the Transport PIN in the authority's letter.")); } case CardReturnCode::INVALID_CAN: //: INFO ALL_PLATFORMS The CAN was entered wrongfully and needs to be supplied again. - return tr("You have entered an incorrect, six-digit Card Access Number (CAN). Please try again."); + return tr("You have entered an incorrect Card Access Number (CAN). Please try again. " + "You can find your CAN in the bottom right on the front of your ID card."); case CardReturnCode::INVALID_PUK: //: INFO ALL_PLATFORMS The PUK entered wrongfully and needs to be supplied again. - return tr("You have entered an incorrect, ten-digit PUK. Please try again."); + return tr("You have entered an incorrect, 10-digit PUK. Please try again."); default: return CardReturnCodeUtil::toGlobalStatus(paceResult).toErrorDescription(true); diff --git a/src/ui/qml/NumberModel.h b/src/ui/qml/NumberModel.h index 959570640..af42c1546 100644 --- a/src/ui/qml/NumberModel.h +++ b/src/ui/qml/NumberModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,28 +9,32 @@ #pragma once -#include "EnumHelper.h" #include "Env.h" +#include "SingletonCreator.h" #include "context/WorkflowContext.h" #include #include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus { -defineEnumType(PasswordType, TRANSPORT_PIN, PIN, CAN, PUK, NEW_PIN, NEW_PIN_CONFIRMATION, REMOTE_PIN, SMART_PIN, NEW_SMART_PIN, NEW_SMART_PIN_CONFIRMATION, SMART_BLOCKING_CODE) - class NumberModel : public QObject + , public SingletonCreator { Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(PasswordType passwordType READ getPasswordType NOTIFY firePasswordTypeChanged) Q_PROPERTY(QString can READ getCan WRITE setCan NOTIFY fireCanChanged) @@ -38,10 +42,10 @@ class NumberModel Q_PROPERTY(QString newPin READ getNewPin WRITE setNewPin NOTIFY fireNewPinChanged) Q_PROPERTY(QString newPinConfirmation READ getNewPinConfirmation WRITE setNewPinConfirmation NOTIFY fireNewPinConfirmationChanged) Q_PROPERTY(QString puk READ getPuk WRITE setPuk NOTIFY firePukChanged) - Q_PROPERTY(bool hasPasswordError READ hasPasswordError NOTIFY fireInputErrorChanged) Q_PROPERTY(QString inputError READ getInputError NOTIFY fireInputErrorChanged) Q_PROPERTY(int retryCounter READ getRetryCounter NOTIFY fireReaderInfoChanged) Q_PROPERTY(bool isCanAllowedMode READ isCanAllowedMode NOTIFY fireCanAllowedModeChanged) + Q_PROPERTY(QString initialInputError READ getInitialInputError NOTIFY firePasswordTypeChanged) private: QSharedPointer mContext; @@ -59,6 +63,22 @@ class NumberModel void onCardConnectionChanged(); public: + enum class PasswordType + { + TRANSPORT_PIN, + PIN, + CAN, + PUK, + NEW_PIN, + NEW_PIN_CONFIRMATION, + REMOTE_PIN, + SMART_PIN, + NEW_SMART_PIN, + NEW_SMART_PIN_CONFIRMATION, + SMART_BLOCKING_CODE + }; + Q_ENUM(PasswordType) + void resetContext(const QSharedPointer& pContext = QSharedPointer()); [[nodiscard]] PasswordType getPasswordType() const; @@ -74,16 +94,19 @@ class NumberModel [[nodiscard]] QString getNewPinConfirmation() const; void setNewPinConfirmation(const QString& pNewPinConfirmation); Q_INVOKABLE bool commitNewPin(); + Q_INVOKABLE void resetInputError(); [[nodiscard]] QString getPuk() const; void setPuk(const QString& pPuk); - [[nodiscard]] bool hasPasswordError() const; [[nodiscard]] QString getInputError() const; [[nodiscard]] int getRetryCounter() const; [[nodiscard]] bool isCanAllowedMode() const; + [[nodiscard]] QString getInitialInputError() const; + Q_INVOKABLE void setInitialInputErrorShown(); + private Q_SLOTS: void onReaderInfoChanged(const ReaderInfo& pInfo); diff --git a/src/ui/qml/PersonalizationModel.cpp b/src/ui/qml/PersonalizationModel.cpp index 3d24f0bcd..5efa3fc03 100644 --- a/src/ui/qml/PersonalizationModel.cpp +++ b/src/ui/qml/PersonalizationModel.cpp @@ -1,11 +1,10 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "PersonalizationModel.h" #include "GlobalStatus.h" -#include "LanguageLoader.h" #if __has_include("controller/PersonalizationController.h") #include "AppSettings.h" #include "SecureStorage.h" @@ -21,7 +20,7 @@ PersonalizationModel::PersonalizationModel() } -void PersonalizationModel::startWorkflow() const +void PersonalizationModel::startWorkflow() { #if __has_include("controller/PersonalizationController.h") const bool useTestUri = Env::getSingleton()->getGeneralSettings().useSelfAuthTestUri(); @@ -108,10 +107,10 @@ void PersonalizationModel::resetPersonalizationContext(const QSharedPointer PersonalizationModel::getSupportedReaderPlugInTypes() const +QList PersonalizationModel::getSupportedReaderPluginTypes() const { - auto plugins = WorkflowModel::getSupportedReaderPlugInTypes(); - plugins.removeOne(ReaderManagerPlugInType::SMART); + auto plugins = WorkflowModel::getSupportedReaderPluginTypes(); + plugins.removeOne(ReaderManagerPluginType::SMART); return plugins; } diff --git a/src/ui/qml/PersonalizationModel.h b/src/ui/qml/PersonalizationModel.h index a1b8d1817..e999a6efb 100644 --- a/src/ui/qml/PersonalizationModel.h +++ b/src/ui/qml/PersonalizationModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,14 +9,16 @@ #pragma once #include "AuthModel.h" +#include "SingletonCreator.h" #include "WorkflowRequest.h" #if __has_include("context/PersonalizationContext.h") #include "context/PersonalizationContext.h" #endif +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -26,8 +28,11 @@ class PersonalizationModel : public AuthModel { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(QString blockingCode READ getBlockingCode NOTIFY fireBlockingCodeChanged) Q_PROPERTY(int remainingAttempts READ getRemainingAttempts NOTIFY fireRemainingAttemptsChanged) @@ -48,19 +53,25 @@ class PersonalizationModel #endif public: - Q_INVOKABLE void startWorkflow() const; + static PersonalizationModel* create(const QQmlEngine* pQmlEngine, const QJSEngine* pJSEngine) + { + return SingletonCreator::create(pQmlEngine, pJSEngine); + } + + + Q_INVOKABLE void startWorkflow(); [[nodiscard]] QString getBlockingCode() const; [[nodiscard]] int getRemainingAttempts() const; [[nodiscard]] QString getRestrictionDate() const; [[nodiscard]] QString getBlockingPeriodMessage() const; [[nodiscard]] bool isApplet() const; - [[nodiscard]] QVector getSupportedReaderPlugInTypes() const override; + [[nodiscard]] QList getSupportedReaderPluginTypes() const override; public Q_SLOTS: void onTranslationChanged(); Q_SIGNALS: - void fireStartWorkflow(const QSharedPointer& pRequest) const; + void fireStartWorkflow(const QSharedPointer& pRequest); void fireBlockingCodeChanged(); void fireRemainingAttemptsChanged(); void fireRestrictionDateChanged(); diff --git a/src/ui/qml/PinResetInformationModel.cpp b/src/ui/qml/PinResetInformationModel.cpp index 0a0af91ae..d7b6a1271 100644 --- a/src/ui/qml/PinResetInformationModel.cpp +++ b/src/ui/qml/PinResetInformationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "PinResetInformationModel.h" @@ -14,23 +14,35 @@ using namespace governikus; PinResetInformationModel::PinResetInformationModel() : QObject() { - const auto& providerConfiguration = Env::getSingleton(); + const auto* providerConfiguration = Env::getSingleton(); connect(providerConfiguration, &ProviderConfiguration::fireUpdated, this, &PinResetInformationModel::fireUpdated); } +bool PinResetInformationModel::hasPinResetService() const +{ + const auto* config = Env::getSingleton(); + const auto& info = config->getProviderInfo(QStringLiteral("pinResetService")); + return !info.getAddress().isEmpty(); +} + + QUrl PinResetInformationModel::getPinResetUrl() const { - const auto& config = Env::getSingleton(); + const auto* config = Env::getSingleton(); const auto& info = config->getProviderInfo(QStringLiteral("pinResetService")); const auto& homepage = info.getAddress(); if (homepage.isEmpty()) { - return tr("https://www.personalausweisportal.de/EN"); + if (LanguageLoader::getLocaleCode() == QLatin1String("de")) + { + return QStringLiteral("https://servicesuche.bund.de"); + } + return QStringLiteral("https://servicesuche.bund.de/#/en"); } - if (LanguageLoader::getLocaleCode() != QStringLiteral("de")) + if (LanguageLoader::getLocaleCode() != QLatin1String("de")) { return homepage + QStringLiteral("/en"); } @@ -41,22 +53,31 @@ QUrl PinResetInformationModel::getPinResetUrl() const QString PinResetInformationModel::getNoPinAndNoPukHint() const { - //: LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. - return tr("You cannot use the PUK to reset your previously set card PIN. If you forgot your card PIN, you can use the PIN Reset Service to request a new PIN."); + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. + tr("You cannot use the PUK to reset your previously set card PIN. If you forgot your card PIN, you can use the PIN Reset Service to request a new PIN.") : + //: LABEL ALL_PLATFORMS Hint text for requested PUK but both, PUK and PIN are not known. + tr("If you don't have your Transport PIN letter and no access to the PUK, you may turn to the competent authority and set a new ID card PIN there.") + authorityFinderSuffix(); } QString PinResetInformationModel::getRequestNewPinHint() const { - //: LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK - return tr("Request a new card PIN free of charge to be able to use the eID function again."); + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK + tr("Request a new card PIN to be able to use the eID function again.") : + //: LABEL ALL_PLATFORMS Hint when a workflow failed because of a blocked PUK + tr("You may turn to the competent authority and set a new ID card PIN there.") + authorityFinderSuffix(); } QString PinResetInformationModel::getActivateOnlineFunctionHint() const { - //: LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated - return tr("You can request activation of the eID function without charge."); + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + tr("You can request activation of the eID function.") : + //: LABEL ALL_PLATFORMS Hint when a workflow failed because the eID function was not activated + tr("Please contact the competent authority to activate the eID function.") + authorityFinderSuffix(); } @@ -68,15 +89,57 @@ QString PinResetInformationModel::getActivateOnlineFunctionDescription() const QString PinResetInformationModel::getActivateOnlineFunctionActionText() const { - //: LABEL ALL_PLATFORMS - return tr("Go to Activation Service"); + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS + tr("Go to Activation Service") : + //: LABEL ALL_PLATFORMS + tr("Find competent authority"); +} + + +QString PinResetInformationModel::getPinResetHintNoPin() const +{ + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + tr("You can use the PIN Reset Service to request a new card PIN.") : + //: LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + tr("You may turn to the competent authority and set a new ID card PIN there.") + authorityFinderSuffix(); +} + + +QString PinResetInformationModel::getPinResetHintTransportPin() const +{ + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN, are not known. + tr("If you do not know either your Transport PIN or your card PIN, you can request a new PIN using the PIN Reset Service.") : + //: LABEL ALL_PLATFORMS Hint text for requested Transport PIN but both, Transport PIN and PIN are not known. + tr("If you know neither your Transport PIN nor your ID card PIN, you may turn to the competent authority and set a new ID card PIN there.") + authorityFinderSuffix(); +} + + +QString PinResetInformationModel::getPinResetHint() const +{ + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + tr("If you have forgotten your ID card PIN, you can request a new PIN using the PIN Reset Service.") : + //: LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + tr("If you cannot recall your ID card PIN, you may turn to the competent authority and set a new ID card PIN there.") + authorityFinderSuffix(); } QString PinResetInformationModel::getPinResetActionText() const { - //: LABEL ALL_PLATFORMS - return tr("Go to PIN Reset Service"); + return hasPinResetService() ? + //: LABEL ALL_PLATFORMS + tr("Go to PIN Reset Service") : + //: LABEL ALL_PLATFORMS + tr("Find competent authority"); +} + + +QString PinResetInformationModel::authorityFinderSuffix() const +{ + return QStringLiteral("

") + tr("To find your competent authority you may visit servicesuche.bund.de."); } diff --git a/src/ui/qml/PinResetInformationModel.h b/src/ui/qml/PinResetInformationModel.h index 803e5809d..7d11e554e 100644 --- a/src/ui/qml/PinResetInformationModel.h +++ b/src/ui/qml/PinResetInformationModel.h @@ -1,36 +1,55 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #pragma once +#include "Env.h" +#include "SingletonCreator.h" + #include +#include namespace governikus { class PinResetInformationModel : public QObject + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + + friend class Env; Q_PROPERTY(QUrl pinResetUrl READ getPinResetUrl NOTIFY fireUpdated) Q_PROPERTY(QString noPinAndNoPukHint READ getNoPinAndNoPukHint NOTIFY fireUpdated) Q_PROPERTY(QString requestNewPinHint READ getRequestNewPinHint NOTIFY fireUpdated) Q_PROPERTY(QString activateOnlineFunctionHint READ getActivateOnlineFunctionHint NOTIFY fireUpdated) Q_PROPERTY(QString activateOnlineFunctionDescription READ getActivateOnlineFunctionDescription NOTIFY fireUpdated) + Q_PROPERTY(QString pinResetHintNoPin READ getPinResetHintNoPin NOTIFY fireUpdated) + Q_PROPERTY(QString pinResetHintTransportPin READ getPinResetHintTransportPin NOTIFY fireUpdated) + Q_PROPERTY(QString pinResetHint READ getPinResetHint NOTIFY fireUpdated) Q_PROPERTY(QString pinResetActionText READ getPinResetActionText NOTIFY fireUpdated) - public: + private: PinResetInformationModel(); + ~PinResetInformationModel() override = default; + bool hasPinResetService() const; + public: [[nodiscard]] QUrl getPinResetUrl() const; [[nodiscard]] QString getNoPinAndNoPukHint() const; [[nodiscard]] QString getRequestNewPinHint() const; [[nodiscard]] QString getActivateOnlineFunctionHint() const; [[nodiscard]] QString getActivateOnlineFunctionDescription() const; [[nodiscard]] QString getActivateOnlineFunctionActionText() const; + [[nodiscard]] QString getPinResetHintNoPin() const; + [[nodiscard]] QString getPinResetHintTransportPin() const; + [[nodiscard]] QString getPinResetHint() const; [[nodiscard]] QString getPinResetActionText() const; + [[nodiscard]] QString authorityFinderSuffix() const; public Q_SLOTS: void onTranslationChanged(); diff --git a/src/ui/qml/PlatformTools.h b/src/ui/qml/PlatformTools.h index b26ca925d..8f240f35d 100644 --- a/src/ui/qml/PlatformTools.h +++ b/src/ui/qml/PlatformTools.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ui/qml/PlatformTools_generic.cpp b/src/ui/qml/PlatformTools_generic.cpp index 915333835..de8bfe7e0 100644 --- a/src/ui/qml/PlatformTools_generic.cpp +++ b/src/ui/qml/PlatformTools_generic.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "PlatformTools.h" diff --git a/src/ui/qml/PlatformTools_osx.mm b/src/ui/qml/PlatformTools_osx.mm index 33a326a87..b015b6752 100644 --- a/src/ui/qml/PlatformTools_osx.mm +++ b/src/ui/qml/PlatformTools_osx.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "PlatformTools.h" diff --git a/src/ui/qml/ProxyCredentials.cpp b/src/ui/qml/ProxyCredentials.cpp index d9b127f91..5878f5696 100644 --- a/src/ui/qml/ProxyCredentials.cpp +++ b/src/ui/qml/ProxyCredentials.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "ProxyCredentials.h" diff --git a/src/ui/qml/ProxyCredentials.h b/src/ui/qml/ProxyCredentials.h index 5e03535a6..01b86a231 100644 --- a/src/ui/qml/ProxyCredentials.h +++ b/src/ui/qml/ProxyCredentials.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/ui/qml/ReaderModel.cpp b/src/ui/qml/ReaderModel.cpp index 5833c32a3..e163f22da 100644 --- a/src/ui/qml/ReaderModel.cpp +++ b/src/ui/qml/ReaderModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderModel.h" @@ -41,11 +41,10 @@ SortedReaderModel* ReaderModel::getSortedModel() void ReaderModel::collectReaderData() { - mKnownDrivers.clear(); mConnectedReaders.clear(); - const QVector installedReaders = Env::getSingleton()->getReaderInfos(ReaderFilter({ - ReaderManagerPlugInType::PCSC, ReaderManagerPlugInType::NFC + const QList installedReaders = Env::getSingleton()->getReaderInfos(ReaderFilter({ + ReaderManagerPluginType::PCSC, ReaderManagerPluginType::NFC })); for (const auto& installedReader : installedReaders) @@ -56,7 +55,7 @@ void ReaderModel::collectReaderData() } #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - QVector readersWithoutDriver; + QList readersWithoutDriver; const auto& attachedSupportedDevices = Env::getSingleton()->getAttachedSupportedDevices(); for (const auto& info : attachedSupportedDevices) { @@ -106,23 +105,20 @@ QString ReaderModel::getHTMLDescription(const QModelIndex& pIndex) const return QString(); } - const auto& readerSupported = isSupportedReader(pIndex); - const auto& readerInstalled = isInstalledReader(pIndex); + if (!isPcscScanRunning()) + { + //: LABEL ALL_PLATFORMS + return tr("The smartcard service of your system is not reachable."); + } - if (readerSupported) + if (isSupportedReader(pIndex)) { - if (readerInstalled) + if (isInstalledReader(pIndex)) { //: LABEL ALL_PLATFORMS return tr("Driver installed"); } - if (!Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::PCSC).isScanRunning()) - { - //: LABEL ALL_PLATFORMS - return tr("The smartcard service of your system is not reachable."); - } - //: LABEL ALL_PLATFORMS const auto& driverInfo = tr("No driver installed"); //: INFO ALL_PLATFORMS The driver for card reader needs to be installed, the download link is provided in the message. @@ -151,7 +147,7 @@ bool ReaderModel::isSupportedReader(const QModelIndex& pIndex) const bool ReaderModel::isInstalledReader(const QModelIndex& pIndex) const { - if (!indexIsValid(pIndex)) + if (!indexIsValid(pIndex) || !isPcscScanRunning()) { return false; } @@ -161,6 +157,12 @@ bool ReaderModel::isInstalledReader(const QModelIndex& pIndex) const } +bool ReaderModel::isPcscScanRunning() const +{ + return Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::PCSC).isScanRunning(); +} + + void ReaderModel::onUpdateContent() { beginResetModel(); @@ -174,8 +176,8 @@ void ReaderModel::onUpdateContent() } -ReaderModel::ReaderModel(QObject* pParent) - : QAbstractListModel(pParent) +ReaderModel::ReaderModel() + : QAbstractListModel() , mKnownDrivers() , mConnectedReaders() , mConnectedReadersUpdateTime() diff --git a/src/ui/qml/ReaderModel.h b/src/ui/qml/ReaderModel.h index d9164486d..90028fd06 100644 --- a/src/ui/qml/ReaderModel.h +++ b/src/ui/qml/ReaderModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,30 +8,42 @@ #pragma once +#include "Env.h" #include "ReaderConfigurationInfo.h" +#include "SingletonCreator.h" #include "SortedReaderModel.h" #include #include +#include #include #include -#include +#include +class test_ReaderModel; namespace governikus { class ReaderModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + + friend class Env; + friend class ::test_ReaderModel; Q_PROPERTY(QString lastUpdatedInformation READ getLastUpdatedInformation NOTIFY fireModelChanged) - Q_PROPERTY(SortedReaderModel * sortedModel READ getSortedModel CONSTANT) + Q_PROPERTY(governikus::SortedReaderModel * sortedModel READ getSortedModel CONSTANT) private: + ReaderModel(); + QSet mKnownDrivers; - QVector mConnectedReaders; + QList mConnectedReaders; QTime mConnectedReadersUpdateTime; SortedReaderModel mSortedModel; @@ -44,6 +56,7 @@ class ReaderModel [[nodiscard]] QString getHTMLDescription(const QModelIndex& pIndex) const; [[nodiscard]] bool isSupportedReader(const QModelIndex& pIndex) const; [[nodiscard]] bool isInstalledReader(const QModelIndex& pIndex) const; + [[nodiscard]] bool isPcscScanRunning() const; private Q_SLOTS: void onUpdateContent(); @@ -59,7 +72,6 @@ class ReaderModel READER_INSTALLED, READER_SUPPORTED }; - explicit ReaderModel(QObject* pParent = nullptr); [[nodiscard]] int rowCount(const QModelIndex& pParent = QModelIndex()) const override; [[nodiscard]] QVariant data(const QModelIndex& pIndex, int pRole = Qt::DisplayRole) const override; diff --git a/src/ui/qml/ReaderScanEnabler.cpp b/src/ui/qml/ReaderScanEnabler.cpp index d26406a77..c98d5401e 100644 --- a/src/ui/qml/ReaderScanEnabler.cpp +++ b/src/ui/qml/ReaderScanEnabler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderScanEnabler.h" @@ -18,7 +18,7 @@ using namespace governikus; ReaderScanEnabler::ReaderScanEnabler(QQuickItem* pParent) : QQuickItem(pParent) - , mPlugInType(ReaderManagerPlugInType::UNKNOWN) + , mPluginType(ReaderManagerPluginType::UNKNOWN) , mObligedToStopScan(false) { connect(Env::getSingleton(), &ReaderManager::fireStatusChanged, this, &ReaderScanEnabler::onStatusChanged); @@ -37,18 +37,18 @@ void ReaderScanEnabler::enableScan(const bool pEnable) { if (!isScanRunning()) { - qCDebug(qml) << "Starting scan on" << mPlugInType; - mObligedToStopScan = Env::getSingleton()->getCurrentWorkflow() == ApplicationModel::Workflow::WORKFLOW_NONE; - Env::getSingleton()->startScan(mPlugInType, false); + qCDebug(qml) << "Starting scan on" << mPluginType; + mObligedToStopScan = Env::getSingleton()->getCurrentWorkflow() == ApplicationModel::Workflow::NONE; + Env::getSingleton()->startScan(mPluginType, false); } return; } if (mObligedToStopScan) { - qCDebug(qml) << "Stopping scan on" << mPlugInType; + qCDebug(qml) << "Stopping scan on" << mPluginType; mObligedToStopScan = false; - Env::getSingleton()->stopScan(mPlugInType); + Env::getSingleton()->stopScan(mPluginType); } } @@ -61,37 +61,37 @@ void ReaderScanEnabler::enableScanIfVisible() bool ReaderScanEnabler::isScanRunning() const { - return Env::getSingleton()->getPlugInInfo(mPlugInType).isScanRunning(); + return Env::getSingleton()->getPluginInfo(mPluginType).isScanRunning(); } -void ReaderScanEnabler::onStatusChanged(const ReaderManagerPlugInInfo& pInfo) +void ReaderScanEnabler::onStatusChanged(const ReaderManagerPluginInfo& pInfo) { - if (pInfo.getPlugInType() == mPlugInType) + if (pInfo.getPluginType() == mPluginType) { Q_EMIT fireScanRunningChanged(); } } -ReaderManagerPlugInType ReaderScanEnabler::getPlugInType() const +ReaderManagerPluginType ReaderScanEnabler::getPluginType() const { - return mPlugInType; + return mPluginType; } -void ReaderScanEnabler::setPlugInType(ReaderManagerPlugInType pPlugInType) +void ReaderScanEnabler::setPluginType(ReaderManagerPluginType pPluginType) { - if (mPlugInType == pPlugInType) + if (mPluginType == pPluginType) { return; } enableScan(false); - mPlugInType = pPlugInType; + mPluginType = pPluginType; QMetaObject::invokeMethod(this, &ReaderScanEnabler::enableScanIfVisible, Qt::QueuedConnection); - Q_EMIT firePlugInTypeChanged(); + Q_EMIT firePluginTypeChanged(); Q_EMIT fireScanRunningChanged(); } diff --git a/src/ui/qml/ReaderScanEnabler.h b/src/ui/qml/ReaderScanEnabler.h index 42e7b425a..5f8d698be 100644 --- a/src/ui/qml/ReaderScanEnabler.h +++ b/src/ui/qml/ReaderScanEnabler.h @@ -1,12 +1,13 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include +#include class test_ReaderScanEnabler; @@ -17,13 +18,15 @@ class ReaderScanEnabler : public QQuickItem { Q_OBJECT + QML_ELEMENT + friend class ::test_ReaderScanEnabler; - Q_PROPERTY(ReaderManagerPlugInType plugInType READ getPlugInType WRITE setPlugInType NOTIFY firePlugInTypeChanged) + Q_PROPERTY(governikus::EnumReaderManagerPluginType::ReaderManagerPluginType pluginType READ getPluginType WRITE setPluginType NOTIFY firePluginTypeChanged) Q_PROPERTY(bool scanRunning READ isScanRunning NOTIFY fireScanRunningChanged) private: - ReaderManagerPlugInType mPlugInType; + ReaderManagerPluginType mPluginType; bool mObligedToStopScan; void enableScan(const bool pEnable); @@ -31,19 +34,19 @@ class ReaderScanEnabler [[nodiscard]] bool isScanRunning() const; private Q_SLOTS: - void onStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void onStatusChanged(const ReaderManagerPluginInfo& pInfo); public: explicit ReaderScanEnabler(QQuickItem* pParent = nullptr); ~ReaderScanEnabler() override; - [[nodiscard]] ReaderManagerPlugInType getPlugInType() const; - void setPlugInType(ReaderManagerPlugInType pPlugInType); + [[nodiscard]] ReaderManagerPluginType getPluginType() const; + void setPluginType(ReaderManagerPluginType pPluginType); void itemChange(QQuickItem::ItemChange pChange, const QQuickItem::ItemChangeData& pValue) override; Q_INVOKABLE void restartScan(); Q_SIGNALS: - void firePlugInTypeChanged(); + void firePluginTypeChanged(); void fireScanRunningChanged(); }; diff --git a/src/ui/qml/ReleaseInformationModel.cpp b/src/ui/qml/ReleaseInformationModel.cpp index 16dca1973..c9ccccb52 100644 --- a/src/ui/qml/ReleaseInformationModel.cpp +++ b/src/ui/qml/ReleaseInformationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "ReleaseInformationModel.h" diff --git a/src/ui/qml/ReleaseInformationModel.h b/src/ui/qml/ReleaseInformationModel.h index a0a217c78..fcb5a6b96 100644 --- a/src/ui/qml/ReleaseInformationModel.h +++ b/src/ui/qml/ReleaseInformationModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include #include #include +#include class test_ReleaseInformationModel; @@ -25,10 +26,12 @@ class ReleaseInformationModel : public QObject { Q_OBJECT + QML_ELEMENT + friend class ::test_ReleaseInformationModel; - Q_PROPERTY(FormattedTextModel * currentRelease READ getCurrentRelease NOTIFY fireCurrentInformationChanged) - Q_PROPERTY(FormattedTextModel * updateRelease READ getUpdateRelease NOTIFY fireUpdateInformationChanged) + Q_PROPERTY(governikus::FormattedTextModel * currentRelease READ getCurrentRelease NOTIFY fireCurrentInformationChanged) + Q_PROPERTY(governikus::FormattedTextModel * updateRelease READ getUpdateRelease NOTIFY fireUpdateInformationChanged) Q_PROPERTY(bool allowRetry READ allowRetry NOTIFY fireCurrentInformationChanged) private: diff --git a/src/ui/qml/RemoteDeviceFilterModel.cpp b/src/ui/qml/RemoteDeviceFilterModel.cpp index 8a8e7ff14..32d1f957a 100644 --- a/src/ui/qml/RemoteDeviceFilterModel.cpp +++ b/src/ui/qml/RemoteDeviceFilterModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteDeviceFilterModel.h" diff --git a/src/ui/qml/RemoteDeviceFilterModel.h b/src/ui/qml/RemoteDeviceFilterModel.h index 18d8a3e7b..e30a97bc8 100644 --- a/src/ui/qml/RemoteDeviceFilterModel.h +++ b/src/ui/qml/RemoteDeviceFilterModel.h @@ -1,10 +1,11 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include +#include class test_RemoteDeviceFilterModel; @@ -15,6 +16,8 @@ class RemoteDeviceFilterModel : public QSortFilterProxyModel { Q_OBJECT + QML_UNCREATABLE("Used by RemoteServiceModel only") + QML_ELEMENT friend class ::test_RemoteDeviceFilterModel; diff --git a/src/ui/qml/RemoteDeviceModel.cpp b/src/ui/qml/RemoteDeviceModel.cpp index 0df9944b1..b3dba43da 100644 --- a/src/ui/qml/RemoteDeviceModel.cpp +++ b/src/ui/qml/RemoteDeviceModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteDeviceModel.h" @@ -27,13 +27,13 @@ RemoteDeviceModel::RemoteDeviceModel(QObject* pParent) connect(&settings, &RemoteServiceSettings::fireTrustedRemoteInfosChanged, this, &RemoteDeviceModel::onKnownRemoteReadersChanged); onKnownRemoteReadersChanged(); - const auto& ifdClient = Env::getSingleton(); + const auto* ifdClient = Env::getSingleton(); connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteDeviceModel::onUpdateReaderList); connect(ifdClient, &IfdClient::fireDeviceUpdated, this, &RemoteDeviceModel::onUpdateReaderList); connect(ifdClient, &IfdClient::fireDeviceVanished, this, &RemoteDeviceModel::onUpdateReaderList); connect(ifdClient, &IfdClient::fireDispatcherDestroyed, this, &RemoteDeviceModel::onUpdateReaderList); - const auto& applicationModel = Env::getSingleton(); + const auto* applicationModel = Env::getSingleton(); connect(applicationModel, &ApplicationModel::fireApplicationStateChanged, this, &RemoteDeviceModel::onApplicationStateChanged); } @@ -114,6 +114,41 @@ QString RemoteDeviceModel::getStatus(const RemoteDeviceModelEntry& pRemoteDevice } +QString RemoteDeviceModel::getCurrentDeviceName(const QModelIndex& pIndex) const +{ + const auto& availableReaders = presentReaders(); + for (const auto& availableReader : availableReaders) + { + if (mAllRemoteReaders.at(pIndex.row()).getId() != availableReader.getId()) + { + continue; + } + + const QSharedPointer deviceListEntry = availableReader.getRemoteDeviceListEntry(); + if (deviceListEntry.isNull() || deviceListEntry->getIfdDescriptor().isNull()) + { + break; + } + + return deviceListEntry->getIfdDescriptor().getIfdName(); + } + return {}; +} + + +QString RemoteDeviceModel::constructDisplayDeviceName(const QModelIndex& pIndex) const +{ + const auto& storedName = mAllRemoteReaders.at(pIndex.row()).getDeviceNameEscaped(); + const auto& newRemoteName = getCurrentDeviceName(pIndex); + if (newRemoteName.isNull() || storedName == newRemoteName) + { + return storedName; + } + //: LABEL ALL_PLATFORMS Describes the former name of the device and is shown as: "New_Name (was Old_Name)" + return newRemoteName + QStringLiteral(" (%1 %2)").arg(tr("was"), storedName); +} + + void RemoteDeviceModel::updatePairedReaders() { const auto& availableReaders = presentReaders(); @@ -197,10 +232,10 @@ void RemoteDeviceModel::removeVanishedReaders() } -QVector RemoteDeviceModel::presentReaders() const +QList RemoteDeviceModel::presentReaders() const { const auto& announcingRemoteDevices = Env::getSingleton()->getAnnouncingRemoteDevices(); - QVector presentReaders; + QList presentReaders; for (auto& deviceListEntry : announcingRemoteDevices) { @@ -216,7 +251,7 @@ bool RemoteDeviceModel::addOrUpdateReader(const RemoteDeviceModelEntry& pModelEn { if (!mAllRemoteReaders.contains(pModelEntry)) { - const int readerCount = static_cast(mAllRemoteReaders.size()); + const auto readerCount = static_cast(mAllRemoteReaders.size()); beginInsertRows(index(readerCount, 0), readerCount, readerCount); mAllRemoteReaders.append(pModelEntry); endInsertRows(); @@ -249,7 +284,7 @@ QVariant RemoteDeviceModel::data(const QModelIndex& pIndex, int pRole) const { case Qt::DisplayRole: case REMOTE_DEVICE_NAME: - return reader.getDeviceNameEscaped(); + return constructDisplayDeviceName(pIndex); case REMOTE_DEVICE_STATUS: return getStatus(reader); diff --git a/src/ui/qml/RemoteDeviceModel.h b/src/ui/qml/RemoteDeviceModel.h index cf83b8a43..0ee41ecd7 100644 --- a/src/ui/qml/RemoteDeviceModel.h +++ b/src/ui/qml/RemoteDeviceModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,12 +13,13 @@ #include "RemoteServiceSettings.h" #include +#include #include #include #include #include #include -#include +#include class test_RemoteDeviceModel; @@ -32,12 +33,15 @@ class RemoteDeviceModel : public QAbstractListModel { Q_OBJECT + QML_UNCREATABLE("Used by RemoteServiceModel only") + QML_ELEMENT + friend class ::test_RemoteDeviceModel; friend class ::test_RemoteDeviceFilterModel; private: QMap mPairedReaders; - QVector mAllRemoteReaders; + QList mAllRemoteReaders; RemoteServiceSettings::RemoteInfo mLastPairedDevice; QTimer mTimer; bool mIsDetectingRemoteDevices; @@ -47,10 +51,12 @@ class RemoteDeviceModel [[nodiscard]] bool indexIsValid(const QModelIndex& pIndex) const; [[nodiscard]] QString getStatus(const RemoteDeviceModelEntry& pRemoteDeviceModelEntry) const; + [[nodiscard]] QString getCurrentDeviceName(const QModelIndex& pIndex) const; + [[nodiscard]] QString constructDisplayDeviceName(const QModelIndex& pIndex) const; void updatePairedReaders(); void updateUnpairedReaders(); void removeVanishedReaders(); - [[nodiscard]] QVector presentReaders() const; + [[nodiscard]] virtual QList presentReaders() const; bool addOrUpdateReader(const RemoteDeviceModelEntry& pModelEntry); private Q_SLOTS: diff --git a/src/ui/qml/RemoteDeviceModelEntry.cpp b/src/ui/qml/RemoteDeviceModelEntry.cpp index 425f76b26..c02d54431 100644 --- a/src/ui/qml/RemoteDeviceModelEntry.cpp +++ b/src/ui/qml/RemoteDeviceModelEntry.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteDeviceModelEntry.h" diff --git a/src/ui/qml/RemoteDeviceModelEntry.h b/src/ui/qml/RemoteDeviceModelEntry.h index a20374aa3..1a3fb6c45 100644 --- a/src/ui/qml/RemoteDeviceModelEntry.h +++ b/src/ui/qml/RemoteDeviceModelEntry.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/ui/qml/RemoteServiceModel.cpp b/src/ui/qml/RemoteServiceModel.cpp index 24a21faec..32c0cc255 100644 --- a/src/ui/qml/RemoteServiceModel.cpp +++ b/src/ui/qml/RemoteServiceModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteServiceModel.h" @@ -19,13 +19,6 @@ using namespace governikus; - -namespace -{ -const QRegularExpression percentMatcher = QRegularExpression(QStringLiteral("(\\s|^)(100|\\d{1,2}) ?%")); -} // namespace - - RemoteServiceModel::RemoteServiceModel() : WorkflowModel() , mContext() @@ -56,30 +49,25 @@ RemoteServiceModel::RemoteServiceModel() QQmlEngine::setObjectOwnership(&mAvailablePairedDevices, QQmlEngine::CppOwnership); QQmlEngine::setObjectOwnership(&mUnavailablePairedDevices, QQmlEngine::CppOwnership); - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::firePluginAdded, this, &RemoteServiceModel::onEnvironmentChanged); connect(readerManager, &ReaderManager::fireStatusChanged, this, &RemoteServiceModel::onEnvironmentChanged); connect(readerManager, &ReaderManager::fireReaderAdded, this, &RemoteServiceModel::onEnvironmentChanged); connect(readerManager, &ReaderManager::fireReaderRemoved, this, &RemoteServiceModel::onEnvironmentChanged); - const auto applicationModel = Env::getSingleton(); + const auto* applicationModel = Env::getSingleton(); connect(applicationModel, &ApplicationModel::fireWifiEnabledChanged, this, &RemoteServiceModel::onEnvironmentChanged); connect(applicationModel, &ApplicationModel::fireApplicationStateChanged, this, &RemoteServiceModel::onApplicationStateChanged); const auto* const ifdClient = Env::getSingleton(); connect(ifdClient, &IfdClient::fireDetectionChanged, this, &RemoteServiceModel::fireDetectionChanged); connect(ifdClient, &IfdClient::fireNewDispatcher, this, &RemoteServiceModel::onConnectedDevicesChanged); + connect(ifdClient, &IfdClient::fireDispatcherChanged, this, &RemoteServiceModel::onConnectedDevicesChanged); connect(ifdClient, &IfdClient::fireDispatcherDestroyed, this, &RemoteServiceModel::onConnectedDevicesChanged); connect(ifdClient, &IfdClient::fireDeviceAppeared, this, &RemoteServiceModel::fireRemoteReaderVisibleChanged); connect(ifdClient, &IfdClient::fireDeviceVanished, this, &RemoteServiceModel::fireRemoteReaderVisibleChanged); connect(ifdClient, &IfdClient::fireCertificateRemoved, this, &RemoteServiceModel::fireCertificateRemoved); - connect(this, &WorkflowModel::fireReaderPlugInTypeChanged, this, &RemoteServiceModel::onReaderPlugInTypesChanged); - - const RemoteServiceSettings& settings = Env::getSingleton()->getRemoteServiceSettings(); - connect(&settings, &RemoteServiceSettings::fireInitialDeviceNameSet, this, [](const QString& pName){ - //: LABEL ALL_PLATFORMS - Env::getSingleton()->showFeedback(tr("Pairing with %1 successful.").arg(pName)); - }); + connect(this, &WorkflowModel::fireReaderPluginTypeChanged, this, &RemoteServiceModel::onReaderPluginTypesChanged); QMetaObject::invokeMethod(this, &RemoteServiceModel::onEnvironmentChanged, Qt::QueuedConnection); } @@ -87,11 +75,11 @@ RemoteServiceModel::RemoteServiceModel() void RemoteServiceModel::onEnvironmentChanged() { - const auto& nfcInfo = Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::NFC); + const auto& nfcInfo = Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::NFC); const bool nfcPluginAvailable = nfcInfo.isAvailable(); const bool nfcPluginEnabled = nfcInfo.isEnabled(); - bool readerAvailable = !(Env::getSingleton()->getReaderInfos(ReaderFilter({ReaderManagerPlugInType::NFC})).isEmpty()); + bool readerAvailable = !(Env::getSingleton()->getReaderInfos(ReaderFilter({ReaderManagerPluginType::NFC})).isEmpty()); const bool wifiEnabled = Env::getSingleton()->isWifiEnabled(); const bool runnable = readerAvailable && wifiEnabled; @@ -149,36 +137,36 @@ void RemoteServiceModel::onTranslationChanged() } -void RemoteServiceModel::onReaderPlugInTypesChanged(bool pExplicitStart) +void RemoteServiceModel::onReaderPluginTypesChanged(bool pExplicitStart) { if (!mContext) { return; } - const auto& plugInType = getReaderPlugInType(); + const auto& pluginType = getReaderPluginType(); if (mContext->getIfdServer() && mContext->getIfdServer()->getMessageHandler()) { - mContext->getIfdServer()->getMessageHandler()->setAllowedCardTypes({plugInType}); + mContext->getIfdServer()->getMessageHandler()->setAllowedCardTypes({pluginType}); } auto* readerManager = Env::getSingleton(); - const auto& readerPlugInTypes = Enum::getList(); - for (const auto t : readerPlugInTypes) + const auto& readerPluginTypes = Enum::getList(); + for (const auto t : readerPluginTypes) { - if (t != plugInType) + if (t != pluginType) { readerManager->stopScan(t); continue; } #ifdef Q_OS_IOS - if (plugInType != ReaderManagerPlugInType::NFC || pExplicitStart) + if (pluginType != ReaderManagerPluginType::NFC || pExplicitStart) #else Q_UNUSED(pExplicitStart) #endif { - readerManager->startScan(plugInType); + readerManager->startScan(pluginType); } } } @@ -270,7 +258,7 @@ bool RemoteServiceModel::detectRemoteDevices() const } -void RemoteServiceModel::connectToRememberedServer(const QString& pServerPsk) +void RemoteServiceModel::connectToRememberedServer(const QByteArray& pServerPsk) { if (!pServerPsk.isEmpty() && !mRememberedServerEntry.isNull()) { @@ -283,13 +271,13 @@ void RemoteServiceModel::connectToRememberedServer(const QString& pServerPsk) } -QVector RemoteServiceModel::getSupportedReaderPlugInTypes() const +QList RemoteServiceModel::getSupportedReaderPluginTypes() const { #if __has_include("SmartManager.h") - return {ReaderManagerPlugInType::NFC, ReaderManagerPlugInType::SMART}; + return {ReaderManagerPluginType::NFC, ReaderManagerPluginType::SMART}; #else - return {ReaderManagerPlugInType::NFC}; + return {ReaderManagerPluginType::NFC}; #endif } @@ -314,7 +302,7 @@ void RemoteServiceModel::onEstablishConnectionDone(const QSharedPointersetReaderPlugInTypes({}); + mContext->setReaderPluginTypes({}); } Q_EMIT fireConnectedChanged(); } @@ -363,6 +351,7 @@ void RemoteServiceModel::resetRemoteServiceContext(const QSharedPointergetIfdServer().data(), &IfdServer::firePskChanged, this, [this](const QByteArray& pPsk){ mPsk = pPsk; }); + connect(mContext->getIfdServer().data(), &IfdServer::fireNameChanged, this, &RemoteServiceModel::onNameChanged); connect(mContext->getIfdServer().data(), &IfdServer::firePskChanged, this, &RemoteServiceModel::firePskChanged); connect(mContext.data(), &IfdServiceContext::fireDisplayTextChanged, this, &RemoteServiceModel::fireDisplayTextChanged); connect(mContext->getIfdServer().data(), &IfdServer::fireConnectedChanged, this, &RemoteServiceModel::onConnectionInfoChanged); @@ -383,6 +372,7 @@ void RemoteServiceModel::resetRemoteServiceContext(const QSharedPointergetDisplayText() : QString(); - return displayText.remove(percentMatcher); + return displayText.remove(getPercentMatcher()); } int RemoteServiceModel::getPercentage() const { QString displayText = mContext ? mContext->getDisplayText() : QString(); - return percentMatcher.match(displayText).captured(2).toInt(); + return getPercentMatcher().match(displayText).captured(2).toInt(); } @@ -513,8 +503,12 @@ QString RemoteServiceModel::getErrorMessage(bool pNfcPluginAvailable, bool pNfcP } if (!pNfcPluginAvailable) { - //: INFO ALL_PLATFORMS The device does not offer NFC. - return tr("The NFC radio standard is required for communication with the ID card.\n\nUnfortunately NFC is not available on your device."); + //: ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + return tr("This device cannot be used to read your ID card.") + QStringLiteral("

") + + //: ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + tr("If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader.") + QStringLiteral("

") + + //: ALL_PLATFORMS AA2 can't use NFC on this device, suggest to use SaK instead. + tr("To pair a smartphone go to Settings and Manage Pairings."); } if (!pNfcPluginEnabled) { @@ -526,6 +520,12 @@ QString RemoteServiceModel::getErrorMessage(bool pNfcPluginAvailable, bool pNfcP } +QRegularExpression RemoteServiceModel::getPercentMatcher() const +{ + return QRegularExpression(QStringLiteral("(\\s|^)(100|\\d{1,2}) ?%")); +} + + void RemoteServiceModel::forgetDevice(const QString& pId) { mAllDevices.forgetDevice(pId); @@ -536,7 +536,16 @@ void RemoteServiceModel::cancelPasswordRequest() { if (mContext) { - mContext->cancelPasswordRequest(); + mContext->userError(StatusCode::INPUT_CANCELLED); + } +} + + +void RemoteServiceModel::passwordsDiffer() +{ + if (mContext) + { + mContext->userError(StatusCode::PASSWORDS_DIFFER); } } @@ -568,3 +577,9 @@ void RemoteServiceModel::onConnectedDevicesChanged() mConnectedServerDeviceNames = deviceNames.join(QLatin1String(", ")); Q_EMIT fireConnectedServerDeviceNamesChanged(); } + + +void RemoteServiceModel::onNameChanged() +{ + onConnectionInfoChanged(true); +} diff --git a/src/ui/qml/RemoteServiceModel.h b/src/ui/qml/RemoteServiceModel.h index aeaa3a1db..717917d9d 100644 --- a/src/ui/qml/RemoteServiceModel.h +++ b/src/ui/qml/RemoteServiceModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,15 +11,17 @@ #include "Env.h" #include "RemoteDeviceFilterModel.h" #include "RemoteDeviceModel.h" +#include "SingletonCreator.h" #include "WorkflowModel.h" #include "WorkflowRequest.h" #include "context/IfdServiceContext.h" #include #include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -27,10 +29,14 @@ namespace governikus class RemoteServiceModel : public WorkflowModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(bool running READ isRunning NOTIFY fireIsRunningChanged) Q_PROPERTY(bool isStarting READ isStarting NOTIFY fireIsStartingChanged) @@ -44,10 +50,10 @@ class RemoteServiceModel Q_PROPERTY(bool connectedToPairedDevice READ isConnectedToPairedDevice NOTIFY fireConnectedChanged) Q_PROPERTY(QString connectionInfo READ getConnectionInfo NOTIFY fireConnectionInfoChanged) Q_PROPERTY(QString connectedServerDeviceNames READ getConnectedServerDeviceNames NOTIFY fireConnectedServerDeviceNamesChanged) - Q_PROPERTY(RemoteDeviceModel * allDevices READ getAllDevices CONSTANT) - Q_PROPERTY(RemoteDeviceFilterModel * availableDevicesInPairingMode READ getAvailableDevicesInPairingMode CONSTANT) - Q_PROPERTY(RemoteDeviceFilterModel * availablePairedDevices READ getAvailablePairedDevices CONSTANT) - Q_PROPERTY(RemoteDeviceFilterModel * unavailablePairedDevices READ getUnavailablePairedDevices CONSTANT) + Q_PROPERTY(governikus::RemoteDeviceModel * allDevices READ getAllDevices CONSTANT) + Q_PROPERTY(governikus::RemoteDeviceFilterModel * availableDevicesInPairingMode READ getAvailableDevicesInPairingMode CONSTANT) + Q_PROPERTY(governikus::RemoteDeviceFilterModel * availablePairedDevices READ getAvailablePairedDevices CONSTANT) + Q_PROPERTY(governikus::RemoteDeviceFilterModel * unavailablePairedDevices READ getUnavailablePairedDevices CONSTANT) Q_PROPERTY(bool detectRemoteDevices READ detectRemoteDevices WRITE setDetectRemoteDevices NOTIFY fireDetectionChanged) Q_PROPERTY(bool enableTransportPinLink READ enableTransportPinLink NOTIFY fireEstablishPaceChannelUpdated) Q_PROPERTY(bool remoteReaderVisible READ getRemoteReaderVisible NOTIFY fireRemoteReaderVisibleChanged) @@ -80,6 +86,7 @@ class RemoteServiceModel ~RemoteServiceModel() override = default; QString getErrorMessage(bool pNfcPluginAvailable, bool pNfcPluginEnabled, bool pWifiEnabled) const; + QRegularExpression getPercentMatcher() const; void setStarting(bool pStarting); @@ -92,10 +99,11 @@ class RemoteServiceModel void onEnvironmentChanged(); void onApplicationStateChanged(const bool pIsAppInForeground); void onPairingCompleted(const QSslCertificate& pCertificate); + void onNameChanged(); public Q_SLOTS: void onTranslationChanged(); - void onReaderPlugInTypesChanged(bool pExplicitStart); + void onReaderPluginTypesChanged(bool pExplicitStart); public: [[nodiscard]] bool isRunning() const; @@ -110,8 +118,8 @@ class RemoteServiceModel void setDetectRemoteDevices(bool pNewStatus); [[nodiscard]] bool detectRemoteDevices() const; Q_INVOKABLE bool rememberServer(const QString& pDeviceId); - Q_INVOKABLE void connectToRememberedServer(const QString& pServerPsk); - [[nodiscard]] QVector getSupportedReaderPlugInTypes() const override; + Q_INVOKABLE void connectToRememberedServer(const QByteArray& pServerPsk); + [[nodiscard]] QList getSupportedReaderPluginTypes() const override; void resetRemoteServiceContext(const QSharedPointer& pContext = QSharedPointer()); void setPairing(bool pEnabled) const; @@ -133,6 +141,7 @@ class RemoteServiceModel [[nodiscard]] Q_INVOKABLE bool pinPadModeOn() const; Q_INVOKABLE void forgetDevice(const QString& pId); Q_INVOKABLE void cancelPasswordRequest(); + Q_INVOKABLE void passwordsDiffer(); Q_INVOKABLE void changePinLength(); [[nodiscard]] Q_INVOKABLE bool isPinAuthentication() const; @@ -147,7 +156,7 @@ class RemoteServiceModel void fireServerPskChanged(); void fireDetectionChanged(); void firePairingFailed(const QString& pDeviceName, const QString& pErrorMessage); - void firePairingSuccess(); + void firePairingSuccess(const QString& pDeviceName); void firePairingCompleted(); void fireConnectionInfoChanged(); void fireConnectedServerDeviceNamesChanged(); diff --git a/src/ui/qml/SelfAuthModel.cpp b/src/ui/qml/SelfAuthModel.cpp index 46181544f..837643585 100644 --- a/src/ui/qml/SelfAuthModel.cpp +++ b/src/ui/qml/SelfAuthModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "SelfAuthModel.h" @@ -104,14 +104,14 @@ QVariant SelfAuthModel::data(const QModelIndex& pIndex, int pRole) const { if (pIndex.isValid() && pIndex.row() < rowCount()) { - auto pair = mSelfData.at(pIndex.row()); + const auto& [name, value] = mSelfData.at(pIndex.row()); if (pRole == Qt::DisplayRole || pRole == NAME) { - return pair.first; + return name; } if (pRole == VALUE) { - return pair.second; + return value; } } return QVariant(); diff --git a/src/ui/qml/SelfAuthModel.h b/src/ui/qml/SelfAuthModel.h index e1a9c0ad6..d6b750d5c 100644 --- a/src/ui/qml/SelfAuthModel.h +++ b/src/ui/qml/SelfAuthModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,15 +10,17 @@ #include "Env.h" #include "SelfAuthenticationData.h" +#include "SingletonCreator.h" #include "WorkflowRequest.h" #include #include #include #include +#include -class test_UIPlugInQml; +class test_UiPluginQml; namespace governikus @@ -28,10 +30,14 @@ class SelfAuthContext; class SelfAuthModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; - friend class ::test_UIPlugInQml; + friend class ::test_UiPluginQml; Q_PROPERTY(bool workflowCancelled READ isWorkflowCancelled NOTIFY fireCancelWorkflow FINAL) diff --git a/src/ui/qml/SettingsModel.cpp b/src/ui/qml/SettingsModel.cpp index d467e52b3..21e04e476 100644 --- a/src/ui/qml/SettingsModel.cpp +++ b/src/ui/qml/SettingsModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "SettingsModel.h" @@ -27,13 +27,16 @@ SettingsModel::SettingsModel() connect(Env::getSingleton(), &AppUpdateDataModel::fireAppUpdateDataChanged, this, &SettingsModel::fireAppUpdateDataChanged); const auto& generalSettings = Env::getSingleton()->getGeneralSettings(); - connect(&generalSettings, &GeneralSettings::fireShowInAppNotificationsChanged, this, &SettingsModel::fireShowInAppNotificationsChanged); connect(&generalSettings, &GeneralSettings::fireDeveloperOptionsChanged, this, &SettingsModel::fireDeveloperOptionsChanged); connect(&generalSettings, &GeneralSettings::fireProxyChanged, this, &SettingsModel::fireUseCustomProxyChanged); connect(&generalSettings, &GeneralSettings::fireUseSystemFontChanged, this, &SettingsModel::fireUseSystemFontChanged); + connect(&generalSettings, &GeneralSettings::fireUseAnimationsChanged, this, &SettingsModel::fireUseAnimationsChanged); connect(&generalSettings, &GeneralSettings::fireDarkModeChanged, this, &SettingsModel::fireDarkModeChanged); + const auto& simulatorSettings = Env::getSingleton()->getSimulatorSettings(); + connect(&simulatorSettings, &SimulatorSettings::fireEnabledChanged, this, &SettingsModel::fireSimulatorChanged); + #ifdef Q_OS_ANDROID mIsStartedByAuth = QJniObject::callStaticMethod("com/governikus/ausweisapp2/MainActivity", "isStartedByAuth"); #endif @@ -127,16 +130,16 @@ void SettingsModel::setUseSelfauthenticationTestUri(bool pUse) const } -QString SettingsModel::getServerName() const +QString SettingsModel::getDeviceName() const { - return Env::getSingleton()->getRemoteServiceSettings().getServerName(); + return Env::getSingleton()->getRemoteServiceSettings().getDeviceName(); } -void SettingsModel::setServerName(const QString& name) +void SettingsModel::setDeviceName(const QString& name) { auto& settings = Env::getSingleton()->getRemoteServiceSettings(); - settings.setServerName(name); + settings.setDeviceName(name); Q_EMIT fireDeviceNameChanged(); } @@ -181,23 +184,6 @@ void SettingsModel::setShowAccessRights(bool pShowAccessRights) } -bool SettingsModel::isUseScreenKeyboard() const -{ - return Env::getSingleton()->getGeneralSettings().isUseScreenKeyboard(); -} - - -void SettingsModel::setUseScreenKeyboard(bool pUseScreenKeyboard) -{ - if (isUseScreenKeyboard() != pUseScreenKeyboard) - { - auto& settings = Env::getSingleton()->getGeneralSettings(); - settings.setUseScreenKeyboard(pUseScreenKeyboard); - Q_EMIT fireScreenKeyboardChanged(); - } -} - - bool SettingsModel::isVisualPrivacy() const { return Env::getSingleton()->getGeneralSettings().isVisualPrivacy(); @@ -268,7 +254,7 @@ void SettingsModel::setSkipRightsOnCanAllowed(bool pSkipRightsOnCanAllowed) bool SettingsModel::isSimulatorEnabled() const { - return Env::getSingleton()->getGeneralSettings().isSimulatorEnabled(); + return Env::getSingleton()->getSimulatorSettings().isEnabled(); } @@ -276,8 +262,8 @@ void SettingsModel::setSimulatorEnabled(bool pEnabled) const { if (isSimulatorEnabled() != pEnabled) { - auto& settings = Env::getSingleton()->getGeneralSettings(); - settings.setSimulatorEnabled(pEnabled); + auto& simulatorSettings = Env::getSingleton()->getSimulatorSettings(); + simulatorSettings.setEnabled(pEnabled); } } @@ -378,6 +364,23 @@ void SettingsModel::setAutoCloseWindowAfterAuthentication(bool pEnabled) } +bool SettingsModel::isAutoRedirectAfterAuthentication() const +{ + return Env::getSingleton()->getGeneralSettings().isAutoRedirectAfterAuthentication(); +} + + +void SettingsModel::setAutoRedirectAfterAuthentication(bool pEnabled) +{ + if (isAutoRedirectAfterAuthentication() != pEnabled) + { + auto& settings = Env::getSingleton()->getGeneralSettings(); + settings.setAutoRedirectAfterAuthentication(pEnabled); + Q_EMIT fireAutoRedirectAfterAuthenticationChanged(); + } +} + + bool SettingsModel::isAutoUpdateAvailable() const { return Env::getSingleton()->getGeneralSettings().isAutoUpdateAvailable(); @@ -532,7 +535,23 @@ void SettingsModel::setUseSystemFont(bool pUseSystemFont) const } -ModeOption SettingsModel::getDarkMode() const +bool SettingsModel::isUseAnimations() const +{ + return Env::getSingleton()->getGeneralSettings().isUseAnimations(); +} + + +void SettingsModel::setUseAnimations(bool pUseAnimations) const +{ + if (isUseAnimations() != pUseAnimations) + { + auto& settings = Env::getSingleton()->getGeneralSettings(); + settings.setUseAnimations(pUseAnimations); + } +} + + +SettingsModel::ModeOption SettingsModel::getDarkMode() const { return Enum::fromString( Env::getSingleton()->getGeneralSettings().getDarkMode(), diff --git a/src/ui/qml/SettingsModel.h b/src/ui/qml/SettingsModel.h index d129649a7..900e9a7de 100644 --- a/src/ui/qml/SettingsModel.h +++ b/src/ui/qml/SettingsModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,24 +10,25 @@ #include "AppUpdateDataModel.h" #include "Env.h" +#include "SingletonCreator.h" +#include "UiPlugin.h" #include #include -#include +#include namespace governikus { -defineEnumType(ModeOption, - ON, - OFF, - AUTO - ) - class SettingsModel : public QObject + , public SingletonCreator { Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + QML_ELEMENT + QML_SINGLETON + friend class Env; Q_PROPERTY(QString language READ getLanguage WRITE setLanguage NOTIFY fireLanguageChanged) @@ -38,30 +39,31 @@ class SettingsModel Q_PROPERTY(bool useSelfauthenticationTestUri READ useSelfauthenticationTestUri WRITE setUseSelfauthenticationTestUri NOTIFY fireDeveloperOptionsChanged) Q_PROPERTY(bool pinPadMode READ getPinPadMode WRITE setPinPadMode NOTIFY firePinPadModeChanged) Q_PROPERTY(bool showAccessRights READ getShowAccessRights WRITE setShowAccessRights NOTIFY fireShowAccessRightsChanged) - Q_PROPERTY(QString serverName READ getServerName WRITE setServerName NOTIFY fireDeviceNameChanged) - Q_PROPERTY(bool useScreenKeyboard READ isUseScreenKeyboard WRITE setUseScreenKeyboard NOTIFY fireScreenKeyboardChanged) + Q_PROPERTY(QString deviceName READ getDeviceName WRITE setDeviceName NOTIFY fireDeviceNameChanged) Q_PROPERTY(bool visualPrivacy READ isVisualPrivacy WRITE setVisualPrivacy NOTIFY fireScreenKeyboardChanged) Q_PROPERTY(bool shuffleScreenKeyboard READ isShuffleScreenKeyboard WRITE setShuffleScreenKeyboard NOTIFY fireScreenKeyboardChanged) Q_PROPERTY(bool enableCanAllowed READ isEnableCanAllowed WRITE setEnableCanAllowed NOTIFY fireCanAllowedChanged) Q_PROPERTY(bool skipRightsOnCanAllowed READ isSkipRightsOnCanAllowed WRITE setSkipRightsOnCanAllowed NOTIFY fireCanAllowedChanged) - Q_PROPERTY(bool enableSimulator READ isSimulatorEnabled WRITE setSimulatorEnabled NOTIFY fireDeveloperOptionsChanged) - Q_PROPERTY(UiModule startupModule READ getStartupModule WRITE setStartupModule NOTIFY fireStartupModuleChanged) + Q_PROPERTY(bool enableSimulator READ isSimulatorEnabled WRITE setSimulatorEnabled NOTIFY fireSimulatorChanged) + Q_PROPERTY(governikus::EnumUiModule::UiModule startupModule READ getStartupModule WRITE setStartupModule NOTIFY fireStartupModuleChanged) Q_PROPERTY(bool autoStartAvailable READ isAutoStartAvailable CONSTANT) Q_PROPERTY(bool autoStartApp READ isAutoStart WRITE setAutoStart NOTIFY fireAutoStartChanged) Q_PROPERTY(bool showTrayIcon READ showTrayIcon NOTIFY fireShowTrayIconChanged) Q_PROPERTY(bool autoStartSetByAdmin READ autoStartIsSetByAdmin CONSTANT) Q_PROPERTY(bool autoUpdateAvailable READ isAutoUpdateAvailable CONSTANT) Q_PROPERTY(bool autoCloseWindowAfterAuthentication READ isAutoCloseWindowAfterAuthentication WRITE setAutoCloseWindowAfterAuthentication NOTIFY fireAutoCloseWindowAfterAuthenticationChanged) + Q_PROPERTY(bool autoRedirectAfterAuthentication READ isAutoRedirectAfterAuthentication WRITE setAutoRedirectAfterAuthentication NOTIFY fireAutoRedirectAfterAuthenticationChanged) Q_PROPERTY(bool autoUpdateCheck READ isAutoUpdateCheck WRITE setAutoUpdateCheck NOTIFY fireAutoUpdateCheckChanged) Q_PROPERTY(bool autoUpdateCheckSetByAdmin READ autoUpdateCheckIsSetByAdmin CONSTANT) Q_PROPERTY(bool remindUserToClose READ isRemindUserToClose WRITE setRemindUserToClose NOTIFY fireRemindUserToCloseChanged) Q_PROPERTY(bool transportPinReminder READ isTransportPinReminder WRITE setTransportPinReminder NOTIFY fireTransportPinReminderChanged) Q_PROPERTY(bool showInAppNotifications READ isShowInAppNotifications WRITE setShowInAppNotifications NOTIFY fireShowInAppNotificationsChanged) - Q_PROPERTY(AppUpdateDataModel * appUpdateData READ getAppUpdateData NOTIFY fireAppUpdateDataChanged) + Q_PROPERTY(governikus::AppUpdateDataModel * appUpdateData READ getAppUpdateData NOTIFY fireAppUpdateDataChanged) Q_PROPERTY(QUrl customProxyUrl READ getCustomProxyUrl CONSTANT) Q_PROPERTY(bool customProxyAttributesPresent READ isCustomProxyAttributesPresent CONSTANT) Q_PROPERTY(bool useCustomProxy READ isUseCustomProxy WRITE setUseCustomProxy NOTIFY fireUseCustomProxyChanged) Q_PROPERTY(bool useSystemFont READ isUseSystemFont WRITE setUseSystemFont NOTIFY fireUseSystemFontChanged) + Q_PROPERTY(bool useAnimations READ isUseAnimations WRITE setUseAnimations NOTIFY fireUseAnimationsChanged) Q_PROPERTY(ModeOption userDarkMode READ getDarkMode WRITE setDarkMode NOTIFY fireDarkModeChanged) private: @@ -73,6 +75,14 @@ class SettingsModel ~SettingsModel() override = default; public: + enum class ModeOption + { + ON, + OFF, + AUTO + }; + Q_ENUM(ModeOption) + [[nodiscard]] QString getLanguage() const; void setLanguage(const QString& pLanguage) const; @@ -88,8 +98,8 @@ class SettingsModel [[nodiscard]] bool useSelfauthenticationTestUri() const; void setUseSelfauthenticationTestUri(bool pUse) const; - [[nodiscard]] QString getServerName() const; - void setServerName(const QString& name); + [[nodiscard]] QString getDeviceName() const; + void setDeviceName(const QString& name); Q_INVOKABLE void removeTrustedCertificate(const QString& pFingerprint) const; @@ -99,9 +109,6 @@ class SettingsModel [[nodiscard]] bool getShowAccessRights() const; void setShowAccessRights(bool pShowAccessRights); - [[nodiscard]] bool isUseScreenKeyboard() const; - void setUseScreenKeyboard(bool pUseScreenKeyboard); - [[nodiscard]] bool isVisualPrivacy() const; void setVisualPrivacy(bool pVisualPrivacy); @@ -128,6 +135,9 @@ class SettingsModel [[nodiscard]] bool isAutoCloseWindowAfterAuthentication() const; void setAutoCloseWindowAfterAuthentication(bool pEnabled); + [[nodiscard]] bool isAutoRedirectAfterAuthentication() const; + void setAutoRedirectAfterAuthentication(bool pEnabled); + [[nodiscard]] bool isAutoUpdateAvailable() const; [[nodiscard]] bool isAutoUpdateCheck() const; [[nodiscard]] bool autoUpdateCheckIsSetByAdmin() const; @@ -151,6 +161,9 @@ class SettingsModel [[nodiscard]] bool isUseSystemFont() const; void setUseSystemFont(bool pUseSystemFont) const; + bool isUseAnimations() const; + void setUseAnimations(bool pUseAnimations) const; + [[nodiscard]] ModeOption getDarkMode() const; void setDarkMode(ModeOption pMode); @@ -172,6 +185,7 @@ class SettingsModel void fireLanguageChanged(); void fireAdvancedSettingsChanged(); void fireDeveloperOptionsChanged(); + void fireSimulatorChanged(); void fireDeviceNameChanged(); void firePinPadModeChanged(); void fireShowAccessRightsChanged(); @@ -180,6 +194,7 @@ class SettingsModel void fireStartupModuleChanged(); void fireAutoStartChanged(); void fireAutoCloseWindowAfterAuthenticationChanged(); + void fireAutoRedirectAfterAuthenticationChanged(); void fireAutoUpdateCheckChanged(); void fireRemindUserToCloseChanged(); void fireTransportPinReminderChanged(); @@ -187,6 +202,7 @@ class SettingsModel void fireShowInAppNotificationsChanged(); void fireUseCustomProxyChanged(); void fireUseSystemFontChanged(); + void fireUseAnimationsChanged(); void fireDarkModeChanged(); void fireShowTrayIconChanged(); diff --git a/src/ui/qml/ShareUtil.java b/src/ui/qml/ShareUtil.java index d39944cd1..eea63ba8e 100644 --- a/src/ui/qml/ShareUtil.java +++ b/src/ui/qml/ShareUtil.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ package com.governikus.ausweisapp2; @@ -40,6 +40,10 @@ public static void mailLog(Activity activity, final String email, final String s for (ResolveInfo resolveInfo : emailApps) { String packageName = resolveInfo.activityInfo.packageName; + if ("org.chromium.arc.intent_helper".equals(packageName)) + { + continue; + } Intent shareData = new Intent(Intent.ACTION_SEND); shareData.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name)); diff --git a/src/ui/qml/SingletonCreator.cpp b/src/ui/qml/SingletonCreator.cpp new file mode 100644 index 000000000..a1b5f98fa --- /dev/null +++ b/src/ui/qml/SingletonCreator.cpp @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "SingletonCreator.h" + +#include "UiLoader.h" +#include "UiPluginQml.h" + +using namespace governikus; + +QObject* governikus::registerSingletonModel(QObject* pModel) +{ + QJSEngine::setObjectOwnership(pModel, QJSEngine::CppOwnership); + + const auto& metaObject = pModel->metaObject(); + const auto& onTranslationChangedSlot = metaObject->method(metaObject->indexOfSlot("onTranslationChanged()")); + if (onTranslationChangedSlot.isValid()) + { + const auto& qmlPlugin = Env::getSingleton()->getLoaded(); + if (qmlPlugin) + { + QObject::connect(qmlPlugin, QMetaMethod::fromSignal(&UiPluginQml::fireTranslationChanged), pModel, onTranslationChangedSlot); + } + } + + return pModel; +} diff --git a/src/ui/qml/SingletonCreator.h b/src/ui/qml/SingletonCreator.h new file mode 100644 index 000000000..6da8655a2 --- /dev/null +++ b/src/ui/qml/SingletonCreator.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "Env.h" + +#include + + +namespace governikus +{ + +// Use this in SingletonCreator::create only! +// Avoid another template here to reduce generation +// of a lot of templated functions in the binary. +QObject* registerSingletonModel(QObject* pModel); + +template +class SingletonCreator +{ + public: + static T* create(const QQmlEngine*, const QJSEngine*) + { + return static_cast(registerSingletonModel(Env::getSingleton())); + } + + +}; + +} // namespace governikus diff --git a/src/ui/qml/SmartModel.cpp b/src/ui/qml/SmartModel.cpp index 89b1a0d2c..5f62944ae 100644 --- a/src/ui/qml/SmartModel.cpp +++ b/src/ui/qml/SmartModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartModel.h" @@ -23,7 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(card_smart) SmartModel::SmartModel() : QObject(nullptr) - , mStatus(QmlSmartState::SMART_UNAVAILABLE) + , mStatus(State::UNAVAILABLE) , mErrorString() , mCachedCardInfo(CardType::NONE) , mProgress(0) @@ -36,11 +36,11 @@ SmartModel::SmartModel() void SmartModel::updateStatus() { #if __has_include("SmartManager.h") - const auto& readerManager = Env::getSingleton(); - const auto& smartInfo = readerManager->getPlugInInfo(ReaderManagerPlugInType::SMART); + const auto* readerManager = Env::getSingleton(); + const auto& smartInfo = readerManager->getPluginInfo(ReaderManagerPluginType::SMART); if (smartInfo.isAvailable()) { - setStatus(QmlSmartState::SMART_UPDATING_STATUS); + setStatus(State::UPDATING_STATUS); Env::getSingleton()->callExecuteCommand([] { return QVariant::fromValue(SmartManager::get()->status()); @@ -49,7 +49,7 @@ void SmartModel::updateStatus() return; } - setStatus(QmlSmartState::SMART_UNAVAILABLE); + setStatus(State::UNAVAILABLE); #endif } @@ -66,16 +66,16 @@ void SmartModel::setErrorString(const QString& pError) void SmartModel::updatePinStatus() { - if (getSmartState() == QmlSmartState::SMART_READY || getSmartState() == QmlSmartState::SMART_UPDATING_STATUS) + if (getState() == State::READY || getState() == State::UPDATING_STATUS) { - setStatus(QmlSmartState::SMART_UPDATING_STATUS); - const auto& readerManager = Env::getSingleton(); + setStatus(State::UPDATING_STATUS); + auto* readerManager = Env::getSingleton(); connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &SmartModel::onUpdatePinStatusDone); connect(readerManager, &ReaderManager::fireCardInfoChanged, this, &SmartModel::onUpdatePinStatusDone); - readerManager->startScan(ReaderManagerPlugInType::SMART); - if (Env::getSingleton()->getCurrentWorkflow() == ApplicationModel::Workflow::WORKFLOW_NONE) + readerManager->startScan(ReaderManagerPluginType::SMART); + if (Env::getSingleton()->getCurrentWorkflow() == ApplicationModel::Workflow::NONE) { - readerManager->stopScan(ReaderManagerPlugInType::SMART); + readerManager->stopScan(ReaderManagerPluginType::SMART); } return; } @@ -92,19 +92,19 @@ void SmartModel::setProgress(int pProgress) } -void SmartModel::setStatus(QmlSmartState pNewStatus) +void SmartModel::setStatus(State pNewStatus) { if (mStatus != pNewStatus) { mStatus = pNewStatus; - Q_EMIT fireSmartStateChanged(); + Q_EMIT fireStateChanged(); } } void SmartModel::onUpdateSupportInfoDone(const QVariant& pResult) { - QmlSmartState newStatus = QmlSmartState::SMART_UNAVAILABLE; + State newStatus = State::UNAVAILABLE; #if __has_include("SmartManager.h") const auto& [result, status] = pResult.value(); switch (result) @@ -158,13 +158,13 @@ void SmartModel::onUpdateSupportInfoDone(const QVariant& pResult) { case EidSupportStatus::UNAVAILABLE: case EidSupportStatus::INTERNAL_ERROR: - newStatus = QmlSmartState::SMART_UNAVAILABLE; + newStatus = State::UNAVAILABLE; break; case EidSupportStatus::AVAILABLE: case EidSupportStatus::UP_TO_DATE: case EidSupportStatus::UPDATE_AVAILABLE: - newStatus = QmlSmartState::SMART_NO_PROVISIONING; + newStatus = State::NO_PROVISIONING; break; } } @@ -174,7 +174,7 @@ void SmartModel::onUpdateSupportInfoDone(const QVariant& pResult) if (newStatus != mStatus) { - if (newStatus == QmlSmartState::SMART_NO_PROVISIONING) + if (newStatus == State::NO_PROVISIONING) { updateStatus(); return; @@ -251,29 +251,29 @@ void SmartModel::onDeleteSmartDone(const QVariant& pResult) void SmartModel::onUpdateStatusDone(const QVariant& pResult) { - QmlSmartState newStatus = QmlSmartState::SMART_UNAVAILABLE; + State newStatus = State::UNAVAILABLE; #if __has_include("SmartManager.h") switch (pResult.value()) { case EidStatus::INTERNAL_ERROR: - newStatus = QmlSmartState::SMART_UNAVAILABLE; + newStatus = State::UNAVAILABLE; break; case EidStatus::NO_PROVISIONING: - newStatus = QmlSmartState::SMART_NO_PROVISIONING; + newStatus = State::NO_PROVISIONING; break; case EidStatus::NO_PERSONALIZATION: - newStatus = QmlSmartState::SMART_NO_PERSONALIZATION; + newStatus = State::NO_PERSONALIZATION; break; case EidStatus::UNUSABLE: case EidStatus::CERT_EXPIRED: - newStatus = QmlSmartState::SMART_UNUSABLE; + newStatus = State::UNUSABLE; break; case EidStatus::PERSONALIZED: - newStatus = QmlSmartState::SMART_READY; + newStatus = State::READY; break; } #else @@ -283,7 +283,7 @@ void SmartModel::onUpdateStatusDone(const QVariant& pResult) if (newStatus != mStatus) { - if (newStatus == QmlSmartState::SMART_READY) + if (newStatus == State::READY) { updatePinStatus(); return; @@ -303,29 +303,29 @@ int SmartModel::getProgress() const void SmartModel::onUpdatePinStatusDone(const ReaderInfo& pInfo) { - if (pInfo.getPlugInType() != ReaderManagerPlugInType::SMART) + if (pInfo.getPluginType() != ReaderManagerPluginType::SMART) { return; } - const auto& readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); disconnect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, &SmartModel::onUpdatePinStatusDone); disconnect(readerManager, &ReaderManager::fireCardInfoChanged, this, &SmartModel::onUpdatePinStatusDone); mCachedCardInfo = pInfo.getCardInfo(); - setStatus(QmlSmartState::SMART_READY); + setStatus(State::READY); } -void SmartModel::onStatusChanged(const ReaderManagerPlugInInfo& pInfo) +void SmartModel::onStatusChanged(const ReaderManagerPluginInfo& pInfo) { - if (pInfo.getPlugInType() != ReaderManagerPlugInType::SMART) + if (pInfo.getPluginType() != ReaderManagerPluginType::SMART) { return; } - if (mStatus == QmlSmartState::SMART_UNAVAILABLE && pInfo.isAvailable()) + if (mStatus == State::UNAVAILABLE && pInfo.isAvailable()) { updateStatus(); } @@ -334,11 +334,11 @@ void SmartModel::onStatusChanged(const ReaderManagerPlugInInfo& pInfo) } -SmartModel::QmlSmartState SmartModel::getSmartState() const +SmartModel::State SmartModel::getState() const { - if (mStatus == QmlSmartState::SMART_READY && (mCachedCardInfo.isPinInitial() || mCachedCardInfo.getRetryCounter() < 1)) + if (mStatus == State::READY && (mCachedCardInfo.isPinInitial() || mCachedCardInfo.getRetryCounter() < 1)) { - return QmlSmartState::SMART_UNUSABLE; + return State::UNUSABLE; } return mStatus; @@ -360,7 +360,7 @@ void SmartModel::workflowFinished(QSharedPointer pContext) if (pContext->getAction() == Action::PERSONALIZATION) { - mStatus = QmlSmartState::SMART_UNAVAILABLE; + mStatus = State::UNAVAILABLE; updateStatus(); return; } @@ -372,10 +372,10 @@ void SmartModel::workflowFinished(QSharedPointer pContext) void SmartModel::updateSupportInfo() { #if __has_include("SmartManager.h") - if (mStatus != QmlSmartState::SMART_UPDATING_STATUS && mStatus != QmlSmartState::SMART_READY) + if (mStatus != State::UPDATING_STATUS && mStatus != State::READY) { setErrorString(QString()); - setStatus(QmlSmartState::SMART_UPDATING_STATUS); + setStatus(State::UPDATING_STATUS); Env::getSingleton()->callExecuteCommand([] { return QVariant::fromValue(SmartManager::get()->updateSupportInfo()); @@ -427,5 +427,5 @@ MobileEidType SmartModel::getMobileEidType() const bool SmartModel::isScanRunning() const { - return Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::SMART).isScanRunning(); + return Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::SMART).isScanRunning(); } diff --git a/src/ui/qml/SmartModel.h b/src/ui/qml/SmartModel.h index a12137d5b..0ee82dbdf 100644 --- a/src/ui/qml/SmartModel.h +++ b/src/ui/qml/SmartModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,12 +9,14 @@ #pragma once #include "Env.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" +#include "SingletonCreator.h" #include "context/WorkflowContext.h" #include #include #include +#include class test_SmartModel; @@ -25,31 +27,36 @@ namespace governikus class SmartModel : public QObject + , public SingletonCreator { Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + QML_ELEMENT + QML_SINGLETON + friend class Env; friend class ::test_SmartModel; - Q_PROPERTY(QmlSmartState smartState READ getSmartState NOTIFY fireSmartStateChanged) + Q_PROPERTY(State state READ getState NOTIFY fireStateChanged) Q_PROPERTY(QString errorString READ getErrorString NOTIFY fireErrorStringChanged) Q_PROPERTY(int progress READ getProgress NOTIFY fireProgressChanged) Q_PROPERTY(bool isScanRunning READ isScanRunning NOTIFY fireScanRunningChanged) public: - enum class QmlSmartState + enum class State { - SMART_UPDATING_STATUS, - SMART_UNAVAILABLE, - SMART_NO_PROVISIONING, - SMART_NO_PERSONALIZATION, - SMART_UNUSABLE, - SMART_READY + UPDATING_STATUS, + UNAVAILABLE, + NO_PROVISIONING, + NO_PERSONALIZATION, + UNUSABLE, + READY }; - Q_ENUM(QmlSmartState) + Q_ENUM(State) private: SmartModel(); - QmlSmartState mStatus; + State mStatus; QString mErrorString; CardInfo mCachedCardInfo; int mProgress; @@ -58,7 +65,7 @@ class SmartModel void setErrorString(const QString& pError); void updatePinStatus(); void setProgress(int pProgress); - void setStatus(QmlSmartState pNewStatus); + void setStatus(State pNewStatus); [[nodiscard]] bool isScanRunning() const; @@ -68,10 +75,10 @@ class SmartModel void onDeleteSmartDone(const QVariant& pResult); void onUpdateStatusDone(const QVariant& pResult); void onUpdatePinStatusDone(const ReaderInfo& pInfo); - void onStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void onStatusChanged(const ReaderManagerPluginInfo& pInfo); public: - QmlSmartState getSmartState() const; + State getState() const; [[nodiscard]] QString getErrorString() const; [[nodiscard]] int getProgress() const; @@ -84,7 +91,7 @@ class SmartModel Q_INVOKABLE void deleteSmart(); Q_SIGNALS: - void fireSmartStateChanged(); + void fireStateChanged(); void fireDeleteSmartDone(); void fireDeletePersonalizationDone(bool pSuccess); void fireProgressChanged(); diff --git a/src/ui/qml/SortedReaderModel.cpp b/src/ui/qml/SortedReaderModel.cpp index 843300d87..eeed306d4 100644 --- a/src/ui/qml/SortedReaderModel.cpp +++ b/src/ui/qml/SortedReaderModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SortedReaderModel.h" @@ -10,18 +10,17 @@ using namespace governikus; bool SortedReaderModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const { - const auto& readerSupportedLeft = sourceModel()->data(source_left, ReaderModel::READER_SUPPORTED).toBool(); const auto& readerSupportedRight = sourceModel()->data(source_right, ReaderModel::READER_SUPPORTED).toBool(); - const auto& readerInstalledLeft = sourceModel()->data(source_left, ReaderModel::READER_INSTALLED).toBool(); - const auto& readerInstalledRight = sourceModel()->data(source_right, ReaderModel::READER_INSTALLED).toBool(); - if (readerSupportedLeft == readerSupportedRight) { - return readerInstalledLeft < readerInstalledRight; + const auto& readerInstalledLeft = sourceModel()->data(source_left, ReaderModel::READER_INSTALLED).toBool(); + const auto& readerInstalledRight = sourceModel()->data(source_right, ReaderModel::READER_INSTALLED).toBool(); + + return !readerInstalledLeft && readerInstalledRight; } - return readerSupportedLeft < readerSupportedRight; + return !readerSupportedLeft && readerSupportedRight; } diff --git a/src/ui/qml/SortedReaderModel.h b/src/ui/qml/SortedReaderModel.h index 2667d67ee..699fae560 100644 --- a/src/ui/qml/SortedReaderModel.h +++ b/src/ui/qml/SortedReaderModel.h @@ -1,10 +1,11 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once #include +#include namespace governikus { @@ -13,6 +14,8 @@ class SortedReaderModel : public QSortFilterProxyModel { Q_OBJECT + QML_UNCREATABLE("Used by ReaderModel only") + QML_ELEMENT protected: [[nodiscard]] bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; diff --git a/src/ui/qml/SurveyModel.cpp b/src/ui/qml/SurveyModel.cpp new file mode 100644 index 000000000..04406d032 --- /dev/null +++ b/src/ui/qml/SurveyModel.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "SurveyModel.h" + +#include "Env.h" + + +Q_DECLARE_LOGGING_CATEGORY(network) + +using namespace governikus; + +SurveyModel::SurveyModel() + : QAbstractListModel() + , mData() +{ + connect(Env::getSingleton(), &Survey::fireSurveyDataChanged, this, &SurveyModel::onSurveyDataChanged); + onSurveyDataChanged(); +} + + +void SurveyModel::onSurveyDataChanged() +{ + beginResetModel(); + mData = Env::getSingleton()->getSurveyData(); + endResetModel(); +} + + +int SurveyModel::rowCount(const QModelIndex&) const +{ + return static_cast(mData.size()); +} + + +QVariant SurveyModel::data(const QModelIndex& pIndex, int pRole) const +{ + if (pIndex.isValid() && pIndex.row() < rowCount()) + { + const auto& [title, value] = mData[pIndex.row()]; + if (pRole == TITLE) + { + return title; + } + if (pRole == VALUE) + { + return value; + } + } + return QVariant(); +} + + +QHash SurveyModel::roleNames() const +{ + QHash roles = QAbstractListModel::roleNames(); + roles.insert(TITLE, "title"); + roles.insert(VALUE, "value"); + return roles; +} + + +bool SurveyModel::askForDeviceSurvey() const +{ + return Env::getSingleton()->askForDeviceSurvey(); +} + + +void SurveyModel::setDeviceSurveyPending(bool pValue) const +{ + return Env::getSingleton()->setDeviceSurveyPending(pValue); +} diff --git a/src/ui/qml/SurveyModel.h b/src/ui/qml/SurveyModel.h new file mode 100644 index 000000000..20708b1f4 --- /dev/null +++ b/src/ui/qml/SurveyModel.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "SingletonCreator.h" +#include "Survey.h" + +#include +#include + +namespace governikus +{ + +class SurveyModel + : public QAbstractListModel + , public SingletonCreator +{ + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + + friend class Env; + + private: + Survey::SurveyData mData; + + enum UserRoles + { + TITLE = Qt::UserRole + 1, + VALUE + }; + + SurveyModel(); + ~SurveyModel() override = default; + + private Q_SLOTS: + void onSurveyDataChanged(); + + public: + [[nodiscard]] int rowCount(const QModelIndex& = QModelIndex()) const override; + [[nodiscard]] QVariant data(const QModelIndex& pIndex, int pRole = Qt::DisplayRole) const override; + [[nodiscard]] QHash roleNames() const override; + + [[nodiscard]] Q_INVOKABLE bool askForDeviceSurvey() const; + Q_INVOKABLE void setDeviceSurveyPending(bool pValue) const; +}; + +} // namespace governikus diff --git a/src/ui/qml/TrayIcon.cpp b/src/ui/qml/TrayIcon.cpp index 2d13fc3ae..c7c61f965 100644 --- a/src/ui/qml/TrayIcon.cpp +++ b/src/ui/qml/TrayIcon.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "TrayIcon.h" @@ -109,16 +109,16 @@ void TrayIcon::updateMenu() trayIconMenu->clear(); - #if defined(Q_OS_MACOS) + #if defined(Q_OS_MACOS) || defined(Q_OS_LINUX) || defined(Q_OS_BSD4) //: LABEL DESKTOP - QAction* showApplicationAction = new QAction(tr("Open"), trayIconMenu); + auto* showApplicationAction = new QAction(tr("Open"), trayIconMenu); connect(showApplicationAction, &QAction::triggered, this, &TrayIcon::fireShow); trayIconMenu->addAction(showApplicationAction); trayIconMenu->addSeparator(); #endif //: LABEL DESKTOP - const auto quitAction = new QAction(tr("Quit %1").arg(QCoreApplication::applicationName()), trayIconMenu); + auto* quitAction = new QAction(tr("Quit %1").arg(QCoreApplication::applicationName()), trayIconMenu); connect(quitAction, &QAction::triggered, this, &TrayIcon::fireQuit); trayIconMenu->addAction(quitAction); } @@ -166,18 +166,6 @@ void TrayIcon::setVisible(bool pVisible) } -bool TrayIcon::isVisible() const -{ -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - if (mTrayIcon) - { - mTrayIcon->isVisible(); - } -#endif - return false; -} - - void TrayIcon::showMessage(const QString& pTitle, const QString& pMessage) { #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) diff --git a/src/ui/qml/TrayIcon.h b/src/ui/qml/TrayIcon.h index eba447244..bc7886038 100644 --- a/src/ui/qml/TrayIcon.h +++ b/src/ui/qml/TrayIcon.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -42,7 +42,6 @@ class TrayIcon void create(); void shutdown(); void setVisible(bool pVisible); - [[nodiscard]] bool isVisible() const; void showMessage(const QString& pTitle, const QString& pMessage); diff --git a/src/ui/qml/UIPlugInQml.h b/src/ui/qml/UIPlugInQml.h deleted file mode 100644 index b06544087..000000000 --- a/src/ui/qml/UIPlugInQml.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief UIPlugIn implementation of QML. - */ - -#pragma once - -#include "GlobalStatus.h" -#include "ProxyCredentials.h" -#include "TrayIcon.h" -#include "UIPlugIn.h" - -#include -#include -#include -#if defined (Q_OS_MACOS) - #include -#endif - -#ifdef Q_OS_IOS -Q_FORWARD_DECLARE_OBJC_CLASS(FontChangeTracker); -#endif - - -class test_UIPlugInQml; - - -namespace governikus -{ - -class UIPlugInQml - : public UIPlugIn -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) - Q_PROPERTY(QString platformStyle READ getPlatformStyle CONSTANT FINAL) - Q_PROPERTY(bool debugBuild READ isDebugBuild CONSTANT) - Q_PROPERTY(bool developerVersion READ isDeveloperVersion CONSTANT) - Q_PROPERTY(QString dominator READ getDominator NOTIFY fireDominatorChanged) - Q_PROPERTY(bool dominated READ isDominated NOTIFY fireDominatorChanged) - Q_PROPERTY(QVariantMap safeAreaMargins READ getSafeAreaMargins NOTIFY fireSafeAreaMarginsChanged) - Q_PROPERTY(bool highContrastEnabled READ isHighContrastEnabled NOTIFY fireHighContrastEnabledChanged) - Q_PROPERTY(bool osDarkModeEnabled READ isOsDarkModeEnabled NOTIFY fireOsDarkModeChanged) - Q_PROPERTY(bool osDarkModeSupported READ isOsDarkModeSupported) - Q_PROPERTY(QString fixedFontFamily READ getFixedFontFamily CONSTANT) - Q_PROPERTY(QSize initialWindowSize READ getInitialWindowSize CONSTANT) - Q_PROPERTY(bool showFocusIndicator READ getShowFocusIndicator NOTIFY fireShowFocusIndicator) - Q_PROPERTY(qreal scaleFactor READ getScaleFactor WRITE setScaleFactor NOTIFY fireScaleFactorChanged) - Q_PROPERTY(qreal fontScaleFactor READ getFontScaleFactor NOTIFY fireFontScaleFactorChanged) - friend class ::test_UIPlugInQml; - - private: - QScopedPointer mEngine; - qsizetype mQmlEngineWarningCount; - QString mExplicitPlatformStyle; - bool mUpdateInformationPending; - TrayIcon mTrayIcon; - QString mDominator; - bool mHighContrastEnabled; - bool mDarkMode; -#if defined(Q_OS_MACOS) - QMenuBar mMenuBar; -#endif - bool mShowFocusIndicator; - constexpr static qreal DEFAULT_SCALE_FACTOR = 0.6; - qreal mScaleFactor; - qreal mFontScaleFactor; - - [[nodiscard]] QString getPlatformSelectors() const; - [[nodiscard]] static QUrl getPath(const QString& pRelativePath, bool pQrc = true); - [[nodiscard]] QQuickWindow* getRootWindow() const; - [[nodiscard]] bool isHidden() const; - [[nodiscard]] bool isTablet() const; - [[nodiscard]] bool showUpdateInformationIfPending(); - [[nodiscard]] qreal getSystemFontScaleFactor() const; - void setFontScaleFactor(qreal pFactor); - void setOsDarkMode(bool pState); - -#ifdef Q_OS_IOS - struct Private - { - Private(); - ~Private(); - FontChangeTracker* const mFontChangeTracker; - }; - const QScopedPointer mPrivate; -#endif - - protected: - [[nodiscard]] bool eventFilter(QObject* pObj, QEvent* pEvent) override; - - public: - UIPlugInQml(); - ~UIPlugInQml() override = default; - - static void registerQmlTypes(); - - [[nodiscard]] QString getPlatformStyle() const; - [[nodiscard]] bool isDebugBuild() const; - [[nodiscard]] bool isDeveloperVersion() const; - [[nodiscard]] QString getDominator() const; - [[nodiscard]] bool isDominated() const; - [[nodiscard]] QVariantMap getSafeAreaMargins() const; - [[nodiscard]] bool isHighContrastEnabled() const; - [[nodiscard]] bool isOsDarkModeEnabled() const; - [[nodiscard]] bool isOsDarkModeSupported() const; - [[nodiscard]] QString getFixedFontFamily() const; - [[nodiscard]] QSize getInitialWindowSize() const; - [[nodiscard]] bool getShowFocusIndicator() const; - [[nodiscard]] qreal getScaleFactor() const; - void setScaleFactor(qreal pScaleFactor); - [[nodiscard]] qreal getFontScaleFactor() const; - - - Q_INVOKABLE void applyPlatformStyle(const QString& pPlatformStyle); - Q_INVOKABLE void init(); - Q_INVOKABLE void hideFromTaskbar() const; - - Q_SIGNALS: - void fireShowRequest(UiModule pModule); - void fireHideRequest(); - void fireDominatorChanged(); - void fireSafeAreaMarginsChanged(); - void fireHighContrastEnabledChanged(); - void fireOsDarkModeChanged(); - void fireProxyAuthenticationRequired(ProxyCredentials* pProxyCredentials); - void fireTranslationChanged(); - void fireShowFocusIndicator(); - void fireScaleFactorChanged(); - void fireFontScaleFactorChanged(); - void fireAppConfigChanged(); - - private Q_SLOTS: - void show(); - void doShutdown() override; - void onWorkflowStarted(const QSharedPointer& pRequest) override; - void onWorkflowFinished(const QSharedPointer& pRequest) override; - void onApplicationInitialized() override; - void onApplicationStarted() override; - void onShowUi(UiModule pModule) override; - void onHideUi() override; - void onTranslationChanged() override; - void onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) override; - void onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) override; - void onUiDominationReleased() override; - void onShowUserInformation(const QString& pMessage) override; - void onUpdateScheduled() const; - void onUpdateAvailable(bool pUpdateAvailable, const GlobalStatus& pStatus); - - void onQmlWarnings(const QList& pWarnings); - void onQmlObjectCreated(QObject* pObject); - void onSceneGraphError(QQuickWindow::SceneGraphError pError, const QString& pMessage); - - void onRawLog(const QString& pMessage, const QString& pCategoryName); - - void onWindowPaletteChanged(); - void onUseSystemFontChanged() const; - void onAutoStartChanged(); - void onAppConfigChanged(); - - public Q_SLOTS: - void doRefresh(); -}; - -} // namespace governikus diff --git a/src/ui/qml/UIPlugInQml_generic.cpp b/src/ui/qml/UIPlugInQml_generic.cpp deleted file mode 100644 index a43c46bc9..000000000 --- a/src/ui/qml/UIPlugInQml_generic.cpp +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany - */ - -#include "UIPlugInQml.h" - -#include - -Q_DECLARE_LOGGING_CATEGORY(qml) - -using namespace governikus; - -qreal UIPlugInQml::getSystemFontScaleFactor() const -{ - return 1.0; -} diff --git a/src/ui/qml/UiPluginModel.cpp b/src/ui/qml/UiPluginModel.cpp new file mode 100644 index 000000000..444122527 --- /dev/null +++ b/src/ui/qml/UiPluginModel.cpp @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiPluginModel.h" + +#include "Env.h" +#include "UiLoader.h" +#include "UiPluginQml.h" + +using namespace governikus; + +UiPluginModel::UiPluginModel() + : UiPlugin() +{ +} + + +UiPluginModel* UiPluginModel::create(const QQmlEngine*, const QJSEngine*) +{ + auto* obj = Env::getSingleton()->getLoaded(); + QJSEngine::setObjectOwnership(obj, QJSEngine::CppOwnership); + return obj; +} diff --git a/src/ui/qml/UiPluginModel.h b/src/ui/qml/UiPluginModel.h new file mode 100644 index 000000000..0f3390c5d --- /dev/null +++ b/src/ui/qml/UiPluginModel.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "ProxyCredentials.h" +#include "UiPlugin.h" + +#include +#include +#include +#include +#include + +namespace governikus +{ + +class UiPluginModel + : public UiPlugin +{ + Q_OBJECT + Q_INTERFACES(governikus::UiPlugin) + QML_ELEMENT + QML_SINGLETON + + Q_PROPERTY(bool debugBuild READ isDebugBuild CONSTANT) + Q_PROPERTY(bool developerVersion READ isDeveloperVersion CONSTANT) + Q_PROPERTY(QString dominator READ getDominator NOTIFY fireDominatorChanged) + Q_PROPERTY(bool dominated READ isDominated NOTIFY fireDominatorChanged) + Q_PROPERTY(QVariantMap safeAreaMargins READ getSafeAreaMargins NOTIFY fireSafeAreaMarginsChanged) + Q_PROPERTY(bool highContrastEnabled READ isHighContrastEnabled NOTIFY fireHighContrastEnabledChanged) + Q_PROPERTY(bool osDarkModeEnabled READ isOsDarkModeEnabled NOTIFY fireOsDarkModeChanged) + Q_PROPERTY(bool osDarkModeSupported READ isOsDarkModeSupported CONSTANT) + Q_PROPERTY(QString fixedFontFamily READ getFixedFontFamily CONSTANT) + Q_PROPERTY(QSize initialWindowSize READ getInitialWindowSize CONSTANT) + Q_PROPERTY(bool showFocusIndicator READ getShowFocusIndicator NOTIFY fireShowFocusIndicator) + Q_PROPERTY(qreal scaleFactor READ getScaleFactor WRITE setScaleFactor NOTIFY fireScaleFactorChanged) + Q_PROPERTY(qreal fontScaleFactor READ getFontScaleFactor NOTIFY fireFontScaleFactorChanged) + Q_PROPERTY(bool isChromeOS READ isChromeOS CONSTANT) + + protected: + UiPluginModel(); + ~UiPluginModel() override = default; + + public: + static UiPluginModel* create(const QQmlEngine*, const QJSEngine*); + + [[nodiscard]] virtual bool isDebugBuild() const = 0; + [[nodiscard]] virtual bool isDeveloperVersion() const = 0; + [[nodiscard]] virtual QString getDominator() const = 0; + [[nodiscard]] virtual bool isDominated() const = 0; + [[nodiscard]] virtual QVariantMap getSafeAreaMargins() const = 0; + [[nodiscard]] virtual bool isHighContrastEnabled() const = 0; + [[nodiscard]] virtual bool isOsDarkModeEnabled() const = 0; + [[nodiscard]] virtual bool isOsDarkModeSupported() const = 0; + [[nodiscard]] virtual QString getFixedFontFamily() const = 0; + [[nodiscard]] virtual QSize getInitialWindowSize() const = 0; + [[nodiscard]] virtual bool getShowFocusIndicator() const = 0; + [[nodiscard]] virtual qreal getScaleFactor() const = 0; + virtual void setScaleFactor(qreal pScaleFactor) = 0; + [[nodiscard]] virtual qreal getFontScaleFactor() const = 0; + [[nodiscard]] virtual bool isChromeOS() const = 0; + + Q_INVOKABLE virtual void hideFromTaskbar() const = 0; + Q_INVOKABLE virtual void doRefresh() = 0; + + Q_SIGNALS: + void fireShowRequest(UiModule pModule); + void fireHideRequest(); + void fireDominatorChanged(); + void fireSafeAreaMarginsChanged(); + void fireHighContrastEnabledChanged(); + void fireOsDarkModeChanged(); + void fireProxyAuthenticationRequired(ProxyCredentials* pProxyCredentials); + void fireShowFocusIndicator(); + void fireScaleFactorChanged(); + void fireFontScaleFactorChanged(); +}; + +} // namespace governikus diff --git a/src/ui/qml/UIPlugInQml.cpp b/src/ui/qml/UiPluginQml.cpp similarity index 60% rename from src/ui/qml/UIPlugInQml.cpp rename to src/ui/qml/UiPluginQml.cpp index 7c616b20a..a8d531af7 100644 --- a/src/ui/qml/UIPlugInQml.cpp +++ b/src/ui/qml/UiPluginQml.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInQml.h" +#include "UiPluginQml.h" #include "AppSettings.h" #include "ApplicationModel.h" @@ -26,15 +26,17 @@ #include "PersonalizationModel.h" #include "PinResetInformationModel.h" #include "PlatformTools.h" +#include "ReaderModel.h" #include "ReaderScanEnabler.h" #include "ReleaseInformationModel.h" #include "RemoteServiceModel.h" #include "SelfAuthModel.h" #include "Service.h" #include "SettingsModel.h" +#include "SingletonCreator.h" #include "SmartModel.h" #include "SurveyModel.h" -#include "UILoader.h" +#include "UiLoader.h" #include "VersionInformationModel.h" #include "VersionNumber.h" #include "VolatileSettings.h" @@ -47,17 +49,13 @@ #include "DiagnosisModel.h" #endif -#if defined(Q_OS_WIN) || (defined(Q_OS_BSD4) && !defined(Q_OS_IOS)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) - #include "ReaderModel.h" - #define ENABLE_READERMODEL -#endif #if __has_include("context/PersonalizationContext.h") #include "context/PersonalizationContext.h" #endif #if defined(Q_OS_ANDROID) - #include "UILoader.h" + #include "UiLoader.h" #include #include @@ -84,9 +82,14 @@ #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) #include #endif +#include #include #include +#ifdef Q_OS_WIN + #include + #include +#endif Q_DECLARE_LOGGING_CATEGORY(qml) @@ -98,78 +101,38 @@ INIT_FUNCTION([] { qRegisterMetaType>("QList"); }) +#ifdef Q_OS_WIN namespace { -#if defined(ENABLE_READERMODEL) -template -[[nodiscard]] QObject* provideQmlType(const QQmlEngine*, const QJSEngine*) -{ - return new T(); -} - - -#endif - - -template -[[nodiscard]] QObject* provideSingletonQmlType(const QQmlEngine*, const QJSEngine*) +void updateTitleBarColor(QQuickWindow* pWindow, bool pDarkMode) { - const auto model = Env::getSingleton(); - QQmlEngine::setObjectOwnership(model, QQmlEngine::CppOwnership); - - const auto& metaObject = model->metaObject(); - const auto& onTranslationChangedSlot = metaObject->method(metaObject->indexOfSlot("onTranslationChanged()")); - if (onTranslationChangedSlot.isValid()) + if (pWindow) { - const auto& qmlPlugin = Env::getSingleton()->getLoaded(); - if (qmlPlugin) - { - QObject::connect(qmlPlugin, QMetaMethod::fromSignal(&UIPlugInQml::fireTranslationChanged), model, onTranslationChangedSlot); - } + BOOL darkMode = pDarkMode ? TRUE : FALSE; + HWND hwnd = reinterpret_cast(pWindow->winId()); + #ifdef __MINGW32__ + const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; + #endif + DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &darkMode, sizeof(darkMode)); } - - return model; -} - - -template -void registerQmlSingletonType(const std::function& pTypeProvider) -{ - QByteArray qmlName(T::staticMetaObject.className()); - qmlName.replace(QByteArrayLiteral("governikus::"), QByteArray()); - - const QByteArray url = QByteArrayLiteral("Governikus.Type.") + qmlName; - - qmlRegisterSingletonType(url.constData(), 1, 0, qmlName.constData(), pTypeProvider); -} - - -template -void registerQmlType() -{ - QByteArray qmlName(T::staticMetaObject.className()); - qmlName.replace(QByteArrayLiteral("governikus::"), QByteArray()); - - const QByteArray url = QByteArrayLiteral("Governikus.Type.") + qmlName; - - qmlRegisterType(url.constData(), 1, 0, qmlName.constData()); } } // namespace +#endif -UIPlugInQml::UIPlugInQml() - : UIPlugIn() + +UiPluginQml::UiPluginQml() + : UiPluginModel() , mEngine() +#ifdef Q_OS_MACOS + , mMenuBar() +#endif , mQmlEngineWarningCount(0) - , mExplicitPlatformStyle(getPlatformSelectors()) , mUpdateInformationPending(false) , mTrayIcon() , mHighContrastEnabled(false) , mDarkMode(false) -#if defined(Q_OS_MACOS) - , mMenuBar() -#endif , mShowFocusIndicator(false) , mScaleFactor(DEFAULT_SCALE_FACTOR) , mFontScaleFactor(getSystemFontScaleFactor()) @@ -179,77 +142,51 @@ UIPlugInQml::UIPlugInQml() { Env::getSingleton()->setUsedAsSDK(false); - QFontDatabase::addApplicationFont(QStringLiteral(":/fonts/Roboto-Medium.ttf")); + QFontDatabase::addApplicationFont(QStringLiteral(":/fonts/AusweisApp_Roboto_Regular.ttf")); + QFontDatabase::addApplicationFont(QStringLiteral(":/fonts/AusweisApp_Roboto_Medium.ttf")); + QFontDatabase::addApplicationFont(QStringLiteral(":/fonts/AusweisApp_Roboto_Bold.ttf")); onUseSystemFontChanged(); -#ifdef Q_OS_WIN - QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering); -#endif - #ifndef Q_OS_ANDROID QGuiApplication::setWindowIcon(mTrayIcon.getIcon()); #endif + QGuiApplication::setDesktopFileName(QStringLiteral("com.governikus.ausweisapp2")); - connect(&mTrayIcon, &TrayIcon::fireShow, this, &UIPlugInQml::show); + connect(&mTrayIcon, &TrayIcon::fireShow, this, &UiPluginQml::show); connect(&mTrayIcon, &TrayIcon::fireQuit, this, [this] { Q_EMIT fireQuitApplicationRequest(); }); - connect(this, &UIPlugInQml::fireAppConfigChanged, this, &UIPlugInQml::onAppConfigChanged); + connect(this, &UiPluginQml::fireAppConfigChanged, this, &UiPluginQml::onAppConfigChanged); onAppConfigChanged(); qApp->installEventFilter(this); } -void UIPlugInQml::registerQmlTypes() +void UiPluginQml::registerQmlTypes() { - qmlRegisterUncreatableMetaObject(EnumUiModule::staticMetaObject, "Governikus.Type.UiModule", 1, 0, "UiModule", QStringLiteral("Not creatable as it is an enum type")); - qmlRegisterUncreatableMetaObject(GlobalStatus::staticMetaObject, "Governikus.Type.GlobalStatus", 1, 0, "GlobalStatus", QStringLiteral("Not creatable as it is an enum type")); - qmlRegisterUncreatableMetaObject(EnumReaderManagerPlugInType::staticMetaObject, "Governikus.Type.ReaderPlugIn", 1, 0, "ReaderPlugIn", QStringLiteral("Not creatable as it is an enum type")); - qmlRegisterUncreatableMetaObject(EnumPasswordType::staticMetaObject, "Governikus.Type.PasswordType", 1, 0, "PasswordType", QStringLiteral("Not creatable as it is an enum type")); - qmlRegisterUncreatableMetaObject(FormattedTextModel::staticMetaObject, "Governikus.Type.FormattedTextModel", 1, 0, "LineType", QStringLiteral("Not creatable as it is an enum type")); - qmlRegisterUncreatableMetaObject(EnumModeOption::staticMetaObject, "Governikus.Type.ModeOption", 1, 0, "ModeOption", QStringLiteral("Not creatable as it is an enum type")); - - registerQmlType(); - registerQmlType(); - registerQmlType(); - registerQmlType(); - registerQmlType(); - registerQmlType(); - registerQmlType(); -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - registerQmlType(); -#endif +#ifdef USE_CUSTOM_REGISTRATION + constexpr const char* cModuleName = "Governikus.Type"; + qmlRegisterModule(cModuleName, 1, 0); -#if defined(ENABLE_READERMODEL) - registerQmlSingletonType(&provideQmlType); -#endif + qmlRegisterUncreatableMetaObject(GlobalStatus::staticMetaObject, cModuleName, 1, 0, "GlobalStatus", QStringLiteral("Not creatable as it is an enum type")); + qmlRegisterUncreatableMetaObject(EnumUiModule::staticMetaObject, cModuleName, 1, 0, "UiModule", QStringLiteral("Not creatable as it is an enum type")); + qmlRegisterUncreatableMetaObject(EnumReaderManagerPluginType::staticMetaObject, cModuleName, 1, 0, "ReaderManagerPluginType", QStringLiteral("Not creatable as it is an enum type")); + qmlRegisterUncreatableMetaObject(EnumCardReturnCode::staticMetaObject, cModuleName, 1, 0, "CardReturnCode", QStringLiteral("Not creatable as it is an enum type")); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); - registerQmlSingletonType(&provideSingletonQmlType); + #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) + qmlRegisterType(cModuleName, 1, 0, "DiagnosisModel"); + #endif +#endif } -void UIPlugInQml::init() +void UiPluginQml::init() { - // Activate logging of Qt scenegraph information on startup, e.g. GL_RENDERER, GL_VERSION, ... - qputenv("QSG_INFO", "1"); + if (isChromeOS()) + { + qputenv("QT_QUICK_CONTROLS_HOVER_ENABLED", "1"); + } #if defined(Q_OS_WIN) || defined(Q_OS_MACOS) const QStringList cachePaths = QStandardPaths::standardLocations(QStandardPaths::CacheLocation); @@ -262,31 +199,39 @@ void UIPlugInQml::init() } #endif - // https://bugreports.qt.io/browse/QTBUG-98098 - QQuickStyle::setStyle(QStringLiteral("Basic")); + const auto basicStyle = QStringLiteral("Basic"); + if (QQuickStyle::name() != basicStyle) + { + QQuickStyle::setStyle(basicStyle); + } +#ifdef Q_OS_MACOS + mMenuBar.reset(new QMenuBar()); +#endif mEngine.reset(new QQmlApplicationEngine()); - connect(mEngine.data(), &QQmlApplicationEngine::warnings, this, &UIPlugInQml::onQmlWarnings, Qt::QueuedConnection); - connect(mEngine.data(), &QQmlApplicationEngine::objectCreated, this, &UIPlugInQml::onQmlObjectCreated, Qt::QueuedConnection); + connect(mEngine.data(), &QQmlApplicationEngine::warnings, this, &UiPluginQml::onQmlWarnings, Qt::QueuedConnection); + connect(mEngine.data(), &QQmlApplicationEngine::objectCreated, this, &UiPluginQml::onQmlObjectCreated, Qt::QueuedConnection); - mEngine->rootContext()->setContextProperty(QStringLiteral("plugin"), this); - mEngine->setExtraFileSelectors(mExplicitPlatformStyle.split(QLatin1Char(','))); + UiPluginQml::registerQmlTypes(); - UIPlugInQml::registerQmlTypes(); - -#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) || defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - mEngine->addImportPath(getPath(QStringLiteral("qml/"), false).toString()); + mEngine->addImportPath(QStringLiteral("qrc:///qml/")); +#if (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) + mEngine->addImportPath(QStringLiteral("qrc:///qt/qml/")); + mEngine->load(QStringLiteral("qrc:///qt/qml/Governikus/Init/App.qml")); +#else + #ifndef QT_NO_DEBUG + adjustQmlImportPath(mEngine.data()); + #endif + mEngine->loadFromModule(QAnyStringView("Governikus.Init"), QAnyStringView("App")); #endif - mEngine->addImportPath(getPath(QStringLiteral("qml/")).toString()); - mEngine->load(getPath(QStringLiteral("qml/main.qml"))); QQuickWindow* rootWindow = getRootWindow(); if (rootWindow != nullptr) { - connect(rootWindow, &QQuickWindow::sceneGraphInitialized, this, &UIPlugInQml::fireSafeAreaMarginsChanged, Qt::QueuedConnection); - connect(rootWindow->screen(), &QScreen::orientationChanged, this, &UIPlugInQml::fireSafeAreaMarginsChanged, Qt::QueuedConnection); - connect(rootWindow, &QQuickWindow::sceneGraphError, this, &UIPlugInQml::onSceneGraphError); + connect(rootWindow, &QQuickWindow::sceneGraphInitialized, this, &UiPluginQml::fireSafeAreaMarginsChanged, Qt::QueuedConnection); + connect(rootWindow->screen(), &QScreen::orientationChanged, this, &UiPluginQml::fireSafeAreaMarginsChanged, Qt::QueuedConnection); + connect(rootWindow, &QQuickWindow::sceneGraphError, this, &UiPluginQml::onSceneGraphError); qCDebug(qml) << "Using renderer interface:" << rootWindow->rendererInterface()->graphicsApi(); #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) @@ -298,50 +243,66 @@ void UIPlugInQml::init() } onWindowPaletteChanged(); + +#ifdef Q_OS_WIN + QMetaObject::invokeMethod(this, [] { + Env::getSingleton()->runUpdateIfNeeded(true); + }, Qt::QueuedConnection); +#endif } -void UIPlugInQml::hideFromTaskbar() const +void UiPluginQml::hideFromTaskbar() const { PlatformTools::hideFromTaskbar(); } -QString UIPlugInQml::getPlatformSelectors() const +#ifndef QT_NO_DEBUG +QString UiPluginQml::adjustQmlImportPath(QQmlEngine* pEngine) { - const auto& qtVersion = QStringLiteral("qt6,"); + auto primaryPrefix = QStringLiteral("qrc:/qt/qml"); -#ifndef QT_NO_DEBUG - const char* const overrideSelector = "OVERRIDE_PLATFORM_SELECTOR"; - if (!qEnvironmentVariableIsEmpty(overrideSelector)) + const auto& platform = getOverridePlatform(); + if (!platform.isEmpty() && pEngine) { - const auto& platform = qEnvironmentVariable(overrideSelector); - qCDebug(qml) << "Override platform selector:" << platform; - if (platform.startsWith(QLatin1Char('+')) || platform.contains(QLatin1String(",+"))) + qCDebug(qml) << "Override platform:" << platform; + auto importPath = pEngine->importPathList(); + QMutableListIterator iter(importPath); + while (iter.hasNext()) { - Q_ASSERT(false && "Please supply selectors without a '+'."); + if (iter.next() == primaryPrefix) + { + iter.remove(); + } } - return qtVersion + platform; + primaryPrefix = QStringLiteral("qrc:/%1").arg(platform); + importPath << primaryPrefix; + pEngine->setImportPathList(importPath); } -#endif -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - const QString platform = QStringLiteral("mobile,"); - const QString brand = QGuiApplication::platformName(); -#else - const QString platform = QStringLiteral("desktop,"); - #if defined(Q_OS_WIN) - const QString brand = QStringLiteral("win"); - #else - const QString brand = QStringLiteral("nowin"); - #endif + return primaryPrefix; +} + + #endif - return qtVersion + platform + brand; + +QString UiPluginQml::getOverridePlatform() +{ + QString platform; + + const char* const overrideSelector = "OVERRIDE_PLATFORM"; + if (!qEnvironmentVariableIsEmpty(overrideSelector)) + { + platform = qEnvironmentVariable(overrideSelector); + } + + return platform; } -void UIPlugInQml::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginQml::onWorkflowStarted(const QSharedPointer& pRequest) { if (isDominated()) { @@ -401,7 +362,7 @@ void UIPlugInQml::onWorkflowStarted(const QSharedPointer& pRequ } -void UIPlugInQml::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginQml::onWorkflowFinished(const QSharedPointer& pRequest) { const auto& context = pRequest->getContext(); Env::getSingleton()->keepScreenOn(false); @@ -461,31 +422,31 @@ void UIPlugInQml::onWorkflowFinished(const QSharedPointer& pReq } -void UIPlugInQml::onApplicationInitialized() +void UiPluginQml::onApplicationInitialized() { - connect(Env::getSingleton(), &AuthModel::fireShowUiRequest, this, &UIPlugIn::fireShowUiRequested); - connect(Env::getSingleton(), &ChangePinModel::fireStartWorkflow, this, &UIPlugIn::fireWorkflowRequested); - connect(Env::getSingleton(), &SelfAuthModel::fireStartWorkflow, this, &UIPlugIn::fireWorkflowRequested); - connect(Env::getSingleton(), &RemoteServiceModel::fireStartWorkflow, this, &UIPlugIn::fireWorkflowRequested); - connect(Env::getSingleton(), &PersonalizationModel::fireStartWorkflow, this, &UIPlugIn::fireWorkflowRequested); - connect(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireRawLog, this, &UIPlugInQml::onRawLog, Qt::QueuedConnection); - connect(Env::getSingleton(), &SettingsModel::fireAutoStartChanged, this, &UIPlugInQml::onAutoStartChanged); - connect(Env::getSingleton(), &SettingsModel::fireUseSystemFontChanged, this, &UIPlugInQml::onUseSystemFontChanged); + connect(Env::getSingleton(), &AuthModel::fireShowUiRequest, this, &UiPlugin::fireShowUiRequested); + connect(Env::getSingleton(), &ChangePinModel::fireStartWorkflow, this, &UiPlugin::fireWorkflowRequested); + connect(Env::getSingleton(), &SelfAuthModel::fireStartWorkflow, this, &UiPlugin::fireWorkflowRequested); + connect(Env::getSingleton(), &RemoteServiceModel::fireStartWorkflow, this, &UiPlugin::fireWorkflowRequested); + connect(Env::getSingleton(), &PersonalizationModel::fireStartWorkflow, this, &UiPlugin::fireWorkflowRequested); + connect(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireRawLog, this, &UiPluginQml::onRawLog, Qt::QueuedConnection); + connect(Env::getSingleton(), &SettingsModel::fireAutoStartChanged, this, &UiPluginQml::onAutoStartChanged); + connect(Env::getSingleton(), &SettingsModel::fireUseSystemFontChanged, this, &UiPluginQml::onUseSystemFontChanged); const auto* service = Env::getSingleton(); - connect(service, &Service::fireAppcastFinished, this, &UIPlugInQml::onUpdateAvailable); - connect(service, &Service::fireUpdateScheduled, this, &UIPlugInQml::onUpdateScheduled); + connect(service, &Service::fireAppcastFinished, this, &UiPluginQml::onAppcastFinished); + connect(service, &Service::fireUpdateScheduled, this, &UiPluginQml::onUpdateScheduled); init(); } -void UIPlugInQml::onApplicationStarted() +void UiPluginQml::onApplicationStarted() { mTrayIcon.create(); - connect(this, &UIPlugInQml::fireTranslationChanged, &mTrayIcon, &TrayIcon::onTranslationChanged); + connect(this, &UiPluginQml::fireTranslationChanged, &mTrayIcon, &TrayIcon::onTranslationChanged); -#if defined(ENABLE_READERMODEL) +#if defined(Q_OS_WIN) || (defined(Q_OS_BSD4) && !defined(Q_OS_IOS)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) const auto& generalSettings = Env::getSingleton()->getGeneralSettings(); const bool showSetupAssistant = Enum::fromString(generalSettings.getStartupModule(), UiModule::TUTORIAL) == UiModule::TUTORIAL; const bool developerMode = generalSettings.isDeveloperMode(); @@ -493,7 +454,7 @@ void UIPlugInQml::onApplicationStarted() if (missingTrayIcon || showSetupAssistant || developerMode) #endif { - QMetaObject::invokeMethod(this, &UIPlugInQml::show, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &UiPluginQml::show, Qt::QueuedConnection); } #if defined(Q_OS_ANDROID) @@ -506,7 +467,7 @@ void UIPlugInQml::onApplicationStarted() } -void UIPlugInQml::onShowUi(UiModule pModule) +void UiPluginQml::onShowUi(UiModule pModule) { PlatformTools::restoreToTaskbar(); #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) @@ -526,13 +487,13 @@ void UIPlugInQml::onShowUi(UiModule pModule) } -void UIPlugInQml::onHideUi() +void UiPluginQml::onHideUi() { Q_EMIT fireHideRequest(); } -void UIPlugInQml::onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) +void UiPluginQml::onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) { ProxyCredentials proxyCredentials(pProxy, pAuthenticator); @@ -541,7 +502,7 @@ void UIPlugInQml::onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAu } -void UIPlugInQml::onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) +void UiPluginQml::onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) { if (pUi == this) { @@ -556,7 +517,7 @@ void UIPlugInQml::onUiDomination(const UIPlugIn* pUi, const QString& pInformatio } -void UIPlugInQml::onUiDominationReleased() +void UiPluginQml::onUiDominationReleased() { if (!mDominator.isNull()) { @@ -566,7 +527,7 @@ void UIPlugInQml::onUiDominationReleased() } -void UIPlugInQml::onShowUserInformation(const QString& pMessage) +void UiPluginQml::onShowUserInformation(const QString& pMessage) { #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) Env::getSingleton()->showFeedback(pMessage); @@ -582,7 +543,7 @@ void UIPlugInQml::onShowUserInformation(const QString& pMessage) } -void UIPlugInQml::onUpdateScheduled() const +void UiPluginQml::onUpdateScheduled() const { if (!isHidden()) { @@ -591,14 +552,13 @@ void UIPlugInQml::onUpdateScheduled() const } -void UIPlugInQml::onUpdateAvailable(bool pUpdateAvailable, const GlobalStatus& pStatus) +void UiPluginQml::onAppcastFinished(bool pUpdateAvailable) { - Q_UNUSED(pStatus) mUpdateInformationPending = pUpdateAvailable; } -void UIPlugInQml::show() +void UiPluginQml::show() { if (!showUpdateInformationIfPending()) { @@ -607,7 +567,7 @@ void UIPlugInQml::show() } -bool UIPlugInQml::showUpdateInformationIfPending() +bool UiPluginQml::showUpdateInformationIfPending() { if (!mUpdateInformationPending) { @@ -621,7 +581,7 @@ bool UIPlugInQml::showUpdateInformationIfPending() } -bool UIPlugInQml::eventFilter(QObject* pObj, QEvent* pEvent) +bool UiPluginQml::eventFilter(QObject* pObj, QEvent* pEvent) { if (pEvent->type() == QEvent::ApplicationPaletteChange) { @@ -637,12 +597,6 @@ bool UIPlugInQml::eventFilter(QObject* pObj, QEvent* pEvent) } #endif - if (pEvent->type() == QEvent::Quit) - { - Q_EMIT fireQuitApplicationRequest(); - return true; - } - if (pEvent->type() == QEvent::FocusIn) { const auto focusEvent = static_cast(pEvent); @@ -658,7 +612,7 @@ bool UIPlugInQml::eventFilter(QObject* pObj, QEvent* pEvent) } -void UIPlugInQml::onTranslationChanged() +void UiPluginQml::onTranslationChanged() { if (mEngine) { @@ -668,26 +622,15 @@ void UIPlugInQml::onTranslationChanged() } -void UIPlugInQml::doShutdown() +void UiPluginQml::doShutdown() { mTrayIcon.shutdown(); } -QUrl UIPlugInQml::getPath(const QString& pRelativePath, bool pQrc) -{ - if (pQrc) - { - return QStringLiteral("qrc:///") + pRelativePath; - } - - return QUrl::fromLocalFile(FileDestination::getPath(pRelativePath, QStandardPaths::LocateDirectory)); -} - - -QQuickWindow* UIPlugInQml::getRootWindow() const +QQuickWindow* UiPluginQml::getRootWindow() const { - if (mEngine->rootObjects().isEmpty()) + if (!mEngine || mEngine->rootObjects().isEmpty()) { return nullptr; } @@ -696,32 +639,14 @@ QQuickWindow* UIPlugInQml::getRootWindow() const } -bool UIPlugInQml::isHidden() const +bool UiPluginQml::isHidden() const { const QQuickWindow* rootWindow = getRootWindow(); return !rootWindow || rootWindow->visibility() == QWindow::Hidden; } -#ifndef Q_OS_IOS -bool UIPlugInQml::isTablet() const -{ - #ifdef Q_OS_ANDROID - QJniObject context = QNativeInterface::QAndroidApplication::context(); - const jboolean result = context.callMethod("isTablet", "()Z"); - return result != JNI_FALSE; - - #else - return false; - - #endif -} - - -#endif - - -void UIPlugInQml::onQmlWarnings(const QList& pWarnings) +void UiPluginQml::onQmlWarnings(const QList& pWarnings) { mQmlEngineWarningCount += pWarnings.size(); @@ -734,7 +659,7 @@ void UIPlugInQml::onQmlWarnings(const QList& pWarnings) } -void UIPlugInQml::onQmlObjectCreated(QObject* pObject) +void UiPluginQml::onQmlObjectCreated(QObject* pObject) { const bool fatalErrors = pObject == nullptr; const QString result = fatalErrors ? QStringLiteral("fatal errors.") : QStringLiteral("%1 warnings.").arg(mQmlEngineWarningCount); @@ -748,7 +673,7 @@ void UIPlugInQml::onQmlObjectCreated(QObject* pObject) } -void UIPlugInQml::onSceneGraphError(QQuickWindow::SceneGraphError pError, const QString& pMessage) +void UiPluginQml::onSceneGraphError(QQuickWindow::SceneGraphError pError, const QString& pMessage) { qCDebug(qml) << "Cannot initialize UI rendering:" << pError << '|' << pMessage; @@ -763,7 +688,7 @@ void UIPlugInQml::onSceneGraphError(QQuickWindow::SceneGraphError pError, const } -void UIPlugInQml::onRawLog(const QString& pMessage, const QString& pCategoryName) +void UiPluginQml::onRawLog(const QString& pMessage, const QString& pCategoryName) { if (pCategoryName == QLatin1String("developermode") || pCategoryName == QLatin1String("feedback")) { @@ -780,20 +705,19 @@ void UIPlugInQml::onRawLog(const QString& pMessage, const QString& pCategoryName } -void UIPlugInQml::doRefresh() +void UiPluginQml::doRefresh() { qCDebug(qml) << "Reload qml files"; - QMetaObject::invokeMethod(this, &UIPlugInQml::init, Qt::QueuedConnection); -} - - -QString UIPlugInQml::getPlatformStyle() const -{ - return mExplicitPlatformStyle; + QMetaObject::invokeMethod(this, &UiPluginQml::init, Qt::QueuedConnection); +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_WINRT) + QMetaObject::invokeMethod(this, [this]{ + Q_EMIT fireShowUiRequested(UiModule::CURRENT); + }, Qt::QueuedConnection); +#endif } -bool UIPlugInQml::isDebugBuild() const +bool UiPluginQml::isDebugBuild() const { #ifndef QT_NO_DEBUG return true; @@ -805,26 +729,26 @@ bool UIPlugInQml::isDebugBuild() const } -bool UIPlugInQml::isDeveloperVersion() const +bool UiPluginQml::isDeveloperVersion() const { return VersionNumber::getApplicationVersion().isDeveloperVersion(); } -QString UIPlugInQml::getDominator() const +QString UiPluginQml::getDominator() const { return mDominator; } -bool UIPlugInQml::isDominated() const +bool UiPluginQml::isDominated() const { return !mDominator.isNull(); } #ifndef Q_OS_IOS -QVariantMap UIPlugInQml::getSafeAreaMargins() const +QVariantMap UiPluginQml::getSafeAreaMargins() const { QVariantMap marginMap; @@ -862,10 +786,10 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_MainActivity_notifySafeAr Q_UNUSED(pObj) QMetaObject::invokeMethod(QCoreApplication::instance(), [] { - UIPlugInQml* const uiPlugIn = Env::getSingleton()->getLoaded(); - if (uiPlugIn) + UiPluginQml* const uiPlugin = Env::getSingleton()->getLoaded(); + if (uiPlugin) { - Q_EMIT uiPlugIn->fireSafeAreaMarginsChanged(); + Q_EMIT uiPlugin->fireSafeAreaMarginsChanged(); } }, Qt::QueuedConnection); } @@ -876,7 +800,7 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_MainActivity_notifySafeAr #endif #ifndef Q_OS_MACOS -bool UIPlugInQml::isHighContrastEnabled() const +bool UiPluginQml::isHighContrastEnabled() const { #ifdef Q_OS_WIN HIGHCONTRAST hc; @@ -892,24 +816,28 @@ bool UIPlugInQml::isHighContrastEnabled() const #endif -bool UIPlugInQml::isOsDarkModeEnabled() const +bool UiPluginQml::isOsDarkModeEnabled() const { return mDarkMode; } -void UIPlugInQml::setOsDarkMode(bool pState) +void UiPluginQml::setOsDarkMode(bool pState) { if (mDarkMode != pState) { qCDebug(qml) << "Dark mode setting has changed"; mDarkMode = pState; + +#ifdef Q_OS_WIN + updateTitleBarColor(getRootWindow(), pState); +#endif Q_EMIT fireOsDarkModeChanged(); } } -bool UIPlugInQml::isOsDarkModeSupported() const +bool UiPluginQml::isOsDarkModeSupported() const { #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) return true; @@ -921,34 +849,37 @@ bool UIPlugInQml::isOsDarkModeSupported() const } -QString UIPlugInQml::getFixedFontFamily() const +QString UiPluginQml::getFixedFontFamily() const { return QFontDatabase::systemFont(QFontDatabase::FixedFont).family(); } -QSize UIPlugInQml::getInitialWindowSize() const +QSize UiPluginQml::getInitialWindowSize() const { - const QString platform = getPlatformSelectors(); - bool isMobile = platform.contains(QLatin1String("mobile")); - return isMobile ? QSize(432, 768) : QSize(960, 720); + const auto& platform = getOverridePlatform(); + if (platform == QAnyStringView("android") || platform == QAnyStringView("ios")) + { + return QSize(432, 768); + } + return QSize(960, 720); } -bool UIPlugInQml::getShowFocusIndicator() const +bool UiPluginQml::getShowFocusIndicator() const { return mShowFocusIndicator; } -qreal UIPlugInQml::getScaleFactor() const +qreal UiPluginQml::getScaleFactor() const { return mScaleFactor; } -void UIPlugInQml::setScaleFactor(qreal pScaleFactor) +void UiPluginQml::setScaleFactor(qreal pScaleFactor) { pScaleFactor *= DEFAULT_SCALE_FACTOR; @@ -961,13 +892,26 @@ void UIPlugInQml::setScaleFactor(qreal pScaleFactor) } -qreal UIPlugInQml::getFontScaleFactor() const +qreal UiPluginQml::getFontScaleFactor() const { return mFontScaleFactor; } -void UIPlugInQml::setFontScaleFactor(qreal pFactor) +bool UiPluginQml::isChromeOS() const +{ +#ifdef Q_OS_ANDROID + if (QJniObject activity = QNativeInterface::QAndroidApplication::context(); activity.isValid()) + { + return activity.callMethod("isChromeOS"); + } +#endif + + return false; +} + + +void UiPluginQml::setFontScaleFactor(qreal pFactor) { if (pFactor != mFontScaleFactor) { @@ -978,7 +922,7 @@ void UIPlugInQml::setFontScaleFactor(qreal pFactor) } -void UIPlugInQml::onWindowPaletteChanged() +void UiPluginQml::onWindowPaletteChanged() { const bool highContrast = isHighContrastEnabled(); if (mHighContrastEnabled != highContrast) @@ -989,8 +933,13 @@ void UIPlugInQml::onWindowPaletteChanged() } -void UIPlugInQml::onUseSystemFontChanged() const +void UiPluginQml::onUseSystemFontChanged() const { + const auto guard = qScopeGuard([] { + const auto& family = QGuiApplication::font().family(); + qDebug() << "Using" << family << "with styles" << QFontDatabase::styles(family); + }); + if (Env::getSingleton()->getGeneralSettings().isUseSystemFont()) { auto font = QFontDatabase::systemFont(QFontDatabase::GeneralFont); @@ -1005,42 +954,28 @@ void UIPlugInQml::onUseSystemFontChanged() const return; } - const auto robotoMedium = QStringLiteral("Roboto Medium"); - const auto roboto = QStringLiteral("Roboto"); - const auto families = QFontDatabase::families(); - if (families.contains(robotoMedium)) + const auto& knownFamilies = QFontDatabase::families(); + const QStringList families = {QStringLiteral("AusweisApp_Roboto"), QStringLiteral("Roboto")}; + for (const auto& family : families) { - QGuiApplication::setFont(QFont(robotoMedium)); - } - else if (families.contains(roboto)) - { - QGuiApplication::setFont(QFont(roboto)); - } - else - { - qCCritical(qml) << "Roboto was not found in the FontDatabase. Staying on system default."; + if (knownFamilies.contains(family)) + { + QGuiApplication::setFont(QFont(family)); + return; + } } + + qCCritical(qml) << "Roboto was not found in the FontDatabase. Staying on system default."; } -void UIPlugInQml::onAutoStartChanged() +void UiPluginQml::onAutoStartChanged() { mTrayIcon.setVisible(Env::getSingleton()->getGeneralSettings().showTrayIcon()); } -void UIPlugInQml::onAppConfigChanged() +void UiPluginQml::onAppConfigChanged() { setFontScaleFactor(getSystemFontScaleFactor()); } - - -void UIPlugInQml::applyPlatformStyle(const QString& pPlatformStyle) -{ - const auto& platformStyle = QStringLiteral("qt6,%1").arg(pPlatformStyle); - if (mExplicitPlatformStyle != platformStyle) - { - mExplicitPlatformStyle = platformStyle; - doRefresh(); - } -} diff --git a/src/ui/qml/UiPluginQml.h b/src/ui/qml/UiPluginQml.h new file mode 100644 index 000000000..7f9f6714a --- /dev/null +++ b/src/ui/qml/UiPluginQml.h @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ + +/*! + * \brief UiPlugin implementation of QML. + */ + +#pragma once + +#include "GlobalStatus.h" +#include "ProxyCredentials.h" +#include "TrayIcon.h" +#include "UiPluginModel.h" + +#include +#include +#include +#if defined (Q_OS_MACOS) + #include +#endif + +#ifdef Q_OS_IOS +Q_FORWARD_DECLARE_OBJC_CLASS(FontChangeTracker); +#endif + + +class test_UiPluginQml; + + +namespace governikus +{ + +class UiPluginQml + : public UiPluginModel +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) + friend class ::test_UiPluginQml; + + private: + QScopedPointer mEngine; +#ifdef Q_OS_MACOS + QScopedPointer mMenuBar; +#endif + qsizetype mQmlEngineWarningCount; + bool mUpdateInformationPending; + TrayIcon mTrayIcon; + QString mDominator; + bool mHighContrastEnabled; + bool mDarkMode; + bool mShowFocusIndicator; + constexpr static qreal DEFAULT_SCALE_FACTOR = 0.6; + qreal mScaleFactor; + qreal mFontScaleFactor; + + void init(); + [[nodiscard]] static QString getOverridePlatform(); + [[nodiscard]] QQuickWindow* getRootWindow() const; + [[nodiscard]] bool isHidden() const; + [[nodiscard]] bool showUpdateInformationIfPending(); + [[nodiscard]] qreal getSystemFontScaleFactor() const; + void setFontScaleFactor(qreal pFactor); + void setOsDarkMode(bool pState); + +#ifdef Q_OS_IOS + struct Private + { + Private(); + ~Private(); + FontChangeTracker* const mFontChangeTracker; + }; + const QScopedPointer mPrivate; +#endif + + protected: + [[nodiscard]] bool eventFilter(QObject* pObj, QEvent* pEvent) override; + + public: + UiPluginQml(); + ~UiPluginQml() override = default; + + static void registerQmlTypes(); +#ifndef QT_NO_DEBUG + static QString adjustQmlImportPath(QQmlEngine* pEngine); +#endif + + [[nodiscard]] bool isDebugBuild() const override; + [[nodiscard]] bool isDeveloperVersion() const override; + [[nodiscard]] QString getDominator() const override; + [[nodiscard]] bool isDominated() const override; + [[nodiscard]] QVariantMap getSafeAreaMargins() const override; + [[nodiscard]] bool isHighContrastEnabled() const override; + [[nodiscard]] bool isOsDarkModeEnabled() const override; + [[nodiscard]] bool isOsDarkModeSupported() const override; + [[nodiscard]] QString getFixedFontFamily() const override; + [[nodiscard]] QSize getInitialWindowSize() const override; + [[nodiscard]] bool getShowFocusIndicator() const override; + [[nodiscard]] qreal getScaleFactor() const override; + void setScaleFactor(qreal pScaleFactor) override; + [[nodiscard]] qreal getFontScaleFactor() const override; + [[nodiscard]] bool isChromeOS() const override; + + Q_INVOKABLE void hideFromTaskbar() const override; + Q_INVOKABLE void doRefresh() override; + + Q_SIGNALS: + void fireTranslationChanged(); + void fireAppConfigChanged(); + + private Q_SLOTS: + void show(); + void doShutdown() override; + void onWorkflowStarted(const QSharedPointer& pRequest) override; + void onWorkflowFinished(const QSharedPointer& pRequest) override; + void onApplicationInitialized() override; + void onApplicationStarted() override; + void onShowUi(UiModule pModule) override; + void onHideUi() override; + void onTranslationChanged() override; + void onProxyAuthenticationRequired(const QNetworkProxy& pProxy, QAuthenticator* pAuthenticator) override; + void onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) override; + void onUiDominationReleased() override; + void onShowUserInformation(const QString& pMessage) override; + void onUpdateScheduled() const; + void onAppcastFinished(bool pUpdateAvailable); + + void onQmlWarnings(const QList& pWarnings); + void onQmlObjectCreated(QObject* pObject); + void onSceneGraphError(QQuickWindow::SceneGraphError pError, const QString& pMessage); + + void onRawLog(const QString& pMessage, const QString& pCategoryName); + + void onWindowPaletteChanged(); + void onUseSystemFontChanged() const; + void onAutoStartChanged(); + void onAppConfigChanged(); +}; + +} // namespace governikus diff --git a/src/ui/qml/UIPlugInQml_android.cpp b/src/ui/qml/UiPluginQml_android.cpp similarity index 83% rename from src/ui/qml/UIPlugInQml_android.cpp rename to src/ui/qml/UiPluginQml_android.cpp index f0f5ae086..8ffd09dce 100644 --- a/src/ui/qml/UIPlugInQml_android.cpp +++ b/src/ui/qml/UiPluginQml_android.cpp @@ -1,11 +1,11 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInQml.h" +#include "UiPluginQml.h" #include "Env.h" -#include "UILoader.h" +#include "UiLoader.h" #include #include @@ -23,15 +23,15 @@ JNIEXPORT void JNICALL Java_com_governikus_ausweisapp2_MainActivity_notifyConfig Q_UNUSED(pEnv) Q_UNUSED(pObj) QMetaObject::invokeMethod(QCoreApplication::instance(), [] { - if (auto* uiPlugIn = Env::getSingleton()->getLoaded()) + if (auto* uiPlugin = Env::getSingleton()->getLoaded()) { - Q_EMIT uiPlugIn->fireAppConfigChanged(); + Q_EMIT uiPlugin->fireAppConfigChanged(); } }, Qt::QueuedConnection); } -qreal UIPlugInQml::getSystemFontScaleFactor() const +qreal UiPluginQml::getSystemFontScaleFactor() const { QJniObject ctx = QNativeInterface::QAndroidApplication::context(); if (!ctx.isValid()) diff --git a/src/ui/qml/UiPluginQml_generic.cpp b/src/ui/qml/UiPluginQml_generic.cpp new file mode 100644 index 000000000..f223cb8c2 --- /dev/null +++ b/src/ui/qml/UiPluginQml_generic.cpp @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiPluginQml.h" + +#include + +Q_DECLARE_LOGGING_CATEGORY(qml) + +using namespace governikus; + +qreal UiPluginQml::getSystemFontScaleFactor() const +{ + return 1.0; +} diff --git a/src/ui/qml/UIPlugInQml_ios.mm b/src/ui/qml/UiPluginQml_ios.mm similarity index 72% rename from src/ui/qml/UIPlugInQml_ios.mm rename to src/ui/qml/UiPluginQml_ios.mm index 1ba8d936f..399e7c0c9 100644 --- a/src/ui/qml/UIPlugInQml_ios.mm +++ b/src/ui/qml/UiPluginQml_ios.mm @@ -1,11 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInQml.h" +#include "UiPluginQml.h" #include "Env.h" -#include "UILoader.h" +#include "UiLoader.h" #include @@ -44,9 +44,9 @@ - (void)receiveNotification:(NSNotification*)notification UIContentSizeCategoryDidChangeNotification]) { QMetaObject::invokeMethod(QCoreApplication::instance(), [] { - if (auto* uiPlugIn = Env::getSingleton()->getLoaded()) + if (auto* uiPlugin = Env::getSingleton()->getLoaded()) { - Q_EMIT uiPlugIn->fireAppConfigChanged(); + Q_EMIT uiPlugin->fireAppConfigChanged(); } }, Qt::QueuedConnection); } @@ -56,24 +56,18 @@ - (void)receiveNotification:(NSNotification*)notification @end -UIPlugInQml::Private::Private() : mFontChangeTracker([[FontChangeTracker alloc] init]) +UiPluginQml::Private::Private() : mFontChangeTracker([[FontChangeTracker alloc] init]) { } // It's important that the definition of the destructor is in a .mm file: Otherwise the compiler won't compile it in Objective-C++ mode and ARC won't work. -UIPlugInQml::Private::~Private() +UiPluginQml::Private::~Private() { } -bool UIPlugInQml::isTablet() const -{ - return [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad; -} - - -QVariantMap UIPlugInQml::getSafeAreaMargins() const +QVariantMap UiPluginQml::getSafeAreaMargins() const { UIViewController* rootController = [UIApplication sharedApplication].windows[0].rootViewController; @@ -90,8 +84,8 @@ - (void)receiveNotification:(NSNotification*)notification } -qreal UIPlugInQml::getSystemFontScaleFactor() const +qreal UiPluginQml::getSystemFontScaleFactor() const { UIFont* font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - return font.pointSize / 14.0; + return font.pointSize / 15.0; } diff --git a/src/ui/qml/UIPlugInQml_osx.mm b/src/ui/qml/UiPluginQml_osx.mm similarity index 57% rename from src/ui/qml/UIPlugInQml_osx.mm rename to src/ui/qml/UiPluginQml_osx.mm index 7cf56bd4f..85914089c 100644 --- a/src/ui/qml/UIPlugInQml_osx.mm +++ b/src/ui/qml/UiPluginQml_osx.mm @@ -1,11 +1,11 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInQml.h" +#include "UiPluginQml.h" #include "Env.h" -#include "UILoader.h" +#include "UiLoader.h" #include @@ -16,13 +16,13 @@ using namespace governikus; -bool UIPlugInQml::isHighContrastEnabled() const +bool UiPluginQml::isHighContrastEnabled() const { return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast; } -qreal UIPlugInQml::getSystemFontScaleFactor() const +qreal UiPluginQml::getSystemFontScaleFactor() const { return 1.0; } diff --git a/src/ui/qml/VersionInformationModel.cpp b/src/ui/qml/VersionInformationModel.cpp index 0bbf9dc67..9096e3450 100644 --- a/src/ui/qml/VersionInformationModel.cpp +++ b/src/ui/qml/VersionInformationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -56,14 +56,14 @@ QVariant VersionInformationModel::data(const QModelIndex& pIndex, int pRole) con { if (pIndex.isValid() && pIndex.row() < rowCount()) { - const auto& entry = std::as_const(mData).at(pIndex.row()); + const auto& [label, text] = std::as_const(mData).at(pIndex.row()); if (pRole == LABEL) { - return entry.first; + return label; } if (pRole == TEXT) { - return entry.second; + return text; } } return QVariant(); diff --git a/src/ui/qml/VersionInformationModel.h b/src/ui/qml/VersionInformationModel.h index b36aeb66f..9f0e081b0 100644 --- a/src/ui/qml/VersionInformationModel.h +++ b/src/ui/qml/VersionInformationModel.h @@ -1,23 +1,30 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once +#include "Env.h" +#include "SingletonCreator.h" + #include #include #include #include +#include -#include "Env.h" namespace governikus { class VersionInformationModel : public QAbstractListModel + , public SingletonCreator { Q_OBJECT + QML_ELEMENT + QML_SINGLETON + friend class Env; private: @@ -26,7 +33,7 @@ class VersionInformationModel LABEL = Qt::UserRole + 1, TEXT }; - QVector> mData; + QList> mData; VersionInformationModel(); ~VersionInformationModel() override = default; diff --git a/src/ui/qml/WorkflowModel.cpp b/src/ui/qml/WorkflowModel.cpp index 3b26ff170..793608ce5 100644 --- a/src/ui/qml/WorkflowModel.cpp +++ b/src/ui/qml/WorkflowModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "WorkflowModel.h" @@ -23,27 +23,25 @@ using namespace governikus; INIT_FUNCTION([] { - qRegisterMetaType>("QVector"); + qRegisterMetaType>("QList"); }) -WorkflowModel::WorkflowModel(QObject* pParent) - : QObject(pParent) +WorkflowModel::WorkflowModel() + : QObject() , mContext() #if defined(Q_OS_IOS) , mRemoteScanWasRunning(false) #endif { - connect(Env::getSingleton(), &ReaderManager::fireCardInserted, this, &WorkflowModel::onReaderManagerSignal); - connect(Env::getSingleton(), &ReaderManager::fireCardRemoved, this, &WorkflowModel::onReaderManagerSignal); - connect(Env::getSingleton(), &ReaderManager::fireReaderAdded, this, &WorkflowModel::onReaderManagerSignal); - connect(Env::getSingleton(), &ReaderManager::fireReaderRemoved, this, &WorkflowModel::onReaderManagerSignal); - connect(Env::getSingleton(), &SmartModel::fireSmartStateChanged, this, &WorkflowModel::fireIsCurrentSmartCardAllowedChanged); + connect(Env::getSingleton(), &ReaderManager::fireCardInserted, this, &WorkflowModel::fireHasCardChanged); + connect(Env::getSingleton(), &ReaderManager::fireCardRemoved, this, &WorkflowModel::fireHasCardChanged); + connect(Env::getSingleton(), &ReaderManager::fireReaderAdded, this, &WorkflowModel::fireHasCardChanged); + connect(Env::getSingleton(), &ReaderManager::fireReaderRemoved, this, &WorkflowModel::fireHasCardChanged); + connect(Env::getSingleton(), &SmartModel::fireStateChanged, this, &WorkflowModel::fireIsCurrentSmartCardAllowedChanged); connect(Env::getSingleton(), &ApplicationModel::fireApplicationStateChanged, this, &WorkflowModel::onApplicationStateChanged); - connect(&Env::getSingleton()->getGeneralSettings(), &GeneralSettings::fireDeveloperOptionsChanged, this, &WorkflowModel::fireSupportedPlugInTypesChanged); - - QMetaObject::invokeMethod(this, &WorkflowModel::onReaderManagerSignal, Qt::QueuedConnection); + connect(&Env::getSingleton()->getGeneralSettings(), &GeneralSettings::fireDeveloperOptionsChanged, this, &WorkflowModel::fireSupportedPluginTypesChanged); } @@ -55,14 +53,16 @@ void WorkflowModel::resetWorkflowContext(const QSharedPointer& connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &WorkflowModel::fireCurrentStateChanged); connect(mContext.data(), &WorkflowContext::fireStateChanged, this, &WorkflowModel::fireStateEntered); connect(mContext.data(), &WorkflowContext::fireResultChanged, this, &WorkflowModel::fireResultChanged); - connect(mContext.data(), &WorkflowContext::fireReaderPlugInTypesChanged, this, &WorkflowModel::fireReaderPlugInTypeChanged); - connect(mContext.data(), &WorkflowContext::fireReaderPlugInTypesChanged, this, &WorkflowModel::fireHasCardChanged); + connect(mContext.data(), &WorkflowContext::fireReaderPluginTypesChanged, this, &WorkflowModel::fireReaderPluginTypeChanged); + connect(mContext.data(), &WorkflowContext::fireReaderPluginTypesChanged, this, &WorkflowModel::fireHasCardChanged); connect(mContext.data(), &WorkflowContext::fireCardConnectionChanged, this, &WorkflowModel::fireSelectedReaderChanged); connect(mContext.data(), &WorkflowContext::fireCardConnectionChanged, this, &WorkflowModel::fireHasCardChanged); connect(mContext.data(), &WorkflowContext::fireEidTypeMismatchChanged, this, &WorkflowModel::fireIsCurrentSmartCardAllowedChanged); connect(mContext.data(), &WorkflowContext::fireEidTypeMismatchChanged, this, &WorkflowModel::fireEidTypeMismatchErrorChanged); connect(mContext.data(), &WorkflowContext::fireNextWorkflowPending, this, &WorkflowModel::fireNextWorkflowPendingChanged); connect(mContext.data(), &WorkflowContext::fireRemoveCardFeedbackChanged, this, &WorkflowModel::fireRemoveCardFeedbackChanged); + connect(mContext.data(), &WorkflowContext::firePaceResultUpdated, this, &WorkflowModel::onPaceResultUpdated); + connect(mContext.data(), &WorkflowContext::firePaceResultUpdated, this, &WorkflowModel::fireLastReturnCodeChanged); Q_EMIT fireWorkflowStarted(); } else @@ -99,31 +99,41 @@ bool WorkflowModel::isMaskedError() const } -ReaderManagerPlugInType WorkflowModel::getReaderPlugInType() const +CardReturnCode WorkflowModel::getLastReturnCode() const +{ + if (mContext) + { + return mContext->getLastPaceResult(); + } + return CardReturnCode::UNDEFINED; +} + + +ReaderManagerPluginType WorkflowModel::getReaderPluginType() const { - if (mContext && !mContext->getReaderPlugInTypes().isEmpty()) + if (mContext && !mContext->getReaderPluginTypes().isEmpty()) { - return mContext->getReaderPlugInTypes().at(0); + return mContext->getReaderPluginTypes().at(0); } - return ReaderManagerPlugInType::UNKNOWN; + return ReaderManagerPluginType::UNKNOWN; } -void WorkflowModel::setReaderPlugInType(ReaderManagerPlugInType pReaderPlugInType) +void WorkflowModel::setReaderPluginType(ReaderManagerPluginType pReaderPluginType) { if (!mContext) { return; } - mContext->setReaderPlugInTypes({pReaderPlugInType}); + mContext->setReaderPluginTypes({pReaderPluginType}); auto& settings = Env::getSingleton()->getGeneralSettings(); - settings.setLastReaderPluginType(getEnumName(pReaderPlugInType)); + settings.setLastReaderPluginType(getEnumName(pReaderPluginType)); } -void WorkflowModel::insertCard(ReaderManagerPlugInType pType) const +void WorkflowModel::insertCard(ReaderManagerPluginType pType) const { auto* const readerManager = Env::getSingleton(); const auto& readerInfos = readerManager->getReaderInfos(ReaderFilter({pType})); @@ -135,15 +145,15 @@ void WorkflowModel::insertCard(ReaderManagerPlugInType pType) const } -void WorkflowModel::insertSmartCard() +void WorkflowModel::insertSmartCard() const { - insertCard(ReaderManagerPlugInType::SMART); + insertCard(ReaderManagerPluginType::SMART); } -void WorkflowModel::insertSimulator() +void WorkflowModel::insertSimulator() const { - insertCard(ReaderManagerPlugInType::SIMULATOR); + insertCard(ReaderManagerPluginType::SIMULATOR); } @@ -169,7 +179,7 @@ void WorkflowModel::startScanExplicitly() { if (mContext) { - Q_EMIT mContext->fireReaderPlugInTypesChanged(true); + Q_EMIT mContext->fireReaderPluginTypesChanged(true); } } @@ -189,7 +199,7 @@ bool WorkflowModel::isRemoteReader() const { if (mContext && mContext->getCardConnection()) { - return mContext->getCardConnection()->getReaderInfo().getPlugInType() == ReaderManagerPlugInType::REMOTE_IFD; + return mContext->getCardConnection()->getReaderInfo().getPluginType() == ReaderManagerPluginType::REMOTE_IFD; } return false; @@ -203,7 +213,7 @@ bool WorkflowModel::hasCard() const return false; } - const auto& readerInfos = Env::getSingleton()->getReaderInfos(ReaderFilter({getReaderPlugInType()})); + const auto& readerInfos = Env::getSingleton()->getReaderInfos(ReaderFilter({getReaderPluginType()})); const auto& readersWithEid = filter([](const ReaderInfo& i){return i.hasEid();}, readerInfos); return !readersWithEid.isEmpty(); } @@ -216,23 +226,17 @@ bool WorkflowModel::isCurrentSmartCardAllowed() const } -bool WorkflowModel::isSmartSupported() const +QList WorkflowModel::getSupportedReaderPluginTypes() const { - return getSupportedReaderPlugInTypes().contains(ReaderManagerPlugInType::SMART); -} - + auto supported = Enum::getList(); -QVector WorkflowModel::getSupportedReaderPlugInTypes() const -{ - auto supported = Enum::getList(); - - if (!Env::getSingleton()->getGeneralSettings().isSimulatorEnabled()) + if (!Env::getSingleton()->getSimulatorSettings().isEnabled()) { - supported.removeOne(ReaderManagerPlugInType::SIMULATOR); + supported.removeOne(ReaderManagerPluginType::SIMULATOR); } #if !__has_include("SmartManager.h") - supported.removeOne(ReaderManagerPlugInType::SMART); + supported.removeOne(ReaderManagerPluginType::SMART); #endif return supported; @@ -251,12 +255,6 @@ GlobalStatus::Code WorkflowModel::getStatusCode() const } -QString WorkflowModel::getReaderImage() const -{ - return mReaderImage; -} - - QString WorkflowModel::getStatusCodeImage() const { switch (getStatusCode()) @@ -330,6 +328,21 @@ QString WorkflowModel::getStatusHintText() const } +QString WorkflowModel::getStatusHintTitle() const +{ + switch (getStatusCode()) + { + case GlobalStatus::Code::Card_Puk_Blocked: + case GlobalStatus::Code::Card_Pin_Deactivated: + //: LABEL ALL_PLATFORMS Hint title to assist the user on how to set a new PIN + return tr("Set a new PIN"); + + default: + return QString(); + } +} + + QString WorkflowModel::getStatusHintActionText() const { switch (getStatusCode()) @@ -390,20 +403,20 @@ void WorkflowModel::setInitialPluginType() const GeneralSettings& settings = Env::getSingleton()->getGeneralSettings(); const QString& lastReaderPluginTypeString = settings.getLastReaderPluginType(); - const auto& lastReaderPluginType = Enum::fromString(lastReaderPluginTypeString, ReaderManagerPlugInType::UNKNOWN); + const auto& lastReaderPluginType = Enum::fromString(lastReaderPluginTypeString, ReaderManagerPluginType::UNKNOWN); - if (lastReaderPluginType == ReaderManagerPlugInType::UNKNOWN || !getSupportedReaderPlugInTypes().contains(lastReaderPluginType)) + if (lastReaderPluginType == ReaderManagerPluginType::UNKNOWN || !getSupportedReaderPluginTypes().contains(lastReaderPluginType)) { - setReaderPlugInType(ReaderManagerPlugInType::NFC); + setReaderPluginType(ReaderManagerPluginType::NFC); return; } - setReaderPlugInType(lastReaderPluginType); + setReaderPluginType(lastReaderPluginType); #else if (!mContext) { return; } - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::PCSC, ReaderManagerPlugInType::REMOTE_IFD, ReaderManagerPlugInType::SIMULATOR}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::PCSC, ReaderManagerPluginType::REMOTE_IFD, ReaderManagerPluginType::SIMULATOR}); #endif } @@ -476,16 +489,16 @@ void WorkflowModel::onApplicationStateChanged(bool pIsAppInForeground) { if (mRemoteScanWasRunning) { - Env::getSingleton()->startScan(ReaderManagerPlugInType::REMOTE_IFD); + Env::getSingleton()->startScan(ReaderManagerPluginType::REMOTE_IFD); mRemoteScanWasRunning = false; } } else { - mRemoteScanWasRunning = Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::REMOTE_IFD).isScanRunning(); + mRemoteScanWasRunning = Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::REMOTE_IFD).isScanRunning(); if (mRemoteScanWasRunning) { - Env::getSingleton()->stopScan(ReaderManagerPlugInType::REMOTE_IFD); + Env::getSingleton()->stopScan(ReaderManagerPluginType::REMOTE_IFD); } } #else @@ -494,35 +507,21 @@ void WorkflowModel::onApplicationStateChanged(bool pIsAppInForeground) } -void WorkflowModel::onReaderManagerSignal() +void WorkflowModel::onPaceResultUpdated() { - QString newReaderImage; - const auto& readerInfos = Env::getSingleton()->getReaderInfos(ReaderFilter::UniqueReaderTypes); - const auto& readersWithEid = filter([](const ReaderInfo& i){return i.hasEid();}, readerInfos); - if (readersWithEid.size() == 1) + if (mContext->getLastPaceResult() == CardReturnCode::OK_PUK) { - newReaderImage = readersWithEid.at(0).getReaderConfigurationInfo().getIconWithNPA()->lookupUrl().toString(); - } - else if (readerInfos.size() == 1) - { - newReaderImage = readerInfos.at(0).getReaderConfigurationInfo().getIcon()->lookupUrl().toString(); + Q_EMIT fireOnPinUnlocked(); + return; } - else if (readerInfos.size() > 1) + if (mContext->getLastPaceResult() == CardReturnCode::OK_CAN) { - newReaderImage = ReaderConfiguration::getMultipleReaderIconPath().replace(QLatin1Char(':'), QLatin1String("qrc://")); - } - else - { - newReaderImage = ReaderConfiguration::getNoReaderFoundIconPath().replace(QLatin1Char(':'), QLatin1String("qrc://")); + Q_EMIT fireOnCanSuccess(); + return; } - if (newReaderImage != mReaderImage) - { - mReaderImage = newReaderImage; - Q_EMIT fireReaderImageChanged(); - } + Q_EMIT fireOnPasswordUsed(); - Q_EMIT fireHasCardChanged(); } diff --git a/src/ui/qml/WorkflowModel.h b/src/ui/qml/WorkflowModel.h index 42372c5f4..68048e58e 100644 --- a/src/ui/qml/WorkflowModel.h +++ b/src/ui/qml/WorkflowModel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,8 +8,9 @@ #pragma once -#include "ReaderManagerPlugInInfo.h" -#include "UIPlugIn.h" +#include "CardReturnCode.h" +#include "ReaderManagerPluginInfo.h" +#include "UiPlugin.h" #include "context/WorkflowContext.h" #include @@ -25,47 +26,50 @@ class WorkflowModel : public QObject { Q_OBJECT + friend class Env; + Q_PROPERTY(QString currentState READ getCurrentState NOTIFY fireCurrentStateChanged) Q_PROPERTY(QString resultString READ getResultString NOTIFY fireResultChanged) Q_PROPERTY(bool error READ isError NOTIFY fireResultChanged) Q_PROPERTY(bool errorIsMasked READ isMaskedError NOTIFY fireResultChanged) - Q_PROPERTY(ReaderManagerPlugInType readerPlugInType READ getReaderPlugInType WRITE setReaderPlugInType NOTIFY fireReaderPlugInTypeChanged) - Q_PROPERTY(bool isSmartSupported READ isSmartSupported NOTIFY fireSupportedPlugInTypesChanged) - Q_PROPERTY(QVector supportedPlugInTypes READ getSupportedReaderPlugInTypes NOTIFY fireSupportedPlugInTypesChanged) + Q_PROPERTY(governikus::EnumReaderManagerPluginType::ReaderManagerPluginType readerPluginType READ getReaderPluginType WRITE setReaderPluginType NOTIFY fireReaderPluginTypeChanged) + Q_PROPERTY(QList supportedPluginTypes READ getSupportedReaderPluginTypes NOTIFY fireSupportedPluginTypesChanged) Q_PROPERTY(bool isBasicReader READ isBasicReader NOTIFY fireSelectedReaderChanged) Q_PROPERTY(bool isRemoteReader READ isRemoteReader NOTIFY fireSelectedReaderChanged) Q_PROPERTY(bool isCurrentSmartCardAllowed READ isCurrentSmartCardAllowed NOTIFY fireIsCurrentSmartCardAllowedChanged) Q_PROPERTY(QString eidTypeMismatchError READ eidTypeMismatchError NOTIFY fireEidTypeMismatchErrorChanged) - Q_PROPERTY(QString readerImage READ getReaderImage NOTIFY fireReaderImageChanged) Q_PROPERTY(bool hasNextWorkflowPending READ getNextWorkflowPending NOTIFY fireNextWorkflowPendingChanged) Q_PROPERTY(QString statusHintText READ getStatusHintText NOTIFY fireResultChanged) + Q_PROPERTY(QString statusHintTitle READ getStatusHintTitle NOTIFY fireResultChanged) Q_PROPERTY(QString statusHintActionText READ getStatusHintActionText NOTIFY fireResultChanged) Q_PROPERTY(QString statusCodeImage READ getStatusCodeImage NOTIFY fireResultChanged) Q_PROPERTY(bool showRemoveCardFeedback READ showRemoveCardFeedback WRITE setRemoveCardFeedback NOTIFY fireRemoveCardFeedbackChanged) Q_PROPERTY(bool hasCard READ hasCard NOTIFY fireHasCardChanged) + Q_PROPERTY(governikus::EnumCardReturnCode::CardReturnCode lastReturnCode READ getLastReturnCode NOTIFY fireLastReturnCodeChanged) friend class ::test_WorkflowModel; private: QSharedPointer mContext; - QString mReaderImage; #if defined(Q_OS_IOS) bool mRemoteScanWasRunning; #endif - void insertCard(ReaderManagerPlugInType pType) const; + void insertCard(ReaderManagerPluginType pType) const; - public: - explicit WorkflowModel(QObject* pParent = nullptr); + protected: + WorkflowModel(); ~WorkflowModel() override = default; + public: void resetWorkflowContext(const QSharedPointer& pContext = QSharedPointer()); [[nodiscard]] QString getCurrentState() const; [[nodiscard]] virtual QString getResultString() const; [[nodiscard]] bool isError() const; [[nodiscard]] bool isMaskedError() const; + [[nodiscard]] CardReturnCode getLastReturnCode() const; - [[nodiscard]] ReaderManagerPlugInType getReaderPlugInType() const; - void setReaderPlugInType(ReaderManagerPlugInType pReaderPlugInType); + [[nodiscard]] ReaderManagerPluginType getReaderPluginType() const; + void setReaderPluginType(ReaderManagerPluginType pReaderPluginType); [[nodiscard]] bool isBasicReader() const; [[nodiscard]] bool isRemoteReader() const; @@ -73,25 +77,23 @@ class WorkflowModel [[nodiscard]] bool isCurrentSmartCardAllowed() const; - [[nodiscard]] bool isSmartSupported() const; - [[nodiscard]] virtual QVector getSupportedReaderPlugInTypes() const; + [[nodiscard]] virtual QList getSupportedReaderPluginTypes() const; [[nodiscard]] bool getNextWorkflowPending() const; [[nodiscard]] GlobalStatus::Code getStatusCode() const; - [[nodiscard]] QString getReaderImage() const; [[nodiscard]] QString getStatusCodeImage() const; - [[nodiscard]] QString getStatusHintText() const; + [[nodiscard]] QString getStatusHintTitle() const; [[nodiscard]] QString getStatusHintActionText() const; [[nodiscard]] Q_INVOKABLE bool invokeStatusHintAction(); [[nodiscard]] bool showRemoveCardFeedback() const; void setRemoveCardFeedback(bool pEnabled); - Q_INVOKABLE void insertSmartCard(); - Q_INVOKABLE void insertSimulator(); + Q_INVOKABLE void insertSmartCard() const; + Q_INVOKABLE void insertSimulator() const; Q_INVOKABLE void cancelWorkflow(); Q_INVOKABLE void startScanExplicitly(); Q_INVOKABLE void continueWorkflow(); @@ -106,26 +108,28 @@ class WorkflowModel private Q_SLOTS: void onApplicationStateChanged(bool pIsAppInForeground); - - public Q_SLOTS: - void onReaderManagerSignal(); + void onPaceResultUpdated(); Q_SIGNALS: void fireWorkflowStarted(); void fireCurrentStateChanged(const QString& pState); void fireStateEntered(const QString& pState); void fireResultChanged(); - void fireReaderPlugInTypeChanged(bool pExplicitStart = false); + void fireReaderPluginTypeChanged(bool pExplicitStart = false); void fireSelectedReaderChanged(); void fireIsCurrentSmartCardAllowedChanged(); void fireReaderImageChanged(); void fireNextWorkflowPendingChanged(); - void fireSupportedPlugInTypesChanged(); + void fireSupportedPluginTypesChanged(); void fireRemoveCardFeedbackChanged(); void fireHasCardChanged(); void fireEidTypeMismatchErrorChanged(); void fireShowUiRequest(UiModule pModule); void fireWorkflowFinished(); + void fireOnPinUnlocked(); + void fireOnPasswordUsed(); + void fireOnCanSuccess(); + void fireLastReturnCodeChanged(); }; diff --git a/src/ui/qml/metadata.json b/src/ui/qml/metadata.json index 1fe873d77..a2173a5c2 100644 --- a/src/ui/qml/metadata.json +++ b/src/ui/qml/metadata.json @@ -1,4 +1,8 @@ { "default": true, - "userInteractive": true + "userInteractive": true, + "env": { + "QSG_INFO": "1", + "QT_SVG_ASSUME_TRUSTED_SOURCE": "1" + } } diff --git a/src/ui/qml/modules/Animations/+6.5/HourglassAnimation.qml b/src/ui/qml/modules/Animations/+6.5/HourglassAnimation.qml new file mode 100644 index 000000000..5bb24f35f --- /dev/null +++ b/src/ui/qml/modules/Animations/+6.5/HourglassAnimation.qml @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import Governikus.Global +import Governikus.Style + +TintableIcon { + source: "qrc:///animations/hourglass.svg" + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image +} diff --git a/src/ui/qml/modules/Animations/AnimationLoader.qml b/src/ui/qml/modules/Animations/AnimationLoader.qml new file mode 100644 index 000000000..369c83083 --- /dev/null +++ b/src/ui/qml/modules/Animations/AnimationLoader.qml @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import Governikus.Global +import Governikus.Style + +Loader { + id: root + + enum Type { + NONE, + ENTER_REMOTE_PIN, + ENTER_TRANSPORT_PIN, + ENTER_PIN, + ENTER_NEW_PIN, + ENTER_CAN, + ENTER_PUK, + ENTER_NO_PIN, + WAIT_FOR_CARD_SAC, + WAIT_FOR_CARD_USB, + WAIT_FOR_READER + } + + property bool animated: true + property int symbol: EnterPasswordAnimation.Symbol.STAR + required property int type + + sourceComponent: { + source: switch (type) { + case AnimationLoader.Type.ENTER_REMOTE_PIN: + return enterRemotePin; + case AnimationLoader.Type.ENTER_TRANSPORT_PIN: + return enterTransportPin; + case AnimationLoader.Type.ENTER_PIN: + return enterPin; + case AnimationLoader.Type.ENTER_NEW_PIN: + return enterNewPin; + case AnimationLoader.Type.ENTER_CAN: + return enterCan; + case AnimationLoader.Type.ENTER_PUK: + return enterPuk; + case AnimationLoader.Type.ENTER_NO_PIN: + return enterNoPin; + case AnimationLoader.Type.WAIT_FOR_CARD_SAC: + return waitForCardSac; + case AnimationLoader.Type.WAIT_FOR_CARD_USB: + return waitForCardUsb; + case AnimationLoader.Type.WAIT_FOR_READER: + return waitForReader; + default: + return undefined; + } + } + visible: (status === Loader.Ready || status === Loader.Loading) && type !== AnimationLoader.Type.NONE + + Component { + id: enterRemotePin + + EnterRemotePinAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterTransportPin + + EnterTransportPinAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterPin + + EnterPinAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterNewPin + + EnterNewPinAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterCan + + EnterCanAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterPuk + + EnterPukAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: enterNoPin + + EnterNoPinAnimation { + animated: root.animated + symbol: root.symbol + } + } + Component { + id: waitForCardSac + + WaitForCardSacAnimation { + animated: root.animated + } + } + Component { + id: waitForCardUsb + + WaitForCardUsbAnimation { + animated: root.animated + } + } + Component { + id: waitForReader + + WaitForReaderAnimation { + animated: root.animated + } + } +} diff --git a/src/ui/qml/modules/Animations/EnterCanAnimation.qml b/src/ui/qml/modules/Animations/EnterCanAnimation.qml new file mode 100644 index 000000000..aa35ec22e --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterCanAnimation.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +EnterPasswordAnimation { + source: "qrc:///animations/enter_can.svg" + symbolCount: 6 + symbolDistance: 0.114 + symbolSize: 0.15 + symbolX: 0.08 + symbolY: 0.7 +} diff --git a/src/ui/qml/modules/Animations/EnterNewPinAnimation.qml b/src/ui/qml/modules/Animations/EnterNewPinAnimation.qml new file mode 100644 index 000000000..d14d5e8af --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterNewPinAnimation.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +EnterPasswordAnimation { + source: "qrc:///animations/enter_new_pin.svg" + symbolCount: 6 + symbolDistance: 0.114 + symbolSize: 0.113 + symbolX: 0.08 + symbolY: 0.64 +} diff --git a/src/ui/qml/modules/Animations/EnterNoPinAnimation.qml b/src/ui/qml/modules/Animations/EnterNoPinAnimation.qml new file mode 100644 index 000000000..5b66c728f --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterNoPinAnimation.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +EnterPasswordAnimation { + source: "qrc:///animations/enter_no_pin.svg" + symbolCount: 6 + symbolDistance: 0.12 + symbolSize: 0.1 + symbolX: 0.115 + symbolY: 0.546 +} diff --git a/src/ui/qml/modules/Animations/EnterPasswordAnimation.qml b/src/ui/qml/modules/Animations/EnterPasswordAnimation.qml new file mode 100644 index 000000000..aeb52d914 --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterPasswordAnimation.qml @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global +import Governikus.Style +import Governikus.Type + +TintableIcon { + id: root + + enum Symbol { + STAR, + CHECK, + WARNING, + ERROR + } + + property bool animated: true + property int symbol: EnterPasswordAnimation.Symbol.STAR + required property int symbolCount + required property real symbolDistance + required property real symbolSize + required property real symbolX + required property real symbolY + + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + + Repeater { + model: symbolCount + + TintableIcon { + property real size: symbolSize + + height: parent.height * size + source: { + switch (symbol) { + case EnterPasswordAnimation.Symbol.CHECK: + return "qrc:///animations/enter_password_check.svg"; + case EnterPasswordAnimation.Symbol.WARNING: + return "qrc:///animations/enter_password_warning.svg"; + case EnterPasswordAnimation.Symbol.ERROR: + return "qrc:///animations/enter_password_error.svg"; + case EnterPasswordAnimation.Symbol.STAR: + return "qrc:///animations/enter_password_star.svg"; + default: + return ""; + } + } + sourceSize.height: parent.height * symbolSize + tintColor: root.tintColor + tintEnabled: symbol === EnterPasswordAnimation.Symbol.STAR + + SequentialAnimation on size { + loops: Animation.Infinite + running: animated && SettingsModel.useAnimations + + PropertyAction { + value: 0 + } + PauseAnimation { + id: startTime + + duration: 200 * (index + 1) + } + NumberAnimation { + duration: 500 + easing.type: Easing.Linear + from: 0 + to: symbolSize + } + PauseAnimation { + duration: 2500 - startTime.duration + } + NumberAnimation { + duration: 500 + easing.type: Easing.Linear + from: symbolSize + to: 0 + } + } + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: parent.width * (symbolX + symbolDistance * index) + verticalCenter: parent.top + verticalCenterOffset: parent.height * symbolY + } + } + } +} diff --git a/src/ui/qml/modules/Animations/EnterPinAnimation.qml b/src/ui/qml/modules/Animations/EnterPinAnimation.qml new file mode 100644 index 000000000..667a332c8 --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterPinAnimation.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +EnterPasswordAnimation { + source: "qrc:///animations/enter_pin.svg" + symbolCount: 6 + symbolDistance: 0.114 + symbolSize: 0.113 + symbolX: 0.085 + symbolY: 0.63 +} diff --git a/src/ui/qml/modules/Animations/EnterPukAnimation.qml b/src/ui/qml/modules/Animations/EnterPukAnimation.qml new file mode 100644 index 000000000..8d2995820 --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterPukAnimation.qml @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import Governikus.Type + +EnterPasswordAnimation { + id: animation + + source: "qrc:///animations/enter_puk.svg" + symbolCount: 10 + symbolDistance: 0.07 + symbolSize: 0.113 + symbolX: 0.06 + symbolY: 0.66 + + Image { + source: "qrc:///images/npa.svg" + sourceSize.height: parent.height * 0.069 + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: parent.width * 0.534 + verticalCenter: parent.top + verticalCenterOffset: parent.height * 0.1005 + } + } + Rectangle { + color: "#FF0000" + height: parent.height * 0.115 + radius: parent.height * 0.016 + width: parent.width * 0.14 + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: parent.width * 0.892 + verticalCenter: parent.top + verticalCenterOffset: parent.height * 0.661 + } + Rectangle { + anchors.centerIn: parent + color: UiPluginModel.highContrastEnabled ? "#FFFFFF" : animation.tintColor + height: parent.height / 2 + width: parent.width + } + } +} diff --git a/src/ui/qml/modules/Animations/EnterRemotePinAnimation.qml b/src/ui/qml/modules/Animations/EnterRemotePinAnimation.qml new file mode 100644 index 000000000..8d51cb976 --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterRemotePinAnimation.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +EnterPasswordAnimation { + source: "qrc:///animations/enter_remote_pin.svg" + symbolCount: 4 + symbolDistance: 0.101 + symbolSize: 0.17 + symbolX: 0.617 + symbolY: 0.65 +} diff --git a/src/ui/qml/modules/Animations/EnterTransportPinAnimation.qml b/src/ui/qml/modules/Animations/EnterTransportPinAnimation.qml new file mode 100644 index 000000000..855b8576a --- /dev/null +++ b/src/ui/qml/modules/Animations/EnterTransportPinAnimation.qml @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import Governikus.Type + +EnterPasswordAnimation { + id: animation + + source: "qrc:///animations/enter_transport_pin.svg" + symbolCount: 5 + symbolDistance: 0.113 + symbolSize: 0.114 + symbolX: 0.435 + symbolY: 0.6 + + Image { + source: "qrc:///images/npa.svg" + sourceSize.height: parent.height * 0.082 + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: parent.width * 0.6144 + verticalCenter: parent.top + verticalCenterOffset: parent.height * 0.1243 + } + } + Rectangle { + color: "#FF0000" + height: parent.height * 0.14 + radius: parent.height * 0.02 + width: parent.width * 0.18 + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: parent.width * 0.139 + verticalCenter: parent.top + verticalCenterOffset: parent.height * 0.604 + } + Rectangle { + anchors.centerIn: parent + color: UiPluginModel.highContrastEnabled ? "#FFFFFF" : animation.tintColor + height: parent.height / 2 + width: parent.width + } + } +} diff --git a/src/ui/qml/modules/Animations/HourglassAnimation.qml b/src/ui/qml/modules/Animations/HourglassAnimation.qml new file mode 100644 index 000000000..1a1f2d29e --- /dev/null +++ b/src/ui/qml/modules/Animations/HourglassAnimation.qml @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Effects +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.Type + +TintableIcon { + id: root + + readonly property bool animated: SettingsModel.useAnimations && GraphicsInfo.api !== GraphicsInfo.Software + + source: animated ? "qrc:///animations/hourglass_background.svg" : "qrc:///animations/hourglass.svg" + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + + NumberAnimation { + id: animation + + property real value: 0.0 + + duration: 6000 + from: 0.0 + loops: Animation.Infinite + property: "value" + running: root.animated + target: animation + to: 1.0 + } + TintableIcon { + rotation: animation.value * 360 + source: "qrc:///animations/hourglass_arrows.svg" + sourceSize.height: parent.height * 0.286 + tintColor: root.tintColor + tintEnabled: root.tintEnabled + + anchors { + centerIn: parent + horizontalCenterOffset: -(parent.width * 0.305) + verticalCenterOffset: -(parent.height * 0.075) + } + } + Item { + id: topSandContainer + + anchors.fill: topMask + visible: false + + TintableIcon { + source: "qrc:///animations/hourglass_sand.svg" + sourceSize.height: parent.height + tintColor: root.tintColor + tintEnabled: root.tintEnabled + y: height * (animation.value * 0.6 + 0.2) + } + } + MultiEffect { + anchors.fill: topSandContainer + maskEnabled: true + maskSource: topMask + source: topSandContainer + visible: root.animated + } + Image { + id: topMask + + source: "qrc:///animations/hourglass_mask_top.svg" + sourceSize.height: parent.height * 0.366 + visible: false + + anchors { + centerIn: parent + horizontalCenterOffset: parent.width * 0.137 + verticalCenterOffset: -(parent.height * 0.2) + } + } + Item { + id: bottomSandContainer + + anchors.fill: bottomMask + visible: false + + TintableIcon { + source: "qrc:///animations/hourglass_sand.svg" + sourceSize.height: parent.height + tintColor: root.tintColor + tintEnabled: root.tintEnabled + y: height - height * (animation.value * 0.6 + 0.2) + } + } + MultiEffect { + anchors.fill: bottomSandContainer + maskEnabled: true + maskSource: bottomMask + source: bottomSandContainer + visible: root.animated + } + Image { + id: bottomMask + + source: "qrc:///animations/hourglass_mask_bottom.svg" + sourceSize.height: parent.height * 0.366 + visible: false + + anchors { + centerIn: parent + horizontalCenterOffset: parent.width * 0.137 + verticalCenterOffset: parent.height * 0.195 + } + } +} diff --git a/src/ui/qml/modules/Animations/WaitForCardSacAnimation.qml b/src/ui/qml/modules/Animations/WaitForCardSacAnimation.qml new file mode 100644 index 000000000..777d2e2d8 --- /dev/null +++ b/src/ui/qml/modules/Animations/WaitForCardSacAnimation.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +WaitForAnimation { + horizontalQuestionmarkOffset: 0.14 + source: "qrc:///animations/wait_for_idcard_sac.svg" + verticalQuestionmarkOffset: 0.66 +} diff --git a/src/ui/qml/modules/Animations/WaitForCardUsbAnimation.qml b/src/ui/qml/modules/Animations/WaitForCardUsbAnimation.qml new file mode 100644 index 000000000..556893277 --- /dev/null +++ b/src/ui/qml/modules/Animations/WaitForCardUsbAnimation.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +WaitForAnimation { + horizontalQuestionmarkOffset: 0.1255 + source: "qrc:///animations/wait_for_idcard_usb.svg" + verticalQuestionmarkOffset: 0.72 +} diff --git a/src/ui/qml/modules/Animations/WaitForReaderAnimation.qml b/src/ui/qml/modules/Animations/WaitForReaderAnimation.qml new file mode 100644 index 000000000..282394b57 --- /dev/null +++ b/src/ui/qml/modules/Animations/WaitForReaderAnimation.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +WaitForAnimation { + horizontalQuestionmarkOffset: 0.85 + source: "qrc:///animations/wait_for_reader.svg" + verticalQuestionmarkOffset: 0.72 +} diff --git a/src/ui/qml/modules/Animations/internal/WaitForAnimation.qml b/src/ui/qml/modules/Animations/internal/WaitForAnimation.qml new file mode 100644 index 000000000..a999564fd --- /dev/null +++ b/src/ui/qml/modules/Animations/internal/WaitForAnimation.qml @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global +import Governikus.Style +import Governikus.Type + +TintableIcon { + id: root + + property bool animated: true + required property real horizontalQuestionmarkOffset + required property real verticalQuestionmarkOffset + + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + + TintableIcon { + id: innerIcon + + property real animatedSize + readonly property real maxSize: 0.202 + readonly property real minSize: 0.141 + readonly property real size: animation.running ? animatedSize : maxSize + + source: "qrc:///animations/wait_for_questionmark.svg" + sourceSize.height: parent.height * size + tintColor: root.tintColor + tintEnabled: root.tintEnabled + + SequentialAnimation on animatedSize { + id: animation + + loops: Animation.Infinite + running: root.animated && SettingsModel.useAnimations + + NumberAnimation { + duration: 1000 + easing.type: Easing.InOutQuad + from: innerIcon.maxSize + to: innerIcon.minSize + } + NumberAnimation { + duration: 1000 + easing.type: Easing.InOutQuad + from: innerIcon.minSize + to: innerIcon.maxSize + } + } + + anchors { + horizontalCenter: parent.left + horizontalCenterOffset: root.width * root.horizontalQuestionmarkOffset + verticalCenter: parent.top + verticalCenterOffset: root.height * root.verticalQuestionmarkOffset + } + } +} diff --git a/resources/qml/Governikus/AuthView/+desktop/AuthView.qml b/src/ui/qml/modules/AuthView/+desktop/AuthView.qml similarity index 73% rename from resources/qml/Governikus/AuthView/+desktop/AuthView.qml rename to src/ui/qml/modules/AuthView/+desktop/AuthView.qml index 05a36fc58..fdf80a424 100644 --- a/resources/qml/Governikus/AuthView/+desktop/AuthView.qml +++ b/src/ui/qml/modules/AuthView/+desktop/AuthView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -13,12 +13,7 @@ import Governikus.SettingsView import Governikus.TitleBar import Governikus.View import Governikus.Workflow -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.UiModule +import Governikus.Type SectionPage { id: authView @@ -36,8 +31,11 @@ SectionPage { PasswordInfo, CardPosition, InputError, + InitialInputError, Data, + PinUnlocked, Result, + RedirectToProvider, ReturnToMain, ReaderSettings, Aborting @@ -98,9 +96,9 @@ SectionPage { QtObject { id: d - readonly property int activeView: inputError.visible ? AuthView.SubViews.InputError : view - readonly property bool cancelAllowed: AuthModel.isBasicReader || generalWorkflow.waitingFor !== Workflow.WaitingFor.Password - property int enteredPasswordType: PasswordType.PIN + readonly property int activeView: inputError.visible ? AuthView.SubViews.InputError : pinUnlocked.visible ? AuthView.SubViews.PinUnlocked : initialInputError.visible ? AuthView.SubViews.InitialInputError : view + readonly property bool cancelAllowed: (AuthModel.isBasicReader || generalWorkflow.waitingFor !== Workflow.WaitingFor.Password) && activeView !== AuthView.SubViews.RedirectToProvider && activeView !== AuthView.SubViews.Result + property int enteredPasswordType: NumberModel.PasswordType.PIN readonly property int passwordType: NumberModel.passwordType property int precedingView: AuthView.SubViews.Undefined property int view: AuthView.SubViews.Undefined @@ -131,8 +129,8 @@ SectionPage { DecisionView { moreInformationText: infoData.linkText moreInformationVisible: true - questionSubText: qsTr("Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function.") - questionText: qsTr("Do you know your six-digit ID card PIN?") + questionSubText: qsTr("Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function.") + questionText: qsTr("Do you know your 6-digit ID card PIN?") visible: d.activeView === AuthView.SubViews.TransportPinReminder onAgree: { @@ -145,12 +143,15 @@ SectionPage { ProgressView { id: checkConnectivityView + icon: "qrc:///images/no_internet.svg" + //: INFO DESKTOP Content of the message that no network connection is present during the authentication procedure. subText: qsTr("Please establish an internet connection.") - subTextColor: Constants.red + subTextColor: Style.color.textNormal.basic //: INFO DESKTOP Header of the message that no network connection is present during the authentication procedure. text: qsTr("No network connectivity") + tintColor: Style.color.image visible: d.activeView === AuthView.SubViews.Connectivity } EditRights { @@ -194,8 +195,9 @@ SectionPage { id: enterPasswordView //: LABEL DESKTOP A11y button to confirm the PIN and start the provider authentication - accessibleContinueText: passwordType === PasswordType.PIN || passwordType === PasswordType.SMART_PIN || (passwordType === PasswordType.CAN && NumberModel.isCanAllowedMode) ? qsTr("Authenticate with provider") : "" + accessibleContinueText: passwordType === NumberModel.PasswordType.PIN || passwordType === NumberModel.PasswordType.SMART_PIN || (passwordType === NumberModel.PasswordType.CAN && NumberModel.isCanAllowedMode) ? qsTr("Authenticate with provider") : "" moreInformationText: infoData.linkText + passwordType: d.passwordType visible: d.activeView === AuthView.SubViews.Password onPasswordEntered: pPasswordType => { @@ -208,7 +210,7 @@ SectionPage { PasswordInfoData { id: infoData - contentType: d.activeView === AuthView.SubViews.TransportPinReminder || d.activeView === AuthView.SubViews.TransportPinReminderInfo ? PasswordInfoContent.Type.CHANGE_PIN : fromPasswordType(d.passwordType, NumberModel.isCanAllowedMode) + contentType: d.activeView === AuthView.SubViews.TransportPinReminder || d.activeView === AuthView.SubViews.TransportPinReminderInfo ? PasswordInfoData.Type.CHANGE_PIN : fromPasswordType(d.passwordType, NumberModel.isCanAllowedMode) } PasswordInfoView { id: passwordInfoView @@ -217,6 +219,8 @@ SectionPage { visible: d.activeView === AuthView.SubViews.PasswordInfo || d.activeView === AuthView.SubViews.TransportPinReminderInfo titleBarAction.customSubAction: NavigationAction { + type: NavigationAction.Action.Back + onClicked: passwordInfoView.close() } @@ -226,26 +230,23 @@ SectionPage { updateTitleBarActions(); } } - ResultView { + InputErrorView { id: inputError property bool errorConfirmed: false - icon: switch (d.enteredPasswordType) { - case PasswordType.SMART_PIN: - case PasswordType.PIN: - return "qrc:///images/workflow_error_wrong_pin_%1.svg".arg(Style.currentTheme.name); - case PasswordType.CAN: - return "qrc:///images/workflow_error_wrong_can_%1.svg".arg(Style.currentTheme.name); - case PasswordType.PUK: - return "qrc:///images/workflow_error_wrong_puk_%1.svg".arg(Style.currentTheme.name); - default: - return ""; - } - text: NumberModel.inputError - visible: !errorConfirmed && NumberModel.hasPasswordError && d.view !== AuthView.SubViews.Result + inputError: NumberModel.inputError + passwordType: NumberModel.passwordType + returnCode: AuthModel.lastReturnCode + visible: !errorConfirmed && NumberModel.inputError !== "" && d.view !== AuthView.SubViews.Result && d.view !== AuthView.SubViews.PasswordInfo - onNextView: errorConfirmed = true + onContinueClicked: { + errorConfirmed = true; + if (AuthModel.isBasicReader) { + d.view = AuthView.SubViews.Password; + } + } + onPasswordInfoRequested: showPasswordInfo() Connections { function onFireInputErrorChanged() { @@ -255,6 +256,49 @@ SectionPage { target: NumberModel } } + InputErrorView { + id: initialInputError + + inputError: NumberModel.initialInputError + passwordType: NumberModel.passwordType + returnCode: NumberModel.passwordType === NumberModel.PasswordType.CAN ? CardReturnCode.INVALID_CAN : CardReturnCode.INVALID_PUK + titleVisible: false + visible: NumberModel.initialInputError !== "" && d.view !== AuthView.SubViews.Result && d.view !== AuthView.SubViews.PasswordInfo + + onContinueClicked: { + NumberModel.setInitialInputErrorShown(); + if (AuthModel.isBasicReader) { + d.view = AuthView.SubViews.Password; + } + } + onPasswordInfoRequested: showPasswordInfo() + } + InputSuccessView { + id: pinUnlocked + + property bool confirmed: true + + passwordType: NumberModel.PasswordType.PUK + visible: !confirmed && (d.view === AuthView.SubViews.Password || generalWorkflow.waitingFor === Workflow.WaitingFor.Password) + + onContinueClicked: confirmed = true + + Connections { + function onFireOnCanSuccess() { + pinUnlocked.passwordType = NumberModel.PasswordType.CAN; + pinUnlocked.confirmed = false; + } + function onFireOnPasswordUsed() { + pinUnlocked.confirmed = true; + } + function onFireOnPinUnlocked() { + pinUnlocked.passwordType = NumberModel.PasswordType.PUK; + pinUnlocked.confirmed = false; + } + + target: AuthModel + } + } ResultView { id: cardPositionView @@ -278,7 +322,7 @@ SectionPage { //: INFO DESKTOP Information message about cancellation process without working network connectivity return qsTr("Network problems detected, trying to reach server within 30 seconds."); } - subTextColor: !authController.networkInterfaceActive ? Style.color.text_warning : Style.color.text + subTextColor: Style.color.textNormal.basic //: INFO DESKTOP The user aborted the authentication process, according to TR we need to inform the service provider text: qsTr("Aborting process and informing the service provider") @@ -308,7 +352,7 @@ SectionPage { //: INFO DESKTOP Generic progress status message during authentication. return qsTr("Please wait a moment."); } - subTextColor: !AuthModel.isBasicReader && NumberModel.inputError ? Style.color.text_warning : Style.color.text + subTextColor: Style.color.textNormal.basic text: (isInitialState ? //: INFO DESKTOP Header of the progress information during the authentication process. qsTr("Acquiring provider certificate") : @@ -328,22 +372,36 @@ SectionPage { ResultView { id: authResult - header: AuthModel.errorHeader + buttonIcon: AuthModel.resultViewButtonIcon + buttonText: AuthModel.resultViewButtonText + header: AuthModel.resultHeader hintButtonText: AuthModel.statusHintActionText hintText: AuthModel.statusHintText + hintTitle: AuthModel.statusHintTitle icon: AuthModel.statusCodeImage !== "" ? AuthModel.statusCodeImage.arg(Style.currentTheme.name) : "" mailButtonVisible: AuthModel.errorIsMasked popupText: AuthModel.errorText //: INFO DESKTOP Error code (string) of current GlobalStatus code, shown as header of popup. popupTitle: qsTr("Error code: %1").arg(AuthModel.statusCodeString) + subheader: AuthModel.errorHeader text: AuthModel.resultString visible: d.activeView === AuthView.SubViews.Result onEmailButtonPressed: AuthModel.sendResultMail() onHintClicked: AuthModel.invokeStatusHintAction() onNextView: pName => { + if (AuthModel.resultViewButtonLink !== "") { + Qt.openUrlExternally(AuthModel.resultViewButtonLink); + } authView.nextView(pName); AuthModel.continueWorkflow(); } } + RedirectView { + id: redirectView + + visible: d.activeView === AuthView.SubViews.RedirectToProvider + + onNextView: AuthModel.continueWorkflow() + } } diff --git a/resources/qml/Governikus/AuthView/+desktop/EditRights.qml b/src/ui/qml/modules/AuthView/+desktop/EditRights.qml similarity index 70% rename from resources/qml/Governikus/AuthView/+desktop/EditRights.qml rename to src/ui/qml/modules/AuthView/+desktop/EditRights.qml index 5753892e3..08c769760 100644 --- a/resources/qml/Governikus/AuthView/+desktop/EditRights.qml +++ b/src/ui/qml/modules/AuthView/+desktop/EditRights.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,27 +8,22 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.CertificateDescriptionModel -import Governikus.Type.ChatModel +import Governikus.Type SectionPage { id: root - property bool detailView: false - function showProviderInformation(show) { - detailView = show; - if (!detailView) - onVisibleChanged(); - updateTitleBarActions(); + d.detailView = show; + if (!d.detailView) { + root.visibleChanged(); + } + root.updateTitleBarActions(); } Keys.onEnterPressed: event => d.onKeyboardConfirmPressed(event) Keys.onEscapePressed: event => { - if (!detailView) { + if (!d.detailView) { event.accepted = false; return; } @@ -36,26 +31,16 @@ SectionPage { } Keys.onReturnPressed: event => d.onKeyboardConfirmPressed(event) - QtObject { - id: d - - function onKeyboardConfirmPressed(event) { - if (detailView) { - showProviderInformation(false); - } else { - confirmButton.onClicked(); - } - } - } - ColumnLayout { + FlickableSectionPage { anchors.fill: parent - anchors.topMargin: Constants.pane_padding * 2 + fillWidth: true spacing: Constants.pane_spacing - visible: !root.detailView + visible: !d.detailView RowLayout { Layout.alignment: Qt.AlignHCenter - Layout.maximumWidth: parent.width * 0.65 + Layout.maximumWidth: Style.dimens.max_text_width * 1.2 + Layout.topMargin: Constants.pane_padding spacing: Constants.pane_spacing Image { @@ -64,21 +49,12 @@ SectionPage { source: "qrc:///images/npa.svg" sourceSize.height: Style.dimens.huge_icon_size } - GPane { - id: providerInfoSectionPane - + ProviderInfo { Layout.fillWidth: true + activeFocusOnTab: true + name: CertificateDescriptionModel.subjectName - ProviderInfoSection { - Layout.fillWidth: true - activeFocusOnTab: true - image: "qrc:///images/info.svg" - name: CertificateDescriptionModel.subjectName - //: LABEL DESKTOP - title: qsTr("You are about to identify yourself towards the following provider:") - - onClicked: showProviderInformation(true) - } + onClicked: showProviderInformation(true) } } GButton { @@ -89,11 +65,11 @@ SectionPage { activeFocusOnTab: true icon.source: "qrc:/images/identify.svg" //: LABEL DESKTOP %1 can be "CAN" or "PIN" - text: qsTr("Proceed to %1 entry").arg(NumberModel.isCanAllowedMode ? + text: qsTr("Proceed to %1 entry").arg((NumberModel.isCanAllowedMode ? //: LABEL DESKTOP Inserted into "Proceed to %1 entry" qsTr("CAN") : //: LABEL DESKTOP Inserted into "Proceed to %1 entry" - qsTr("PIN")) + qsTr("PIN"))) tintIcon: true onClicked: { @@ -105,8 +81,7 @@ SectionPage { id: dataIntroduction Accessible.name: dataIntroduction.text - Layout.leftMargin: Constants.pane_padding - Layout.rightMargin: Constants.pane_padding + Layout.alignment: Qt.AlignLeft activeFocusOnTab: true text: NumberModel.isCanAllowedMode ? //: LABEL DESKTOP @@ -117,14 +92,10 @@ SectionPage { FocusFrame { } } - ScrollablePane { + GPane { Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.maximumHeight: parent.height / parent.children.length - Layout.rightMargin: Constants.pane_padding activeFocusOnTab: true - backgroundColor: Style.color.pane_sublevel - minimumVisibleContentHeight: transactionText.effectiveFirstLineHeight + color: Style.color.paneSublevel.background.basic //: LABEL DESKTOP title: qsTr("Transactional information") @@ -135,7 +106,9 @@ SectionPage { Accessible.name: transactionText.text activeFocusOnTab: true + objectName: "transactionText" text: AuthModel.transactionInfo + textFormat: Text.StyledText visible: !!text FocusFrame { @@ -160,20 +133,19 @@ SectionPage { readonly property int maxColumns: 3 + Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true - Layout.leftMargin: Constants.pane_padding - Layout.maximumHeight: implicitHeight - Layout.rightMargin: Constants.pane_padding spacing: Constants.pane_spacing visible: writeData.count > 0 || requiredData.count > 0 || optionalData.count > 0 - ScrollablePane { + GPane { id: writeDataPane Layout.alignment: Qt.AlignTop - Layout.fillHeight: true Layout.fillWidth: true - backgroundColor: Style.color.pane_sublevel + border.color: Style.color.warning + border.width: Constants.pane_border_highlight_width + color: Style.color.paneSublevel.background.basic visible: writeData.count > 0 DataGroup { @@ -189,13 +161,12 @@ SectionPage { writeAccess: true } } - ScrollablePane { + GPane { id: readDataPane Layout.alignment: Qt.AlignTop - Layout.fillHeight: true Layout.fillWidth: true - backgroundColor: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic visible: requiredData.count > 0 || optionalData.count > 0 RowLayout { @@ -232,14 +203,22 @@ SectionPage { } } } - GSpacer { - Layout.fillHeight: true - Layout.fillWidth: true - } } CertificateDescriptionPage { - id: certificateDescriptionPage + anchors.fill: parent + visible: d.detailView + } + QtObject { + id: d - visible: root.detailView + property bool detailView: false + + function onKeyboardConfirmPressed(event) { + if (d.detailView) { + showProviderInformation(false); + } else { + confirmButton.clicked(); + } + } } } diff --git a/resources/qml/Governikus/AuthView/+desktop/AuthController.qml b/src/ui/qml/modules/AuthView/+desktop/internal/AuthController.qml similarity index 89% rename from resources/qml/Governikus/AuthView/+desktop/AuthController.qml rename to src/ui/qml/modules/AuthView/+desktop/internal/AuthController.qml index 291f2e60b..8480244d2 100644 --- a/resources/qml/Governikus/AuthView/+desktop/AuthController.qml +++ b/src/ui/qml/modules/AuthView/+desktop/internal/AuthController.qml @@ -1,14 +1,9 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.SettingsModel -import Governikus.Type.ChatModel -import Governikus.Type.ConnectivityManager +import Governikus.Type Controller { id: controller @@ -81,9 +76,18 @@ Controller { setAuthWorkflowStateAndContinue(AuthController.WorkflowStates.Processing); break; case "StateActivateStoreFeedbackDialog": - showRemoveCardFeedback(AuthModel, true); + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.SELF_AUTHENTICATION) { + showRemoveCardFeedback(AuthModel, true); + } AuthModel.continueWorkflow(); break; + case "StateRedirectBrowser": + if (!AuthModel.error) { + controller.nextView(AuthView.SubViews.RedirectToProvider); + } else { + AuthModel.continueWorkflow(); + } + break; case "FinalState": if (AuthModel.error) { if (AuthModel.shouldSkipResultView()) { @@ -93,7 +97,7 @@ Controller { showRemoveCardFeedback(AuthModel, false); controller.nextView(AuthView.SubViews.Result); } - } else if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_SELF_AUTHENTICATION) { + } else if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.SELF_AUTHENTICATION) { controller.nextView(AuthView.SubViews.Data); } else { controller.nextView(AuthView.SubViews.ReturnToMain); diff --git a/resources/qml/Governikus/AuthView/+desktop/CertificateDescriptionPage.qml b/src/ui/qml/modules/AuthView/+desktop/internal/CertificateDescriptionPage.qml similarity index 60% rename from resources/qml/Governikus/AuthView/+desktop/CertificateDescriptionPage.qml rename to src/ui/qml/modules/AuthView/+desktop/internal/CertificateDescriptionPage.qml index 47d8fa569..deb1ca4e8 100644 --- a/resources/qml/Governikus/AuthView/+desktop/CertificateDescriptionPage.qml +++ b/src/ui/qml/modules/AuthView/+desktop/internal/CertificateDescriptionPage.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -7,22 +7,20 @@ import QtQuick.Layouts import Governikus.Global import Governikus.TitleBar import Governikus.View -import Governikus.Type.CertificateDescriptionModel +import Governikus.Type + +FlickableSectionPage { + fillWidth: true -SectionPage { titleBarAction: TitleBarAction { rootEnabled: false - showHelp: false //: LABEL DESKTOP text: qsTr("Provider Information") } - ScrollablePane { - id: pane - - activeFocusOnTab: true - anchors.fill: parent - anchors.margins: Constants.pane_padding + ColumnLayout { + Layout.maximumWidth: Number.POSITIVE_INFINITY + spacing: Constants.pane_spacing Repeater { id: listView @@ -31,7 +29,8 @@ SectionPage { LabeledText { Layout.fillWidth: true - alignment: Text.AlignHCenter + Layout.leftMargin: Constants.pane_padding + Layout.maximumWidth: implicitWidth label: model.label text: model.text textFormat: Text.PlainText diff --git a/src/ui/qml/modules/AuthView/+desktop/internal/DataGroup.qml b/src/ui/qml/modules/AuthView/+desktop/internal/DataGroup.qml new file mode 100644 index 000000000..1bcfe49ef --- /dev/null +++ b/src/ui/qml/modules/AuthView/+desktop/internal/DataGroup.qml @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +ColumnLayout { + id: root + + property alias chat: repeater.model + property alias columns: grid.columns + readonly property alias count: repeater.count + property alias title: dataTitle.text + property alias titleStyle: dataTitle.textStyle + property bool writeAccess: false + + spacing: Constants.pane_spacing + visible: count > 0 + + GText { + id: dataTitle + + Accessible.name: dataTitle.text + activeFocusOnTab: true + color: writeAccess ? Style.color.textNormal.basic : titleStyle.textColor + textStyle: Style.text.headline + + FocusFrame { + } + } + Grid { + id: grid + + Layout.fillWidth: true + Layout.preferredWidth: repeater.maxItemWidth * columns + grid.columnSpacing * (columns - 1) + columnSpacing: Constants.pane_spacing + flow: Grid.TopToBottom + verticalItemAlignment: Grid.AlignBottom + + GRepeater { + id: repeater + + visible: count > 0 + + Loader { + id: rightItem + + property bool isLast: index === repeater.count - 1 + property int modelIndex: index + property string modelName: name + property bool modelSelected: selected + property bool modelWriteRight: writeRight + + function updateModel(checked) { + selected = checked; + } + + height: fontMetrics.height * 2 + sourceComponent: optional ? optionalDelegate : requiredDelegate + width: (grid.width - (grid.columnSpacing * (grid.columns - 1))) / grid.columns + + Keys.onSpacePressed: if (optional) + selected = !selected + + FocusFrame { + anchors { + bottomMargin: Style.dimens.separator_size * 2 + leftMargin: 0 + rightMargin: 0 + topMargin: Style.dimens.separator_size + } + } + GSeparator { + anchors.bottom: parent.bottom + visible: !(isLast || ((index + 1) % Math.ceil(repeater.count / grid.columns)) === 0) + width: parent.width + } + FontMetrics { + id: fontMetrics + + font.pixelSize: Style.dimens.text + } + } + } + } + Component { + id: optionalDelegate + + GCheckBox { + id: checkBox + + //: LABEL DESKTOP + Accessible.name: qsTr("%1, optional right, element %2 of %3").arg(text).arg(modelIndex + 1).arg(repeater.count) + checked: modelSelected + focusFrameVisible: false + horizontalPadding: Constants.text_spacing + layoutDirection: Qt.RightToLeft + text: modelName + verticalPadding: 0 + + onCheckedChanged: updateModel(checked) + } + } + Component { + id: requiredDelegate + + GText { + id: dataText + + //: LABEL DESKTOP + Accessible.name: qsTr("%1, required right, element %2 of %3").arg(text).arg(modelIndex + 1).arg(repeater.count) + activeFocusOnTab: true + leftPadding: Constants.text_spacing + rightPadding: Constants.text_spacing + text: modelName + } + } +} diff --git a/src/ui/qml/modules/AuthView/+desktop/internal/SelfAuthenticationData.qml b/src/ui/qml/modules/AuthView/+desktop/internal/SelfAuthenticationData.qml new file mode 100644 index 000000000..d76230eeb --- /dev/null +++ b/src/ui/qml/modules/AuthView/+desktop/internal/SelfAuthenticationData.qml @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + signal accept + + fillWidth: true + margins: Constants.pane_padding * 2 + spacing: Constants.component_spacing + + titleBarAction: TitleBarAction { + rootEnabled: false + //: LABEL DESKTOP Title of the self authentication result data view + text: qsTr("Read self-authentication data") + } + + Keys.onEnterPressed: okButton.clicked() + Keys.onEscapePressed: okButton.clicked() + Keys.onReturnPressed: okButton.clicked() + + Connections { + function onFireCancelWorkflow() { + if (SelfAuthModel.workflowCancelled) { + accept(); + } + } + + enabled: visible + target: SelfAuthModel + } + Row { + id: statusRow + + Layout.preferredHeight: baseItem.height / 4 + spacing: Constants.component_spacing + + TintableIcon { + anchors.verticalCenter: parent.verticalCenter + source: "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) + sourceSize.height: Style.dimens.huge_icon_size + tintEnabled: false + } + GText { + id: successText + + Accessible.name: successText.text + activeFocusOnTab: true + anchors.verticalCenter: parent.verticalCenter + + //: INFO DESKTOP Status message that the self authentication successfully completed. + text: qsTr("Successfully read data") + textStyle: Style.text.headline + + FocusFrame { + } + } + } + GPane { + id: pane + + Layout.fillWidth: true + activeFocusOnTab: true + + //: LABEL DESKTOP Title of the self authentication result data view + title: qsTr("Read data") + + Grid { + id: grid + + columns: 3 + spacing: Constants.groupbox_spacing + verticalItemAlignment: Grid.AlignTop + + Repeater { + id: dataRepeater + + model: SelfAuthModel + + LabeledText { + label: name + text: value === "" ? "---" : value + width: (pane.width - 2 * Constants.pane_padding - (grid.columns - 1) * grid.spacing) / grid.columns + } + } + } + } + GButton { + id: okButton + + Layout.alignment: Qt.AlignHCenter + + //: LABEL DESKTOP + text: qsTr("Back to start page") + + onClicked: baseItem.accept() + } +} diff --git a/resources/qml/Governikus/AuthView/+mobile/AbortedProgressView.qml b/src/ui/qml/modules/AuthView/+mobile/AbortedProgressView.qml similarity index 86% rename from resources/qml/Governikus/AuthView/+mobile/AbortedProgressView.qml rename to src/ui/qml/modules/AuthView/+mobile/AbortedProgressView.qml index 957ab9a59..bc25c2140 100644 --- a/resources/qml/Governikus/AuthView/+mobile/AbortedProgressView.qml +++ b/src/ui/qml/modules/AuthView/+mobile/AbortedProgressView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.ProgressView @@ -22,7 +22,7 @@ ProgressView { //: INFO DESKTOP Information message about cancellation process without working network connectivity return qsTr("Network problems detected, trying to reach server within 30 seconds."); } - subTextColor: networkInterfaceActive ? Style.color.text : Style.color.text_warning + subTextColor: Style.color.textNormal.basic //: INFO DESKTOP The user aborted the authentication process, according to TR we need to inform the service provider text: qsTr("Aborting process and informing the service provider") diff --git a/resources/qml/Governikus/AuthView/+mobile/AuthView.qml b/src/ui/qml/modules/AuthView/+mobile/AuthView.qml similarity index 79% rename from resources/qml/Governikus/AuthView/+mobile/AuthView.qml rename to src/ui/qml/modules/AuthView/+mobile/AuthView.qml index 889292aa6..33641a245 100644 --- a/resources/qml/Governikus/AuthView/+mobile/AuthView.qml +++ b/src/ui/qml/modules/AuthView/+mobile/AuthView.qml @@ -1,17 +1,18 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.View -import Governikus.Type.AuthModel +import Governikus.Type SectionPage { id: root property bool autoInsertCard: false property bool hideTechnologySwitch: false - property var initialPlugIn: null + property var initialPlugin: null + signal requestBack signal showChangePinView signal workflowFinished @@ -33,10 +34,11 @@ SectionPage { AuthController { autoInsertCard: root.autoInsertCard hideTechnologySwitch: root.hideTechnologySwitch - initialPlugIn: root.initialPlugIn + initialPlugin: root.initialPlugin stackView: root.stackView title: root.title + onRequestBack: root.requestBack() onShowChangePinView: { setLockedAndHidden(false); root.showChangePinView(); diff --git a/resources/qml/Governikus/AuthView/+mobile/CardPositionView.qml b/src/ui/qml/modules/AuthView/+mobile/CardPositionView.qml similarity index 88% rename from resources/qml/Governikus/AuthView/+mobile/CardPositionView.qml rename to src/ui/qml/modules/AuthView/+mobile/CardPositionView.qml index 9a27ce3fa..1e7b4c36b 100644 --- a/resources/qml/Governikus/AuthView/+mobile/CardPositionView.qml +++ b/src/ui/qml/modules/AuthView/+mobile/CardPositionView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.ResultView diff --git a/resources/qml/Governikus/AuthView/+mobile/CheckConnectivityView.qml b/src/ui/qml/modules/AuthView/+mobile/CheckConnectivityView.qml similarity index 73% rename from resources/qml/Governikus/AuthView/+mobile/CheckConnectivityView.qml rename to src/ui/qml/modules/AuthView/+mobile/CheckConnectivityView.qml index 12884d2de..4154f8dd7 100644 --- a/resources/qml/Governikus/AuthView/+mobile/CheckConnectivityView.qml +++ b/src/ui/qml/modules/AuthView/+mobile/CheckConnectivityView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.ProgressView @@ -11,10 +11,10 @@ ProgressView { signal cancel - icon: "qrc:///images/mobile/no_internet_%1.svg".arg(Style.currentTheme.name) + icon: "qrc:///images/no_internet.svg" //: INFO ANDROID IOS No network connection, the user needs to active the network interface or abort the procedure. subText: qsTr("Please establish an internet connection.") - subTextColor: Style.color.text_warning + subTextColor: Style.color.textNormal.basic //: LABEL ANDROID IOS text: qsTr("No network connectivity") diff --git a/resources/qml/Governikus/AuthView/+mobile/EditRights.qml b/src/ui/qml/modules/AuthView/+mobile/EditRights.qml similarity index 60% rename from resources/qml/Governikus/AuthView/+mobile/EditRights.qml rename to src/ui/qml/modules/AuthView/+mobile/EditRights.qml index c8e05f8d3..97f201750 100644 --- a/resources/qml/Governikus/AuthView/+mobile/EditRights.qml +++ b/src/ui/qml/modules/AuthView/+mobile/EditRights.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,10 +7,7 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.CertificateDescriptionModel -import Governikus.Type.ChatModel +import Governikus.Type FlickableSectionPage { id: baseItem @@ -35,78 +32,22 @@ FlickableSectionPage { GText { id: actionText - //: LABEL IOS_PHONE ANDROID_PHONE + //: LABEL IOS ANDROID text: qsTr("You are about to identify yourself towards the following provider:") } - GPane { + ProviderInfo { Layout.fillWidth: true - color: mouseArea.pressed ? Style.color.pane_active : Style.color.pane - - Item { - Accessible.description: providerInfoSection.title + ". " + providerInfoSection.name + ". " + providerInfoAction.text - Accessible.role: Accessible.Button - height: providerEntries.height - width: parent.width + name: CertificateDescriptionModel.subjectName - Accessible.onPressAction: mouseArea.clicked(null) - - Column { - id: providerEntries - - spacing: Constants.groupbox_spacing - - anchors { - left: parent.left - right: forwardAction.left - rightMargin: Constants.text_spacing - top: parent.top - } - ProviderInfoSection { - id: providerInfoSection - - imageSource: "qrc:///images/info.svg" - name: CertificateDescriptionModel.subjectName - //: LABEL IOS_PHONE ANDROID_PHONE - title: qsTr("Provider") - } - GText { - id: providerInfoAction - - Accessible.ignored: true - - //: LABEL IOS_PHONE ANDROID_PHONE - text: qsTr("Touch for more details") - wrapMode: Text.WordWrap - - anchors { - left: parent.left - leftMargin: Style.dimens.small_icon_size + Constants.groupbox_spacing - right: parent.right - } - } - } - TintableIcon { - id: forwardAction - - anchors.right: parent.right - anchors.verticalCenter: providerEntries.verticalCenter - source: "qrc:///images/material_arrow_right.svg" - sourceSize.height: Style.dimens.small_icon_size - tintColor: Style.color.text - } - MouseArea { - id: mouseArea + onClicked: push(certificateDescriptionPage) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) - anchors.fill: parent - - onClicked: push(certificateDescriptionPage) - } - Component { - id: certificateDescriptionPage + Component { + id: certificateDescriptionPage - CertificateDescriptionPage { - title: baseItem.title - } + CertificateDescriptionPage { + title: baseItem.title } } } @@ -114,14 +55,16 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter icon.source: "qrc:///images/identify.svg" //: LABEL IOS_PHONE ANDROID_PHONE %1 can be "CAN" or "PIN" - text: qsTr("Proceed to %1 entry").arg(NumberModel.isCanAllowedMode ? + text: qsTr("Proceed to %1 entry").arg((NumberModel.isCanAllowedMode ? //: LABEL IOS_PHONE Inserted into "Proceed to %1 entry" qsTr("CAN") : //: LABEL IOS_PHONE Inserted into "Proceed to %1 entry" - qsTr("PIN")) + qsTr("PIN"))) tintIcon: true onClicked: rightsAccepted() + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GText { id: dataPasswordText @@ -135,7 +78,7 @@ FlickableSectionPage { } GPane { Layout.fillWidth: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic drawShadow: false //: LABEL IOS_PHONE ANDROID_PHONE title: qsTr("Transactional information") @@ -143,7 +86,9 @@ FlickableSectionPage { GText { activeFocusOnTab: true + objectName: "transactionText" text: workflowModel.transactionInfo + textFormat: Text.StyledText visible: !!text width: parent.width } @@ -158,7 +103,9 @@ FlickableSectionPage { } GPane { Layout.fillWidth: true - color: Style.color.pane_sublevel + border.color: Style.color.warning + border.width: Constants.pane_border_highlight_width + color: Style.color.paneSublevel.background.basic drawShadow: false visible: writeData.count > 0 @@ -173,6 +120,7 @@ FlickableSectionPage { width: parent.width writeAccess: true + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) onScrollPageDown: baseItem.scrollPageDown() onScrollPageUp: baseItem.scrollPageUp() } @@ -181,8 +129,9 @@ FlickableSectionPage { id: readData Layout.fillWidth: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic drawShadow: false + padding: 0 visible: requiredData.count > 0 || optionalData.count > 0 DataGroup { @@ -194,6 +143,7 @@ FlickableSectionPage { title: qsTr("Read access") width: parent.width + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) onScrollPageDown: baseItem.scrollPageDown() onScrollPageUp: baseItem.scrollPageUp() } @@ -206,6 +156,7 @@ FlickableSectionPage { title: qsTr("Read access (optional)") width: parent.width + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) onScrollPageDown: baseItem.scrollPageDown() onScrollPageUp: baseItem.scrollPageUp() } diff --git a/resources/qml/Governikus/AuthView/+mobile/TransportPinReminderView.qml b/src/ui/qml/modules/AuthView/+mobile/TransportPinReminderView.qml similarity index 80% rename from resources/qml/Governikus/AuthView/+mobile/TransportPinReminderView.qml rename to src/ui/qml/modules/AuthView/+mobile/TransportPinReminderView.qml index 3a477138f..6a8e2858a 100644 --- a/resources/qml/Governikus/AuthView/+mobile/TransportPinReminderView.qml +++ b/src/ui/qml/modules/AuthView/+mobile/TransportPinReminderView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,7 +7,7 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.WorkflowModel +import Governikus.Type FlickableSectionPage { id: root @@ -32,25 +32,25 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter source: "qrc:///images/info.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image } PaneTitle { Layout.alignment: Qt.AlignHCenter //: LABEL ANDROID IOS - text: qsTr("Do you know your six-digit ID card PIN?") + text: qsTr("Do you know your 6-digit ID card PIN?") } GText { Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter //: LABEL ANDROID IOS - text: qsTr("Online identification with Transport PIN is not possible. The self-selected, six-digit ID card PIN is mandatory to use the eID function.") + text: qsTr("Online identification with Transport PIN is not possible. The self-selected, 6-digit ID card PIN is mandatory to use the eID function.") } GText { Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter //: LABEL ANDROID IOS - text: qsTr("To set up a Smart-eID you also need to have assigned a six-digit PIN beforehand.") - visible: WorkflowModel.isSmartSupported + text: qsTr("To set up a Smart-eID you also need to have assigned a 6-digit PIN beforehand.") + visible: ApplicationModel.isSmartSupported } MoreInformationLink { id: moreInformationLink @@ -78,6 +78,8 @@ FlickableSectionPage { text: qsTr("No") onClicked: pinUnknown() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } GButton { Layout.alignment: Qt.AlignVCenter @@ -89,6 +91,8 @@ FlickableSectionPage { text: qsTr("Yes") onClicked: pinKnown() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } } diff --git a/resources/qml/Governikus/AuthView/+mobile/AuthController.qml b/src/ui/qml/modules/AuthView/+mobile/internal/AuthController.qml similarity index 71% rename from resources/qml/Governikus/AuthView/+mobile/AuthController.qml rename to src/ui/qml/modules/AuthView/+mobile/internal/AuthController.qml index 3f1941952..201ce16fc 100644 --- a/resources/qml/Governikus/AuthView/+mobile/AuthController.qml +++ b/src/ui/qml/modules/AuthView/+mobile/internal/AuthController.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.EnterPasswordView @@ -12,15 +12,7 @@ import Governikus.ResultView import Governikus.WhiteListClient import Governikus.View import Governikus.Workflow -import Governikus.Type.AuthModel -import Governikus.Type.ChatModel -import Governikus.Type.ConnectivityManager -import Governikus.Type.LogModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.ReaderPlugIn -import Governikus.Type.SettingsModel -import Governikus.Type.SurveyModel +import Governikus.Type Controller { id: rootController @@ -37,15 +29,16 @@ Controller { property bool autoInsertCard: false property bool hideTechnologySwitch: false - property var initialPlugIn: null + property var initialPlugin: null readonly property bool isInitialState: workflowState === AuthController.WorkflowStates.Initial - readonly property bool isSmartWorkflow: AuthModel.readerPlugInType === ReaderPlugIn.SMART + readonly property bool isSmartWorkflow: AuthModel.readerPluginType === ReaderManagerPluginType.SMART readonly property int passwordType: NumberModel.passwordType readonly property bool smartEidUsed: isSmartWorkflow && !isInitialState property string title property bool workflowProgressVisible: false property int workflowState: 0 + signal requestBack signal showChangePinView signal workflowFinished @@ -83,13 +76,43 @@ Controller { setAuthWorkflowStateAndContinue(AuthController.WorkflowStates.Reader); break; case "StateEnterPacePassword": - if (NumberModel.passwordType === PasswordType.PIN) { + if (AuthModel.lastReturnCode === CardReturnCode.OK_CAN) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.CAN + }); + return; + } else if (AuthModel.lastReturnCode === CardReturnCode.OK_PUK) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.PUK + }); + return; + } + if (NumberModel.inputError !== "") { + push(inputErrorView, { + "returnCode": AuthModel.lastReturnCode, + "inputError": NumberModel.inputError, + "passwordType": NumberModel.passwordType + }); + NumberModel.resetInputError(); + return; + } + if (NumberModel.initialInputError !== "") { + push(inputErrorView, { + "returnCode": NumberModel.passwordType === NumberModel.PasswordType.CAN ? CardReturnCode.INVALID_CAN : CardReturnCode.INVALID_PUK, + "inputError": NumberModel.initialInputError, + "passwordType": NumberModel.passwordType, + "titleVisible": false + }); + NumberModel.setInitialInputErrorShown(); + return; + } + if (NumberModel.passwordType === NumberModel.PasswordType.PIN) { setAuthWorkflowStateAndRequestInput(AuthController.WorkflowStates.Pin); - } else if (NumberModel.passwordType === PasswordType.SMART_PIN) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.SMART_PIN) { setAuthWorkflowStateAndRequestInput(AuthController.WorkflowStates.Pin); - } else if (NumberModel.passwordType === PasswordType.CAN) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.CAN) { setAuthWorkflowStateAndRequestInput(AuthController.WorkflowStates.Can); - } else if (NumberModel.passwordType === PasswordType.PUK) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.PUK) { setAuthWorkflowStateAndRequestInput(AuthController.WorkflowStates.Puk); } break; @@ -111,7 +134,9 @@ Controller { AuthModel.continueWorkflow(); break; case "StateActivateStoreFeedbackDialog": - showRemoveCardFeedback(AuthModel, true); + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.SELF_AUTHENTICATION) { + showRemoveCardFeedback(AuthModel, true); + } AuthModel.continueWorkflow(); break; case "StateShowResult": @@ -124,6 +149,13 @@ Controller { AuthModel.continueWorkflow(); } break; + case "StateRedirectBrowser": + if (!AuthModel.error) { + replace(redirectToProvider); + } else { + AuthModel.continueWorkflow(); + } + break; case "FinalState": if (AuthModel.showChangePinView) { AuthModel.continueWorkflow(); @@ -140,6 +172,9 @@ Controller { AuthModel.continueWorkflow(); } } + function rerunCurrentState() { + processStateChange(AuthModel.currentState); + } function setAuthWorkflowStateAndContinue(pState) { rootController.workflowState = pState; AuthModel.continueWorkflow(); @@ -148,9 +183,8 @@ Controller { rootController.workflowState = pState; if (AuthModel.isBasicReader) { replace(enterPinView, { - "passwordType": NumberModel.passwordType, - "inputError": NumberModel.inputError - }); + "passwordType": NumberModel.passwordType + }); } else { AuthModel.continueWorkflow(); } @@ -173,7 +207,7 @@ Controller { onNetworkInterfaceActiveChanged: { if (AuthModel.currentState === "StateGetTcToken") - processStateChange(AuthModel.currentState); + rerunCurrentState(); } } Component { @@ -193,22 +227,19 @@ Controller { //: INFO ANDROID IOS Second line text if a basic card reader is used and background communication with the card/server is running. Is not actually visible since the basic reader password handling is done by EnterPasswordView. return qsTr("Please do not move the ID card."); } - if (!!NumberModel.inputError) { - return NumberModel.inputError; - } if (rootController.workflowState === AuthController.WorkflowStates.Update || rootController.workflowState === AuthController.WorkflowStates.Pin) { //: INFO ANDROID IOS The card reader requests the user's attention. return qsTr("Please observe the display of your card reader."); } if (rootController.workflowState === AuthController.WorkflowStates.Can) { - //: INFO ANDROID IOS The PIN was entered wrongfully two times, the third attempts requires additional CAN verification, hint where the CAN is found. - return qsTr("A wrong PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); + //: INFO ANDROID IOS The PIN was entered wrongfully two times, the 3rd attempts requires additional CAN verification, hint where the CAN is found. + return qsTr("A wrong PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); } //: INFO ANDROID IOS Generic status message during the authentication process. return qsTr("Please wait a moment."); } - subTextColor: !AuthModel.isBasicReader && (NumberModel.inputError || workflowState === AuthController.WorkflowStates.Can) ? Style.color.text_warning : Style.color.text + subTextColor: Style.color.textNormal.basic //: LABEL ANDROID IOS text: (AuthModel.error ? qsTr("Cancel authentication process") : //: INFO ANDROID IOS Header of the progress status message during the authentication process. @@ -243,9 +274,8 @@ Controller { SelfAuthenticationData { smartEidUsed: rootController.smartEidUsed - onDone: { - AuthModel.continueWorkflow(); - } + onDone: AuthModel.continueWorkflow() + onRequestBack: rootController.requestBack() } } Component { @@ -266,7 +296,7 @@ Controller { GeneralWorkflow { autoInsertCard: rootController.autoInsertCard hideSwitch: rootController.hideTechnologySwitch - initialPlugIn: rootController.initialPlugIn + initialPlugin: rootController.initialPlugin smartEidUsed: rootController.smartEidUsed workflowModel: AuthModel workflowTitle: rootController.title @@ -296,7 +326,7 @@ Controller { PasswordInfoData { id: transportPinReminderInfoData - contentType: PasswordInfoContent.Type.CHANGE_PIN + contentType: PasswordInfoData.Type.CHANGE_PIN } Component { id: transportPinReminderInfoView @@ -328,7 +358,7 @@ Controller { EnterPasswordView { //: LABEL ANDROID IOS A11y button to confirm the PIN and start the provider authentication - accessibleContinueText: passwordType === PasswordType.PIN || passwordType === PasswordType.SMART_PIN || (passwordType === PasswordType.CAN && NumberModel.isCanAllowedMode) ? qsTr("Authenticate with provider") : undefined + accessibleContinueText: passwordType === NumberModel.PasswordType.PIN || passwordType === NumberModel.PasswordType.SMART_PIN || (passwordType === NumberModel.PasswordType.CAN && NumberModel.isCanAllowedMode) ? qsTr("Authenticate with provider") : "" moreInformationText: infoData.linkText smartEidUsed: rootController.smartEidUsed title: rootController.title @@ -384,15 +414,20 @@ Controller { id: authResult ResultErrorView { + //: LABEL ANDROID IOS + buttonText: qsTr("Return to provider") errorCode: AuthModel.statusCodeString errorDescription: AuthModel.errorText - header: AuthModel.errorHeader + //: LABEL ANDROID IOS + header: qsTr("Authentication failed") hintButtonText: AuthModel.statusHintActionText hintText: AuthModel.statusHintText + hintTitle: AuthModel.statusHintTitle icon: AuthModel.statusCodeImage.arg(Style.currentTheme.name) //: LABEL ANDROID IOS mailButtonText: AuthModel.errorIsMasked ? qsTr("Send log") : "" smartEidUsed: rootController.smartEidUsed + subheader: AuthModel.errorHeader text: AuthModel.resultString title: rootController.title @@ -404,4 +439,66 @@ Controller { onMailClicked: LogModel.mailLog("support@ausweisapp.de", AuthModel.getEmailHeader(), AuthModel.getEmailBody()) } } + Component { + id: redirectToProvider + + RedirectView { + title: rootController.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + enabled: false + } + + onContinueClicked: { + pop(); + AuthModel.continueWorkflow(); + } + } + } + Component { + id: inputErrorView + + InputErrorView { + smartEidUsed: rootController.smartEidUsed + title: rootController.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + AuthModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + rootController.rerunCurrentState(); + } + onPasswordInfoRequested: push(passwordInfoView) + } + } + Component { + id: inputSuccessView + + InputSuccessView { + smartEidUsed: rootController.smartEidUsed + title: rootController.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + AuthModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + setAuthWorkflowStateAndRequestInput(AuthController.WorkflowStates.Pin); + } + } + } } diff --git a/resources/qml/Governikus/AuthView/+mobile/CertificateDescriptionPage.qml b/src/ui/qml/modules/AuthView/+mobile/internal/CertificateDescriptionPage.qml similarity index 87% rename from resources/qml/Governikus/AuthView/+mobile/CertificateDescriptionPage.qml rename to src/ui/qml/modules/AuthView/+mobile/internal/CertificateDescriptionPage.qml index 53cea1de1..553f57f44 100644 --- a/resources/qml/Governikus/AuthView/+mobile/CertificateDescriptionPage.qml +++ b/src/ui/qml/modules/AuthView/+mobile/internal/CertificateDescriptionPage.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.TitleBar import Governikus.View -import Governikus.Type.CertificateDescriptionModel +import Governikus.Type FlickableSectionPage { id: root diff --git a/src/ui/qml/modules/AuthView/+mobile/internal/DataGroup.qml b/src/ui/qml/modules/AuthView/+mobile/internal/DataGroup.qml new file mode 100644 index 000000000..9d08fad7a --- /dev/null +++ b/src/ui/qml/modules/AuthView/+mobile/internal/DataGroup.qml @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +Column { + id: column + + property var chat + readonly property alias count: repeater.count + property alias title: dataTitle.text + property alias titleStyle: dataTitle.textStyle + property bool writeAccess: false + + signal receivedFocus(var pItem) + signal scrollPageDown + signal scrollPageUp + + visible: repeater.count > 0 + width: parent.width + + PaneTitle { + id: dataTitle + + color: writeAccess ? Style.color.textNormal.basic : titleStyle.textColor + height: implicitHeight * 1.5 + topPadding: Constants.pane_padding + verticalAlignment: Text.AlignTop + width: parent.width + + anchors { + left: parent.left + leftMargin: Constants.pane_padding + right: parent.right + rightMargin: Constants.pane_padding + } + } + ColumnLayout { + id: grid + + spacing: 0 + width: parent.width + + Repeater { + id: repeater + + model: chat + visible: repeater.count > 0 + + Loader { + id: delegateLoader + + property bool isLast: index === repeater.count - 1 + property int modelIndex: index + property string modelName: name + property bool modelSelected: selected + property bool modelWriteRight: writeRight + + function updateModel(checked) { + selected = checked; + } + + Layout.fillWidth: true + sourceComponent: optional ? optionalDelegate : requiredDelegate + + onFocusChanged: item.focus = focus // QTBUG-122734 + + GSeparator { + anchors.left: parent.left + visible: !isLast + + anchors { + leftMargin: Constants.pane_padding + right: parent.right + rightMargin: Constants.pane_padding + top: parent.bottom + } + } + } + } + } + Component { + id: optionalDelegate + + GCheckBox { + id: checkBox + + //: LABEL ANDROID IOS + Accessible.name: qsTr("%1, optional right, element %2 of %3").arg(text).arg(modelIndex + 1).arg(repeater.count) + checked: modelSelected + horizontalPadding: Constants.pane_padding + layoutDirection: Qt.RightToLeft + text: modelName + verticalPadding: Constants.text_spacing + + background: RoundedRectangle { + bottomLeftCorner: isLast + bottomRightCorner: isLast + color: checkBox.preferredBackgroundColor + topLeftCorner: false + topRightCorner: false + } + + onCheckedChanged: updateModel(checked) + onFocusChanged: if (focus) + column.receivedFocus(this) + } + } + Component { + id: requiredDelegate + + GText { + //: LABEL ANDROID IOS + Accessible.name: qsTr("%1, required right, element %2 of %3").arg(text).arg(modelIndex + 1).arg(repeater.count) + activeFocusOnTab: true + bottomPadding: Constants.text_spacing + leftPadding: Constants.pane_padding + rightPadding: Constants.pane_padding + text: modelName + topPadding: Constants.text_spacing + + onFocusChanged: if (focus) + column.receivedFocus(this) + + FocusFrame { + } + } + } +} diff --git a/resources/qml/Governikus/AuthView/+mobile/SelfAuthenticationData.qml b/src/ui/qml/modules/AuthView/+mobile/internal/SelfAuthenticationData.qml similarity index 71% rename from resources/qml/Governikus/AuthView/+mobile/SelfAuthenticationData.qml rename to src/ui/qml/modules/AuthView/+mobile/internal/SelfAuthenticationData.qml index bfac198b8..3b54e356e 100644 --- a/resources/qml/Governikus/AuthView/+mobile/SelfAuthenticationData.qml +++ b/src/ui/qml/modules/AuthView/+mobile/internal/SelfAuthenticationData.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -8,20 +8,25 @@ import Governikus.ResultView import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.SelfAuthModel +import Governikus.Type FlickableSectionPage { id: root signal done + signal requestBack + spacing: Constants.pane_spacing //: LABEL ANDROID IOS title: qsTr("Identify") navigationAction: NavigationAction { - action: NavigationAction.Action.Cancel + action: NavigationAction.Action.Back - onClicked: done() + onClicked: { + root.requestBack(); + root.done(); + } } GridLayout { @@ -50,8 +55,10 @@ FlickableSectionPage { GButton { Layout.alignment: Qt.AlignHCenter //: LABEL ANDROID IOS - text: qsTr("OK") + text: qsTr("Back to start page") - onClicked: done() + onClicked: root.done() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/src/ui/qml/modules/AuthView/ProviderInfo.qml b/src/ui/qml/modules/AuthView/ProviderInfo.qml new file mode 100644 index 000000000..83955b9e2 --- /dev/null +++ b/src/ui/qml/modules/AuthView/ProviderInfo.qml @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +AbstractButton { + id: root + + required property string name + + //: LABEL DESKTOP + Accessible.description: Constants.is_desktop ? qsTr("Show more information about the service provider") : "" + Accessible.name: label.label + ". " + label.text + (Constants.is_desktop ? "" : (". " + link.text)) + Accessible.role: Accessible.Button + padding: Constants.pane_padding + + background: GPaneBackground { + Accessible.ignored: true + border.color: colors.paneBorder + color: colors.paneBackground + + FocusFrame { + marginFactor: 0.8 + radius: parent.radius * 1.2 + scope: root + } + } + contentItem: RowLayout { + spacing: Constants.component_spacing + + TintableIcon { + Layout.alignment: Qt.AlignTop + source: "qrc:///images/info.svg" + sourceSize.height: Style.dimens.small_icon_size + tintColor: label.labelColor + } + ColumnLayout { + spacing: Constants.component_spacing + + LabeledText { + id: label + + Accessible.ignored: true + Layout.fillWidth: true + activeFocusOnTab: false + bodyElide: Text.ElideRight + label: Constants.is_desktop ? + //: LABEL DESKTOP + qsTr("You are about to identify yourself towards the following provider:") : + //: LABEL ANDROID IOS + qsTr("Provider") + maximumBodyLineCount: 1 + + //: LABEL ALL_PLATFORMS + text: name.length > 0 ? name : qsTr("See details under \"more...\"") + } + GText { + id: link + + Accessible.ignored: true + color: label.labelColor + font.pixelSize: UiPluginModel.scaleFactor * 24 + text: Constants.is_desktop ? + //: LABEL DESKTOP + qsTr("Details about the provider") : + //: LABEL ANDROID IOS + qsTr("Touch for more details") + } + } + TintableIcon { + Layout.alignment: Qt.AlignVCenter + source: "qrc:///images/material_arrow_right.svg" + sourceSize.height: Style.dimens.small_icon_size + tintColor: label.textColor + } + } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + hoveredCondition: hoverHandler.hovered + statefulControl: root + } +} diff --git a/src/ui/qml/modules/AuthView/internal/RedirectView.qml b/src/ui/qml/modules/AuthView/internal/RedirectView.qml new file mode 100644 index 000000000..ca48ce56d --- /dev/null +++ b/src/ui/qml/modules/AuthView/internal/RedirectView.qml @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQml + +import Governikus.Global +import Governikus.ResultView +import Governikus.Style +import Governikus.Type + +ResultView { + id: root + + //: LABEL ALL_PLATFORMS + readonly property string leaveText: qsTr("If you have any questions or encounter any errors during the process, please contact the corresponding provider.") + readonly property string redirectText: { + if (SettingsModel.autoRedirectAfterAuthentication) { + //: INFO ALL_PLATFORMS Redirect information when automatic redirect is enabled + return qsTr("You will be automatically redirected to the provider in a few seconds. If you are not automatically redirected, click on the \"%1\" button.").arg(buttonText); + } + //: INFO ALL_PLATFORMS Redirect information when automatic redirect is disabled + return qsTr("Press the button to complete the authentication and return to the provider."); + } + + buttonIcon: "qrc:///images/open_website.svg" + //: LABEL ALL_PLATFORMS + buttonText: qsTr("Return to provider") + //: LABEL ALL_PLATFORMS + header: qsTr("Authentication successful") + icon: "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) + subheader: { + if (Constants.is_desktop) { + //: INFO DESKTOP Hint to user that the ID card should be removed + return qsTr("Remove the ID card from the card reader"); + } + //: INFO ANDROID IOS Hint to user that the ID card should be removed + return qsTr("Remove the ID card from the NFC interface"); + } + text: { + if (AuthModel.showRemoveCardFeedback) { + return "%1

%2".arg(leaveText).arg(redirectText); + } + return leaveText; + } + + Component.onCompleted: { + if (!Constants.is_desktop && SettingsModel.autoRedirectAfterAuthentication) { + timeout.start(); + } + } + onVisibleChanged: { + if (Constants.is_desktop && visible && SettingsModel.autoRedirectAfterAuthentication) { + timeout.start(); + } + } + + Timer { + id: timeout + + interval: 7000 + + onTriggered: root.confirm() + } +} diff --git a/src/ui/qml/modules/CMakeLists.txt b/src/ui/qml/modules/CMakeLists.txt new file mode 100644 index 000000000..13eac9dab --- /dev/null +++ b/src/ui/qml/modules/CMakeLists.txt @@ -0,0 +1,145 @@ +function(GET_BASENAME _file _output) + get_filename_component(filename ${_file} NAME) + string(REGEX REPLACE "(^|/)\\+[\.|0-9]+\/${filename}" "\\1${filename}" _file "${_file}") + set(${_output} ${_file} PARENT_SCOPE) +endfunction() + +function(FILTER_VERSIONED _files _output) + set(regex "\\+([\.|0-9]+)/[A-Z|a-z]+\.(qml|js)$") + + set(versioned_files "${_files}") + list(FILTER versioned_files INCLUDE REGEX ${regex}) + list(SORT versioned_files COMPARE NATURAL) + + list(FILTER _files EXCLUDE REGEX ${regex}) + + foreach(file ${versioned_files}) + string(REGEX MATCH ${regex} _unused "${file}") + if(CMAKE_MATCH_1 AND QT_VERSION VERSION_LESS CMAKE_MATCH_1) + GET_BASENAME("${file}" basefile) + list(FIND _files "${basefile}" index) + if(NOT index EQUAL -1) + list(REMOVE_ITEM _files "${basefile}") + list(APPEND _files "${file}") + endif() + endif() + endforeach() + + set(${_output} ${_files} PARENT_SCOPE) +endfunction() + +function(FILTER_SELECTOR _files _output _system) + list(APPEND filterList desktop) + list(APPEND filterList mobile) + list(APPEND filterList ios) + list(APPEND filterList android) + + if(_system STREQUAL "Android") + list(REMOVE_ITEM filterList mobile) + list(REMOVE_ITEM filterList android) + elseif(_system STREQUAL "iOS") + list(REMOVE_ITEM filterList mobile) + list(REMOVE_ITEM filterList ios) + else() + list(REMOVE_ITEM filterList desktop) + endif() + + foreach(file ${_files}) + set(allowed_file TRUE) + foreach(filter ${filterList}) + if("${file}" MATCHES "/\\+${filter}/") + set(allowed_file FALSE) + break() + endif() + endforeach() + + if(allowed_file) + list(APPEND filtered_files "${file}") + endif() + endforeach() + + set(${_output} ${filtered_files} PARENT_SCOPE) +endfunction() + +function(GENERATE_QML_MODULES _system) + file(GLOB DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*") + foreach(name ${DIRS}) + if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${name}") + continue() + endif() + + file(GLOB_RECURSE files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${name}/*.qml" "${name}/*.js") + + FILTER_VERSIONED("${files}" files) + FILTER_SELECTOR("${files}" files "${_system}") + if("${files}" STREQUAL "") + continue() + endif() + + foreach(file ${files}) + file(STRINGS "${file}" PRAGMA REGEX "^pragma") + string(REPLACE "${name}/" "" file_alias "${file}") + GET_BASENAME("${file_alias}" file_alias) + string(REGEX REPLACE "\\+[A-Za-z0-9_]+/" "" file_alias "${file_alias}") + + if(file_alias MATCHES "(^|/)internal/") + set_source_files_properties("${file}" PROPERTIES QT_QML_INTERNAL_TYPE TRUE) + string(REPLACE "internal/" "" file_alias "${file_alias}") + endif() + if("${PRAGMA}" MATCHES "Singleton") + set_source_files_properties("${file}" PROPERTIES QT_QML_SINGLETON_TYPE TRUE) + endif() + + set_source_files_properties("${file}" PROPERTIES QT_RESOURCE_ALIAS "${file_alias}") + endforeach() + + if(CMAKE_SYSTEM_NAME STREQUAL "${_system}") + if(QT_VERSION VERSION_LESS "6.5") + set(RESOURCE_PREFIX RESOURCE_PREFIX /qt/qml) + endif() + set(type general) + set(path ${_system}/Governikus/${name}) + set(import_path ${_system}) + else() + string(TOLOWER "${_system}" prefix) + set(RESOURCE_PREFIX RESOURCE_PREFIX /) + set(path ${prefix}/Governikus/${name}) + set(TARGET_PATH TARGET_PATH ${path}) # QTBUG-123169 + set(import_path ${prefix}) + set(type debug) + endif() + + set(ModuleLibrary AusweisAppUiQmlModule${_system}${name}) + add_library(${ModuleLibrary} STATIC) + qt_add_qml_module(${ModuleLibrary} + URI "Governikus.${name}" + VERSION "${PROJECT_VERSION}" + QML_FILES ${files} + OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${path} + ${TARGET_PATH} + NO_CACHEGEN + ${RESOURCE_PREFIX} + IMPORT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${import_path} + IMPORT_PATH ${CMAKE_CURRENT_BINARY_DIR}/common + ) + + target_compile_options(${ModuleLibrary} PRIVATE "${INCOMPATIBLE_QT_COMPILER_FLAGS}") + target_compile_options(${ModuleLibrary}plugin PRIVATE "${INCOMPATIBLE_QT_COMPILER_FLAGS}") + target_link_libraries(AusweisAppUiQmlModules ${type} ${ModuleLibrary} ${type} ${ModuleLibrary}plugin) + endforeach() +endfunction() + +set(QML_IMPORT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SYSTEM_NAME}" CACHE STRING "import path of ${CMAKE_SYSTEM_NAME}" FORCE) +add_library(AusweisAppUiQmlModules STATIC) +GENERATE_QML_MODULES("${CMAKE_SYSTEM_NAME}") +if(DESKTOP) + foreach(entry Android iOS) + GENERATE_QML_MODULES("${entry}") + endforeach() +endif() + +if(IOS) + add_library(AusweisAppQmlPlugins INTERFACE) + qt_import_qml_plugins(AusweisAppQmlPlugins) + target_link_libraries(AusweisAppUiQmlModules AusweisAppQmlPlugins) +endif() diff --git a/resources/qml/Governikus/ChangePinView/+desktop/ChangePinView.qml b/src/ui/qml/modules/ChangePinView/+desktop/ChangePinView.qml similarity index 71% rename from resources/qml/Governikus/ChangePinView/+desktop/ChangePinView.qml rename to src/ui/qml/modules/ChangePinView/+desktop/ChangePinView.qml index 3f8a35e1f..f09219259 100644 --- a/resources/qml/Governikus/ChangePinView/+desktop/ChangePinView.qml +++ b/src/ui/qml/modules/ChangePinView/+desktop/ChangePinView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -13,10 +13,7 @@ import Governikus.SettingsView import Governikus.Style import Governikus.View import Governikus.Workflow -import Governikus.Type.ChangePinModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.UiModule +import Governikus.Type SectionPage { id: baseItem @@ -31,6 +28,7 @@ SectionPage { Progress, ProgressNewPin, CardPosition, + InitialInputError, InputError, Data, PinUnlocked, @@ -82,15 +80,20 @@ SectionPage { } } - Keys.onEscapePressed: if (d.cancelAllowed) - ChangePinModel.cancelWorkflow() + Keys.onEscapePressed: event => { + if (d.cancelAllowed) { + ChangePinModel.cancelWorkflow(); + } else { + event.accepted = false; + } + } QtObject { id: d - readonly property int activeView: inputError.visible ? ChangePinView.SubViews.InputError : pinUnlocked.visible ? ChangePinView.SubViews.PinUnlocked : view - readonly property bool cancelAllowed: view !== ChangePinView.SubViews.NoPassword && view !== ChangePinView.SubViews.Start && (ChangePinModel.isBasicReader || generalWorkflow.waitingFor !== Workflow.WaitingFor.Password) - property int enteredPasswordType: PasswordType.PIN + readonly property int activeView: inputError.visible ? ChangePinView.SubViews.InputError : pinUnlocked.visible ? ChangePinView.SubViews.PinUnlocked : initialInputError.visible ? ChangePinView.SubViews.InitialInputError : view + readonly property bool cancelAllowed: view !== ChangePinView.SubViews.NoPassword && view !== ChangePinView.SubViews.Start && view !== ChangePinView.SubViews.Result && (ChangePinModel.isBasicReader || generalWorkflow.waitingFor !== Workflow.WaitingFor.Password) + property int enteredPasswordType: NumberModel.PasswordType.PIN readonly property int passwordType: NumberModel.passwordType property int precedingView: ChangePinView.SubViews.Start property var view: ChangePinView.SubViews.Start @@ -118,12 +121,13 @@ SectionPage { visible: d.activeView === ChangePinView.SubViews.Start ChangePinViewContent { + id: mainView + anchors.fill: parent - moreInformationText: infoData.linkText onChangePin: ChangePinModel.startWorkflow(false) + onChangePinInfoRequested: baseItem.showPasswordInfo() onChangeTransportPin: ChangePinModel.startWorkflow(true) - onMoreInformationRequested: baseItem.showPasswordInfo() onNoPinAvailable: d.view = ChangePinView.SubViews.NoPassword } } @@ -133,7 +137,7 @@ SectionPage { visible: d.activeView === ChangePinView.SubViews.NoPassword infoContent: PasswordInfoData { - contentType: PasswordInfoContent.Type.NO_PIN + contentType: PasswordInfoData.Type.NO_PIN } onClose: d.view = ChangePinView.SubViews.Start @@ -174,16 +178,17 @@ SectionPage { id: enterPasswordView moreInformationText: infoData.linkText + passwordType: d.passwordType visible: d.activeView === ChangePinView.SubViews.Password onPasswordEntered: pPasswordType => { d.enteredPasswordType = pPasswordType; switch (pPasswordType) { - case PasswordType.NEW_PIN: - case PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: break; - case PasswordType.NEW_PIN_CONFIRMATION: - case PasswordType.NEW_SMART_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: if (NumberModel.commitNewPin()) { d.view = ChangePinView.SubViews.ProgressNewPin; ChangePinModel.continueWorkflow(); @@ -199,12 +204,23 @@ SectionPage { PasswordInfoData { id: infoData - contentType: changePinController.workflowState === ChangePinController.WorkflowStates.Initial ? PasswordInfoContent.Type.CHANGE_PIN : fromPasswordType(d.passwordType) + contentType: { + if (NumberModel.inputError === "" || !ChangePinModel.requestTransportPin) { + return fromPasswordType(d.passwordType); + } + switch (ChangePinModel.lastReturnCode) { + case CardReturnCode.INVALID_CAN: + case CardReturnCode.INVALID_PUK: + return fromPasswordType(d.passwordType); + default: + return PasswordInfoData.Type.TRANSPORT_PIN_NOT_WORKING; + } + } } PasswordInfoView { id: passwordInfoView - infoContent: infoData + infoContent: changePinController.workflowState === ChangePinController.WorkflowStates.Initial ? mainView.pinInfo : infoData visible: d.activeView === ChangePinView.SubViews.PasswordInfo onAbortCurrentWorkflow: ChangePinModel.cancelWorkflow() @@ -225,30 +241,24 @@ SectionPage { qsTr("Change PIN") visible: d.activeView === ChangePinView.SubViews.Progress || d.activeView === ChangePinView.SubViews.ProgressNewPin } - ResultView { + InputErrorView { id: inputError property bool errorConfirmed: false - //: INFO DESKTOP - readonly property string transportPinHint: qsTr("Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid.") - - icon: switch (d.enteredPasswordType) { - case PasswordType.TRANSPORT_PIN: - return "qrc:///images/workflow_error_wrong_transportpin_%1.svg".arg(Style.currentTheme.name); - case PasswordType.SMART_PIN: - case PasswordType.PIN: - return "qrc:///images/workflow_error_wrong_pin_%1.svg".arg(Style.currentTheme.name); - case PasswordType.CAN: - return "qrc:///images/workflow_error_wrong_can_%1.svg".arg(Style.currentTheme.name); - case PasswordType.PUK: - return "qrc:///images/workflow_error_wrong_puk_%1.svg".arg(Style.currentTheme.name); - default: - return "qrc:///images/status_error_%1.svg".arg(Style.currentTheme.name); - } - text: NumberModel.inputError + (NumberModel.inputError !== "" && ChangePinModel.requestTransportPin ? "

%1".arg(transportPinHint) : "") - visible: !errorConfirmed && NumberModel.hasPasswordError && d.view !== ChangePinView.SubViews.Result - onNextView: errorConfirmed = true + inputError: NumberModel.inputError + isTransportPin: ChangePinModel.requestTransportPin + passwordType: NumberModel.passwordType + returnCode: ChangePinModel.lastReturnCode + visible: !errorConfirmed && NumberModel.inputError !== "" && d.view !== ChangePinView.SubViews.Result && d.view !== ChangePinView.SubViews.PasswordInfo + + onContinueClicked: { + errorConfirmed = true; + if (ChangePinModel.isBasicReader) { + d.view = ChangePinView.SubViews.Password; + } + } + onPasswordInfoRequested: showPasswordInfo() Connections { function onFireInputErrorChanged() { @@ -258,20 +268,44 @@ SectionPage { target: NumberModel } } - ResultView { + InputErrorView { + id: initialInputError + + inputError: NumberModel.initialInputError + passwordType: NumberModel.passwordType + returnCode: NumberModel.passwordType === NumberModel.PasswordType.CAN ? CardReturnCode.INVALID_CAN : CardReturnCode.INVALID_PUK + titleVisible: false + visible: NumberModel.initialInputError !== "" && d.view !== ChangePinView.SubViews.Result && d.view !== ChangePinView.SubViews.PasswordInfo + + onContinueClicked: { + NumberModel.setInitialInputErrorShown(); + if (ChangePinModel.isBasicReader) { + d.view = ChangePinView.SubViews.Password; + } + } + onPasswordInfoRequested: showPasswordInfo() + } + InputSuccessView { id: pinUnlocked property bool confirmed: true - animatedIcon: "qrc:///images/puk_%1.webp".arg(Style.currentTheme.name) - //: INFO DESKTOP The ID card has just been unblocked and the user can now continue with their ID card PIN change. - text: qsTr("Your ID card PIN is unblocked. You now have three more attempts to change your PIN.") + isTransportPin: ChangePinModel.requestTransportPin + passwordType: NumberModel.PasswordType.PUK visible: !confirmed && (d.view === ChangePinView.SubViews.Password || generalWorkflow.waitingFor === Workflow.WaitingFor.Password) - onNextView: confirmed = true + onContinueClicked: confirmed = true Connections { + function onFireOnCanSuccess() { + pinUnlocked.passwordType = NumberModel.PasswordType.CAN; + pinUnlocked.confirmed = false; + } + function onFireOnPasswordUsed() { + pinUnlocked.confirmed = true; + } function onFireOnPinUnlocked() { + pinUnlocked.passwordType = NumberModel.PasswordType.PUK; pinUnlocked.confirmed = false; } @@ -294,8 +328,11 @@ SectionPage { ResultView { id: pinResult + //: LABEL DESKTOP + buttonText: qsTr("Back to start page") hintButtonText: ChangePinModel.statusHintActionText hintText: ChangePinModel.statusHintText + hintTitle: ChangePinModel.statusHintTitle icon: ChangePinModel.error ? ChangePinModel.statusCodeImage.arg(Style.currentTheme.name) : "qrc:///images/workflow_success_changepin_%1.svg".arg(Style.currentTheme.name) mailButtonVisible: ChangePinModel.errorIsMasked text: ChangePinModel.resultString diff --git a/resources/qml/Governikus/ChangePinView/+desktop/ChangePinController.qml b/src/ui/qml/modules/ChangePinView/+desktop/internal/ChangePinController.qml similarity index 93% rename from resources/qml/Governikus/ChangePinView/+desktop/ChangePinController.qml rename to src/ui/qml/modules/ChangePinView/+desktop/internal/ChangePinController.qml index 296bd0989..10e3fb624 100644 --- a/resources/qml/Governikus/ChangePinView/+desktop/ChangePinController.qml +++ b/src/ui/qml/modules/ChangePinView/+desktop/internal/ChangePinController.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.View -import Governikus.Type.ChangePinModel -import Governikus.Type.NumberModel +import Governikus.Type Controller { id: controller diff --git a/resources/qml/Governikus/ChangePinView/+mobile/ChangePinView.qml b/src/ui/qml/modules/ChangePinView/+mobile/ChangePinView.qml similarity index 73% rename from resources/qml/Governikus/ChangePinView/+mobile/ChangePinView.qml rename to src/ui/qml/modules/ChangePinView/+mobile/ChangePinView.qml index 0b9803017..5ab0b793a 100644 --- a/resources/qml/Governikus/ChangePinView/+mobile/ChangePinView.qml +++ b/src/ui/qml/modules/ChangePinView/+mobile/ChangePinView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.EnterPasswordView @@ -12,12 +12,7 @@ import Governikus.ProgressView import Governikus.ResultView import Governikus.View import Governikus.Workflow -import Governikus.Type.ApplicationModel -import Governikus.Type.ChangePinModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.UiModule -import Governikus.Type.ReaderPlugIn +import Governikus.Type SectionPage { id: baseItem @@ -25,19 +20,16 @@ SectionPage { property bool autoInsertCard: false property bool hidePinTypeSelection: false property bool hideTechnologySwitch: false - property var initialPlugIn: null - readonly property bool isSmartWorkflow: ChangePinModel.readerPlugInType === ReaderPlugIn.SMART + property var initialPlugin: null + readonly property bool isSmartWorkflow: ChangePinModel.readerPluginType === ReaderManagerPluginType.SMART signal close signal workflowFinished contentIsScrolled: !changePinViewContent.atYBeginning smartEidUsed: isSmartWorkflow - title: NumberModel.passwordType === PasswordType.TRANSPORT_PIN ? //: LABEL ANDROID IOS - qsTr("Change Transport PIN") : - //: LABEL ANDROID IOS - qsTr("Change PIN") + title: qsTr("Change PIN") navigationAction: NavigationAction { action: NavigationAction.Action.Back @@ -45,6 +37,9 @@ SectionPage { onClicked: baseItem.close() } + FadeInAnimation { + target: baseItem + } Connections { function onActivate() { changePinViewContent.highlightScrollbar(); @@ -66,7 +61,7 @@ SectionPage { ChangePinController { autoInsertCard: baseItem.autoInsertCard hideTechnologySwitch: baseItem.hideTechnologySwitch - initialPlugIn: baseItem.initialPlugIn + initialPlugin: baseItem.initialPlugin smartEidUsed: baseItem.smartEidUsed stackView: baseItem.stackView title: baseItem.title @@ -81,28 +76,21 @@ SectionPage { id: changePinViewContent anchors.fill: parent - moreInformationText: changePinInfo.linkText visible: !baseItem.hidePinTypeSelection onChangePin: ChangePinModel.startWorkflow(false) + onChangePinInfoRequested: push(changePinInfoView) onChangeTransportPin: ChangePinModel.startWorkflow(true) - onMoreInformationRequested: push(changePinInfoView) onNoPinAvailable: { setLockedAndHidden(); push(pinUnknownView); } - - PasswordInfoData { - id: changePinInfo - - contentType: PasswordInfoContent.Type.CHANGE_PIN - } } Component { id: changePinInfoView PasswordInfoView { - infoContent: changePinInfo + infoContent: changePinViewContent.pinInfo navigationAction: NavigationAction { action: NavigationAction.Action.Back @@ -118,7 +106,7 @@ SectionPage { PasswordInfoView { infoContent: PasswordInfoData { - contentType: PasswordInfoContent.Type.NO_PIN + contentType: PasswordInfoData.Type.NO_PIN } navigationAction: NavigationAction { action: NavigationAction.Action.Back diff --git a/resources/qml/Governikus/ChangePinView/+mobile/ChangePinController.qml b/src/ui/qml/modules/ChangePinView/+mobile/internal/ChangePinController.qml similarity index 64% rename from resources/qml/Governikus/ChangePinView/+mobile/ChangePinController.qml rename to src/ui/qml/modules/ChangePinView/+mobile/internal/ChangePinController.qml index 1376daea8..750362b9f 100644 --- a/resources/qml/Governikus/ChangePinView/+mobile/ChangePinController.qml +++ b/src/ui/qml/modules/ChangePinView/+mobile/internal/ChangePinController.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.AuthView @@ -12,11 +12,7 @@ import Governikus.TitleBar import Governikus.PasswordInfoView import Governikus.View import Governikus.Workflow -import Governikus.Type.ApplicationModel -import Governikus.Type.ChangePinModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.UiModule +import Governikus.Type Controller { id: rootController @@ -35,16 +31,21 @@ Controller { property bool autoInsertCard: false property bool hideTechnologySwitch: false - property var initialPlugIn: null + property var initialPlugin: null property bool isNewPin: false property bool smartEidUsed: false property string title - //: INFO ANDROID IOS - readonly property string transportPinHint: qsTr("Please note that you may use the five-digit Transport PIN only once to change to a six-digit ID card PIN. If you already set a six-digit ID card PIN, the five-digit Transport PIN is no longer valid.") property int workflowState: 0 signal workflowFinished + function displayInputError() { + push(inputErrorView, { + "returnCode": ChangePinModel.lastReturnCode, + "inputError": NumberModel.inputError, + "passwordType": NumberModel.passwordType + }); + } function processStateChange(pState) { switch (pState) { case "StateSelectReader": @@ -58,16 +59,41 @@ Controller { setPinWorkflowStateAndContinue(ChangePinController.WorkflowStates.Update); break; case "StateEnterPacePassword": - if (NumberModel.passwordType === PasswordType.TRANSPORT_PIN) { + if (ChangePinModel.lastReturnCode === CardReturnCode.OK_CAN) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.CAN + }); + return; + } else if (ChangePinModel.lastReturnCode === CardReturnCode.OK_PUK) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.PUK + }); + return; + } + if (NumberModel.inputError !== "") { + displayInputError(); + return; + } + if (NumberModel.initialInputError !== "") { + push(inputErrorView, { + "returnCode": NumberModel.passwordType === NumberModel.PasswordType.CAN ? CardReturnCode.INVALID_CAN : CardReturnCode.INVALID_PUK, + "inputError": NumberModel.initialInputError, + "passwordType": NumberModel.passwordType, + "titleVisible": false + }); + NumberModel.setInitialInputErrorShown(); + return; + } + if (NumberModel.passwordType === NumberModel.PasswordType.TRANSPORT_PIN) { setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.TransportPin); } - if (NumberModel.passwordType === PasswordType.PIN) { + if (NumberModel.passwordType === NumberModel.PasswordType.PIN) { setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.Pin); - } else if (NumberModel.passwordType === PasswordType.CAN) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.CAN) { setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.Can); - } else if (NumberModel.passwordType === PasswordType.PUK) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.PUK) { setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.Puk); - } else if (NumberModel.passwordType === PasswordType.SMART_PIN) { + } else if (NumberModel.passwordType === NumberModel.PasswordType.SMART_PIN) { setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.Pin); } break; @@ -75,6 +101,12 @@ Controller { push(cardPositionView); break; case "StateEnterNewPacePin": + if (NumberModel.inputError !== "") { + displayInputError(); + NumberModel.newPin = ""; + NumberModel.newPinConfirmation = ""; + return; + } setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.NewPin); break; case "StateCleanUpReaderManager": @@ -93,6 +125,9 @@ Controller { ChangePinModel.continueWorkflow(); } } + function rerunCurrentState() { + processStateChange(ChangePinModel.currentState); + } function setPinWorkflowStateAndContinue(pState) { rootController.workflowState = pState; ChangePinModel.continueWorkflow(); @@ -101,22 +136,17 @@ Controller { rootController.workflowState = pState; if (ChangePinModel.isBasicReader) { push(enterPinView, { - "passwordType": NumberModel.passwordType, - "inputError": NumberModel.inputError + (NumberModel.inputError !== "" && ChangePinModel.requestTransportPin ? "

%1".arg(transportPinHint) : "") - }); + "passwordType": NumberModel.passwordType + }); } else { ChangePinModel.continueWorkflow(); } } Component.onCompleted: if (ChangePinModel.currentState === "StateMaintainCardConnection") - processStateChange(ChangePinModel.currentState) + rerunCurrentState() Connections { - //: INFO ANDROID IOS The ID card has just been unblocked and the user can now continue with their PIN change. - function onFireOnPinUnlocked() { - ApplicationModel.showFeedback(qsTr("Your ID card PIN is unblocked. You now have three more attempts to change your PIN.")); - } function onFireStateEntered(pState) { processStateChange(pState); } @@ -133,7 +163,7 @@ Controller { GeneralWorkflow { autoInsertCard: rootController.autoInsertCard hideSwitch: rootController.hideTechnologySwitch - initialPlugIn: rootController.initialPlugIn + initialPlugin: rootController.initialPlugin smartEidUsed: rootController.smartEidUsed workflowModel: ChangePinModel workflowTitle: rootController.title @@ -152,6 +182,54 @@ Controller { } } } + Component { + id: inputErrorView + + InputErrorView { + isTransportPin: ChangePinModel.requestTransportPin + smartEidUsed: rootController.smartEidUsed + title: rootController.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + ChangePinModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + NumberModel.resetInputError(); + rootController.rerunCurrentState(); + } + onPasswordInfoRequested: push(passwordInfoView) + } + } + Component { + id: inputSuccessView + + InputSuccessView { + isTransportPin: ChangePinModel.requestTransportPin + smartEidUsed: rootController.smartEidUsed + title: rootController.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + ChangePinModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + setPinWorkflowStateAndRequestInput(ChangePinController.WorkflowStates.Pin); + } + } + } Component { id: pinResult @@ -161,13 +239,21 @@ Controller { setLockedAndHidden(false); } + //: LABEL ANDROID IOS + buttonText: qsTr("Back to start page") hintButtonText: ChangePinModel.statusHintActionText hintText: ChangePinModel.statusHintText + hintTitle: ChangePinModel.statusHintTitle icon: ChangePinModel.error ? ChangePinModel.statusCodeImage.arg(Style.currentTheme.name) : "qrc:///images/workflow_success_changepin_%1.svg".arg(Style.currentTheme.name) smartEidUsed: rootController.smartEidUsed text: ChangePinModel.resultString title: rootController.title + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + enabled: false + } + onCancelClicked: continueClicked() onContinueClicked: endWorkflow() onHintClicked: { @@ -179,7 +265,18 @@ Controller { PasswordInfoData { id: infoData - contentType: fromPasswordType(NumberModel.passwordType) + contentType: { + if (NumberModel.inputError === "" || !ChangePinModel.requestTransportPin) { + return fromPasswordType(NumberModel.passwordType); + } + switch (ChangePinModel.lastReturnCode) { + case CardReturnCode.INVALID_CAN: + case CardReturnCode.INVALID_PUK: + return fromPasswordType(NumberModel.passwordType); + default: + return PasswordInfoData.Type.TRANSPORT_PIN_NOT_WORKING; + } + } } Component { id: passwordInfoView @@ -188,11 +285,8 @@ Controller { infoContent: infoData smartEidUsed: rootController.smartEidUsed - navigationAction: NavigationAction { - action: NavigationAction.Action.Back - - onClicked: pop() - } + onAbortCurrentWorkflow: ChangePinModel.cancelWorkflow() + onClose: pop() } } Component { @@ -210,23 +304,22 @@ Controller { } onPasswordEntered: pPasswordType => { + pop(); switch (pPasswordType) { - case PasswordType.NEW_PIN: - case PasswordType.NEW_SMART_PIN: - rootController.processStateChange(ChangePinModel.currentState); + case NumberModel.PasswordType.NEW_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: + rootController.rerunCurrentState(); break; - case PasswordType.NEW_PIN_CONFIRMATION: - case PasswordType.NEW_SMART_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: if (NumberModel.commitNewPin()) { - pop(); rootController.isNewPin = true; ChangePinModel.continueWorkflow(); } else { - rootController.processStateChange(ChangePinModel.currentState); + rootController.rerunCurrentState(); } break; default: - pop(); ChangePinModel.continueWorkflow(); } } @@ -250,26 +343,23 @@ Controller { //: INFO ANDROID IOS Loading screen during PIN change process, data communication is currently ongoing. Message is usually not visible since the password handling with basic reader is handled by EnterPasswordView. return qsTr("Please do not move the ID card."); } - if (NumberModel.inputError !== "") { - return NumberModel.inputError; - } if (rootController.workflowState === ChangePinController.WorkflowStates.Update || rootController.workflowState === ChangePinController.WorkflowStates.Pin || rootController.workflowState === ChangePinController.WorkflowStates.NewPin) { //: INFO ANDROID IOS Either an comfort card reader or smartphone-as-card-reader is used, the user needs to react to request on that device. return qsTr("Please observe the display of your card reader."); } if (rootController.workflowState === ChangePinController.WorkflowStates.Can) { //: INFO ANDROID IOS The wrong ID card PIN was entered twice, the next attempt requires additional verifcation via CAN. - return qsTr("A wrong ID card PIN has been entered twice on your ID card. For a third attempt, please first enter the six-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); + return qsTr("A wrong ID card PIN has been entered 2 times on your ID card. For a 3rd attempt, please first enter the 6-digit Card Access Number (CAN). You can find your CAN in the bottom right on the front of your ID card."); } if (rootController.workflowState === ChangePinController.WorkflowStates.Puk) { //: INFO ANDROID IOS The ID card PIN (including the CAN) was entered wrongfully three times, the PUK is required to unlock the ID card. - return qsTr("You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. To remove the block, the ten-digit PUK must be entered first."); + return qsTr("You have entered an incorrect, 6-digit ID card PIN 3 times, your ID card PIN is now blocked. To remove the block, the 10-digit PUK must be entered first."); } //: INFO ANDROID IOS Generic progress message during PIN change process. return qsTr("Please wait a moment."); } - subTextColor: !ChangePinModel.isBasicReader && (NumberModel.inputError || rootController.workflowState === ChangePinController.WorkflowStates.Can || rootController.workflowState === ChangePinController.WorkflowStates.Puk) ? Constants.red : Style.color.text + subTextColor: Style.color.textNormal.basic text: { if (isSmartWorkflow) { return rootController.isNewPin ? diff --git a/resources/qml/Governikus/ChangePinView/ChangePinViewContent.qml b/src/ui/qml/modules/ChangePinView/internal/ChangePinViewContent.qml similarity index 65% rename from resources/qml/Governikus/ChangePinView/ChangePinViewContent.qml rename to src/ui/qml/modules/ChangePinView/internal/ChangePinViewContent.qml index a2c46fbd7..d496080db 100644 --- a/resources/qml/Governikus/ChangePinView/ChangePinViewContent.qml +++ b/src/ui/qml/modules/ChangePinView/internal/ChangePinViewContent.qml @@ -1,23 +1,23 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global +import Governikus.PasswordInfoView import Governikus.Style -import Governikus.Type.NumberModel -import Governikus.Type.ApplicationModel +import Governikus.Type +import Governikus.View GFlickableColumnLayout { id: root - readonly property double buttonHeight: Math.max(sixDigitButton.implicitHeight, fiveDigitButton.implicitHeight, dontKnowButton.implicitHeight) readonly property double buttonWidth: Math.max(sixDigitButton.implicitWidth, fiveDigitButton.implicitWidth, dontKnowButton.implicitWidth) - property alias moreInformationText: moreInformationLink.text + readonly property alias pinInfo: infoData signal changePin + signal changePinInfoRequested signal changeTransportPin - signal moreInformationRequested signal noPinAvailable maximumContentWidth: Style.dimens.max_text_width @@ -28,18 +28,29 @@ GFlickableColumnLayout { Layout.alignment: Qt.AlignHCenter Layout.topMargin: Constants.component_spacing + activeFocusOnTab: true //: LABEL ALL_PLATFORMS text: qsTr("What kind of PIN do you have?") textStyle: Style.text.headline wrapMode: Text.WordWrap + + FocusFrame { + } } MoreInformationLink { - id: moreInformationLink - Layout.alignment: Qt.AlignHCenter + text: infoData.linkText + + onClicked: root.changePinInfoRequested() + onFocusChanged: if (focus) + root.positionViewAtItem(this) + + PasswordInfoData { + id: infoData - onClicked: root.moreInformationRequested() + contentType: PasswordInfoData.Type.CHANGE_PIN + } } GInformativeButton { id: sixDigitButton @@ -47,16 +58,16 @@ GFlickableColumnLayout { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.maximumWidth: root.buttonWidth - Layout.preferredHeight: root.buttonHeight //: LABEL ALL_PLATFORMS - description: qsTr("Set by yourself") + description: qsTr("Set by yourself or received by the PIN Reset Service") icon.source: "qrc:///images/icon_six_digit_pin.svg" //: LABEL ALL_PLATFORMS - text: qsTr("Six-digit PIN") - tintIcon: true + text: qsTr("6-digit PIN") onClicked: root.changePin() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } GInformativeButton { id: fiveDigitButton @@ -64,16 +75,16 @@ GFlickableColumnLayout { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.maximumWidth: root.buttonWidth - Layout.preferredHeight: root.buttonHeight //: LABEL ALL_PLATFORMS - description: qsTr("Received by mail in PIN letter") + description: qsTr("Received by letter while ordering your ID card") icon.source: "qrc:///images/icon_five_digit_pin.svg" //: LABEL ALL_PLATFORMS - text: qsTr("Five-digit Transport PIN") - tintIcon: true + text: qsTr("5-digit Transport PIN") onClicked: root.changeTransportPin() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } GInformativeButton { id: dontKnowButton @@ -81,15 +92,15 @@ GFlickableColumnLayout { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.maximumWidth: root.buttonWidth - Layout.preferredHeight: root.buttonHeight //: LABEL ALL_PLATFORMS description: qsTr("Lost, forgotten, or never received it") icon.source: "qrc:///images/material_block.svg" //: LABEL ALL_PLATFORMS text: qsTr("No PIN") - tintIcon: true onClicked: root.noPinAvailable() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/src/ui/qml/modules/CheckIDCardView/+mobile/CheckIDCardView.qml b/src/ui/qml/modules/CheckIDCardView/+mobile/CheckIDCardView.qml new file mode 100644 index 000000000..64594dd22 --- /dev/null +++ b/src/ui/qml/modules/CheckIDCardView/+mobile/CheckIDCardView.qml @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.SelfAuthenticationView +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: root + + signal startAuth + + //: LABEL ANDROID IOS + title: qsTr("Check device and ID card") + + navigationAction: NavigationAction { + action: NavigationAction.Action.Back + + onClicked: show(UiModule.DEFAULT) + } + + onStartAuth: { + popAll(); + push(selfAuthView); + } + + FadeInAnimation { + target: root + } + Component { + id: selfAuthView + + SelfAuthenticationView { + hideTechnologySwitch: true + initialPlugin: ReaderManagerPluginType.NFC + + onBack: { + setLockedAndHidden(false); + pop(); + show(UiModule.DEFAULT); + } + onWorkflowFinished: pModuleToShow => { + show(pModuleToShow); + popAll(); + } + } + } + QtObject { + id: d + + function cancel() { + setLockedAndHidden(false); + popAll(); + } + function restartCheck() { + popAll(); + startCheck(); + } + function startCheck() { + setLockedAndHidden(); + push(checkIDCardWorkflow); + } + } + Component { + id: checkIDCardResultView + + CheckIDCardResultView { + title: root.title + + onCancelClicked: d.cancel() + onRestartCheck: d.restartCheck() + onStartAuth: root.startAuth() + } + } + Component { + id: checkIDCardWorkflow + + CheckIDCardWorkflow { + onCancel: d.cancel() + onRestartCheck: d.restartCheck() + onStartAuth: root.startAuth() + } + } + ColumnLayout { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + spacing: Constants.component_spacing + + TintableIcon { + Layout.alignment: Qt.AlignHCenter + source: "qrc:///images/mobile/device.svg" + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + } + GText { + Layout.alignment: Qt.AlignHCenter + //: LABEL ANDROID IOS + text: qsTr("Check if your device & ID card are ready for use") + textStyle: Style.text.subline + } + GText { + Layout.alignment: Qt.AlignHCenter + //: LABEL ANDROID IOS + text: qsTr("To use the eID function, your device must meet certain technical requirements. Furthermore, the eID function must be activated.") + } + GSpacer { + Layout.fillHeight: true + } + GButton { + Layout.alignment: Qt.AlignHCenter + icon.source: "qrc:///images/mobile/device_button.svg" + + //: LABEL ANDROID IOS + text: qsTr("Start check") + tintIcon: true + + onClicked: { + if (ApplicationModel.nfcState === ApplicationModel.NfcState.UNAVAILABLE) { + setLockedAndHidden(); + push(checkIDCardResultView, { + "result": CheckIDCardModel.Result.NO_NFC + }); + } else { + d.startCheck(); + } + } + onFocusChanged: if (focus) + root.positionViewAtItem(this) + } + } +} diff --git a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardResultView.qml b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardResultView.qml similarity index 64% rename from resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardResultView.qml rename to src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardResultView.qml index b87ff7041..785e4ffa3 100644 --- a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardResultView.qml +++ b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQml.Models @@ -7,7 +7,7 @@ import Governikus.CheckResultView import Governikus.Global import Governikus.ResultView import Governikus.Style -import Governikus.Type.CheckIDCardModel +import Governikus.Type CheckResultView { id: root @@ -15,16 +15,16 @@ CheckResultView { signal restartCheck signal startAuth - buttonIcon: result === CheckIDCardModel.SUCCESS ? "qrc:///images/mydata.svg" : "qrc:///images/mobile/help.svg" + buttonIcon: result === CheckIDCardModel.Result.SUCCESS ? "qrc:///images/mobile/mydata_button.svg" : "qrc:///images/mobile/help.svg" //: LABEL ANDROID IOS buttonText: { switch (result) { - case CheckIDCardModel.SUCCESS: + case CheckIDCardModel.Result.SUCCESS: //: LABEL ANDROID IOS return qsTr("Continue"); - case CheckIDCardModel.PIN_DEACTIVATED: - case CheckIDCardModel.PIN_SUSPENDED: - case CheckIDCardModel.PIN_BLOCKED: + case CheckIDCardModel.Result.PIN_DEACTIVATED: + case CheckIDCardModel.Result.PIN_SUSPENDED: + case CheckIDCardModel.Result.PIN_BLOCKED: //: LABEL ANDROID IOS return qsTr("How to proceed?"); default: @@ -34,25 +34,25 @@ CheckResultView { } //: LABEL ANDROID IOS header: qsTr("Test Result") - icon: result === CheckIDCardModel.SUCCESS ? "qrc:///images/mobile/workflow_success_nfc_%1.svg".arg(Style.currentTheme.name) : "qrc:///images/workflow_error_nfc_%1.svg".arg(Style.currentTheme.name) + icon: result === CheckIDCardModel.Result.SUCCESS ? "qrc:///images/mobile/workflow_success_nfc_%1.svg".arg(Style.currentTheme.name) : "qrc:///images/workflow_error_nfc_%1.svg".arg(Style.currentTheme.name) model: resultModel //: LABEL ANDROID IOS title: qsTr("Check device and ID card") onContinueClicked: { - if (result === CheckIDCardModel.SUCCESS) { + if (result === CheckIDCardModel.Result.SUCCESS) { root.startAuth(); } else { push(checkIDCardSuggestionView, { - "result": root.result - }); + "result": root.result + }); } } GText { font.bold: true horizontalAlignment: Text.AlignHCenter - text: result === CheckIDCardModel.SUCCESS ? qsTr("You may now try the function: \"See my personal data\". Press the Continue button to do so now.") : "" + text: result === CheckIDCardModel.Result.SUCCESS ? qsTr("You may now try the function: \"See my personal data\". Press the Continue button to do so now.") : "" visible: text !== "" width: parent.width } @@ -60,8 +60,6 @@ CheckResultView { id: checkIDCardSuggestionView CheckIDCardSuggestionView { - title: root.title - onCancelClicked: root.cancelClicked() onRestartCheck: root.restartCheck() onStartAuth: root.startAuth() @@ -71,7 +69,7 @@ CheckResultView { id: resultModel ResultEntry { - readonly property bool nfcSupported: result !== CheckIDCardModel.NO_NFC + readonly property bool nfcSupported: result !== CheckIDCardModel.Result.NO_NFC resultType: nfcSupported ? ResultEntry.Type.IsSuccess : ResultEntry.Type.IsError @@ -86,23 +84,23 @@ CheckResultView { //: LABEL ANDROID IOS text: qsTr("NFC enabled") - visible: result > CheckIDCardModel.NO_NFC + visible: result > CheckIDCardModel.Result.NO_NFC } ResultEntry { resultType: ResultEntry.Type.IsInfo //: LABEL ANDROID IOS text: qsTr("No supported card detected") - visible: result === CheckIDCardModel.UNKNOWN_CARD_DETECTED + visible: result === CheckIDCardModel.Result.UNKNOWN_CARD_DETECTED } ResultEntry { //: LABEL ANDROID IOS text: qsTr("ID card detected") - visible: result >= CheckIDCardModel.ID_CARD_DETECTED + visible: result >= CheckIDCardModel.Result.ID_CARD_DETECTED } ResultEntry { - readonly property bool insufficientApduLength: result === CheckIDCardModel.INSUFFICIENT_APDU_LENGTH + readonly property bool insufficientApduLength: result === CheckIDCardModel.Result.INSUFFICIENT_APDU_LENGTH resultType: insufficientApduLength ? ResultEntry.Type.IsError : ResultEntry.Type.IsSuccess @@ -112,10 +110,10 @@ CheckResultView { qsTr("Extended length not supported") : //: LABEL ANDROID IOS qsTr("Extended length supported") - visible: result >= CheckIDCardModel.INSUFFICIENT_APDU_LENGTH && Constants.is_layout_android + visible: result >= CheckIDCardModel.Result.INSUFFICIENT_APDU_LENGTH && Constants.is_layout_android } ResultEntry { - readonly property bool cardAccessFailed: result === CheckIDCardModel.CARD_ACCESS_FAILED + readonly property bool cardAccessFailed: result === CheckIDCardModel.Result.CARD_ACCESS_FAILED resultType: cardAccessFailed ? ResultEntry.Type.IsError : ResultEntry.Type.IsSuccess text: cardAccessFailed ? @@ -123,38 +121,38 @@ CheckResultView { qsTr("ID card access failed") : //: LABEL ANDROID IOS qsTr("ID card access successful") - visible: result >= CheckIDCardModel.CARD_ACCESS_FAILED + visible: result >= CheckIDCardModel.Result.CARD_ACCESS_FAILED } ResultEntry { - readonly property bool pinDeactivated: result === CheckIDCardModel.PIN_DEACTIVATED + readonly property bool pinDeactivated: result === CheckIDCardModel.Result.PIN_DEACTIVATED resultType: pinDeactivated ? ResultEntry.Type.IsError : ResultEntry.Type.IsSuccess text: pinDeactivated ? //: LABEL ANDROID IOS - qsTr("Online identification feature disabled") : + qsTr("eID function disabled") : //: LABEL ANDROID IOS - qsTr("Online identification feature enabled") - visible: result >= CheckIDCardModel.PIN_DEACTIVATED + qsTr("eID function enabled") + visible: result >= CheckIDCardModel.Result.PIN_DEACTIVATED } ResultEntry { resultType: ResultEntry.Type.IsInfo //: LABEL ANDROID IOS text: qsTr("ID card PIN suspended") - visible: result === CheckIDCardModel.PIN_SUSPENDED + visible: result === CheckIDCardModel.Result.PIN_SUSPENDED } ResultEntry { resultType: ResultEntry.Type.IsInfo //: LABEL ANDROID IOS text: qsTr("ID card PIN blocked") - visible: result === CheckIDCardModel.PIN_BLOCKED + visible: result === CheckIDCardModel.Result.PIN_BLOCKED } ResultEntry { //: LABEL ANDROID IOS text: qsTr("ID card functional") - visible: result === CheckIDCardModel.SUCCESS + visible: result === CheckIDCardModel.Result.SUCCESS } } } diff --git a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardSuggestionView.qml b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardSuggestionView.qml similarity index 74% rename from resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardSuggestionView.qml rename to src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardSuggestionView.qml index b68d616ba..7dfdbf947 100644 --- a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardSuggestionView.qml +++ b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardSuggestionView.qml @@ -1,11 +1,9 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.CheckResultView -import Governikus.Type.CheckIDCardModel -import Governikus.Type.PinResetInformationModel -import Governikus.Type.SettingsModel +import Governikus.Type CheckResultSuggestionView { id: root @@ -18,19 +16,19 @@ CheckResultSuggestionView { Accessible.name: suggestionData.title suggestionData: { switch (result) { - case CheckIDCardModel.NO_NFC: + case CheckIDCardModel.Result.NO_NFC: return noNfcSuggestionData; - case CheckIDCardModel.UNKNOWN_CARD_DETECTED: + case CheckIDCardModel.Result.UNKNOWN_CARD_DETECTED: return unknownCardSuggestionData; - case CheckIDCardModel.INSUFFICIENT_APDU_LENGTH: + case CheckIDCardModel.Result.INSUFFICIENT_APDU_LENGTH: return insufficientApduLengthSuggestionData; - case CheckIDCardModel.CARD_ACCESS_FAILED: + case CheckIDCardModel.Result.CARD_ACCESS_FAILED: return cardAccessFailedSuggestionData; - case CheckIDCardModel.PIN_DEACTIVATED: + case CheckIDCardModel.Result.PIN_DEACTIVATED: return pinDeactivatedSuggestionData; - case CheckIDCardModel.PIN_SUSPENDED: + case CheckIDCardModel.Result.PIN_SUSPENDED: return pinSuspendedSuggestionData; - case CheckIDCardModel.PIN_BLOCKED: + case CheckIDCardModel.Result.PIN_BLOCKED: return pinBlockedSuggestionData; default: return empty; @@ -48,9 +46,9 @@ CheckResultSuggestionView { continueButtonIcon: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS - continueButtonText: qsTr("Open website") + continueButtonText: qsTr("List of compatible devices") //: LABEL ANDROID IOS - text: qsTr("Your mobile device has no NFC interface. This is required to read the ID card. However, you can use a separate smartphone as card reader to utilize the eID function.

You can find smartphones compatible with the %1 on our website.").arg(Qt.application.name) + text: qsTr("Your mobile device has no NFC interface. This is required to read the ID card. To use the eID function on this device you may pair a NFC capable smartphone as a card reader.

To pair a smartphone go to Settings and Manage Pairings.

You can find smartphones compatible with the %1 on our website.").arg(Qt.application.name) //: LABEL ANDROID IOS title: qsTr("No NFC") @@ -64,7 +62,9 @@ CheckResultSuggestionView { //: LABEL ANDROID IOS continueButtonText: qsTr("Retry") //: LABEL ANDROID IOS - text: qsTr("No supported ID card was detected. The %1 supports:

  • German ID cards
  • Electronic residence permits (eAT)
  • eID cards

If you have used one of the above documents and this error message still appears, please restart the check.

Tip: Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device.").arg(Qt.application.name) + hintText: qsTr("Try a different card position, make sure that you do not move the ID card during the check and that there are no other NFC cards (e.g. credit cards) near the device.") + //: LABEL ANDROID IOS + text: qsTr("No supported ID card was detected. The %1 supports:

  • German ID cards
  • Electronic residence permits (eAT)
  • eID cards for citizen of the EU/EEA/

If you have used one of the above documents and this error message still appears, please restart the check.").arg(Qt.application.name) //: LABEL ANDROID IOS title: qsTr("No supported card detected") @@ -108,10 +108,12 @@ CheckResultSuggestionView { continueButtonText: qsTr("OK") hintButtonText: PinResetInformationModel.pinResetActionText hintText: PinResetInformationModel.activateOnlineFunctionHint + //: LABEL ANDROID IOS Hint when a workflow failed because the eID function was not activated + hintTitle: qsTr("Activate the eID function.") text: PinResetInformationModel.activateOnlineFunctionDescription //: LABEL ANDROID IOS - title: qsTr("Online identification feature disabled") + title: qsTr("eID function disabled") onContinueClicked: navigationAction.clicked() onHintClicked: Qt.openUrlExternally(PinResetInformationModel.pinResetUrl) @@ -123,7 +125,7 @@ CheckResultSuggestionView { //: LABEL ANDROID IOS continueButtonText: qsTr("Continue") //: LABEL ANDROID IOS - text: qsTr("The ID card PIN has been entered incorrectly twice in a row. This is why you must first enter the six-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.

You may now try the function: \"See my personal data\". There you can also use the CAN to unblock the ID card PIN.") + text: qsTr("The ID card PIN has been entered incorrectly 2 times in a row. This is why you must first enter the 6-digit Card Access Number (CAN) for the next identification process. You can find it at the bottom right of the front of your ID card.

You may now try the function: \"See my personal data\". There you can also use the CAN to unblock the ID card PIN.") //: LABEL ANDROID IOS title: qsTr("ID card PIN suspended") @@ -139,7 +141,7 @@ CheckResultSuggestionView { hintButtonText: PinResetInformationModel.pinResetActionText hintText: PinResetInformationModel.noPinAndNoPukHint //: LABEL ANDROID IOS - text: qsTr("The ID card PIN has been entered incorrectly thrice. Therefore, you must first enter the ten-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.

You may now try the function: \"See my personal data\". Have your PUK ready to unlock the ID card PIN.") + text: qsTr("The ID card PIN has been entered incorrectly 3 times. Therefore, you must first enter the 10-digit PUK during the next authentication process. You can find it in the PIN letter you received after applying for your ID card.

You may now try the function: \"See my personal data\". Have your PUK ready to unlock the ID card PIN.") //: LABEL ANDROID IOS title: qsTr("ID card PIN blocked") diff --git a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardWorkflow.qml b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardWorkflow.qml similarity index 79% rename from resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardWorkflow.qml rename to src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardWorkflow.qml index d5cb42514..38f707aec 100644 --- a/resources/qml/Governikus/CheckIDCardView/+mobile/CheckIDCardWorkflow.qml +++ b/src/ui/qml/modules/CheckIDCardView/+mobile/internal/CheckIDCardWorkflow.qml @@ -1,13 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.ProgressView import Governikus.TitleBar import Governikus.View import Governikus.Workflow -import Governikus.Type.CheckIDCardModel -import Governikus.Type.ApplicationModel +import Governikus.Type SectionPage { id: root @@ -42,8 +41,8 @@ SectionPage { interval: 1 onTriggered: push(checkIDCardResultView, { - "result": checkIDCardModel.result - }) + "result": checkIDCardModel.result + }) } Component { id: checkIDCardResultView @@ -60,7 +59,7 @@ SectionPage { id: nfcWorkflow anchors.fill: parent - visible: checkIDCardModel.result < CheckIDCardModel.ID_CARD_DETECTED + visible: checkIDCardModel.result < CheckIDCardModel.Result.ID_CARD_DETECTED onStartScanIfNecessary: checkIDCardModel.startScanIfNecessary() } @@ -74,6 +73,6 @@ SectionPage { //: LABEL ANDROID IOS text: qsTr("Checking ID card") title: root.title - visible: checkIDCardModel.result >= CheckIDCardModel.ID_CARD_DETECTED + visible: checkIDCardModel.result >= CheckIDCardModel.Result.ID_CARD_DETECTED } } diff --git a/resources/qml/Governikus/CheckResultView/+mobile/CheckResultSuggestionView.qml b/src/ui/qml/modules/CheckResultView/+mobile/CheckResultSuggestionView.qml similarity index 83% rename from resources/qml/Governikus/CheckResultView/+mobile/CheckResultSuggestionView.qml rename to src/ui/qml/modules/CheckResultView/+mobile/CheckResultSuggestionView.qml index 8f4f1ab25..712b78878 100644 --- a/resources/qml/Governikus/CheckResultView/+mobile/CheckResultSuggestionView.qml +++ b/src/ui/qml/modules/CheckResultView/+mobile/CheckResultSuggestionView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -16,6 +16,7 @@ ResultView { header: suggestionData.header hintButtonText: suggestionData.hintButtonText hintText: suggestionData.hintText + hintTitle: suggestionData.hintTitle icon: suggestionData.icon text: suggestionData.text textFormat: suggestionData.textFormat @@ -32,5 +33,7 @@ ResultView { visible: text !== "" onClicked: suggestionData.actionClicked() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/resources/qml/Governikus/CheckResultView/+mobile/CheckResultView.qml b/src/ui/qml/modules/CheckResultView/+mobile/CheckResultView.qml similarity index 77% rename from resources/qml/Governikus/CheckResultView/+mobile/CheckResultView.qml rename to src/ui/qml/modules/CheckResultView/+mobile/CheckResultView.qml index 2d8545f10..2807ebfa8 100644 --- a/resources/qml/Governikus/CheckResultView/+mobile/CheckResultView.qml +++ b/src/ui/qml/modules/CheckResultView/+mobile/CheckResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts diff --git a/resources/qml/Governikus/CheckResultView/+mobile/ResultEntry.qml b/src/ui/qml/modules/CheckResultView/+mobile/ResultEntry.qml similarity index 76% rename from resources/qml/Governikus/CheckResultView/+mobile/ResultEntry.qml rename to src/ui/qml/modules/CheckResultView/+mobile/ResultEntry.qml index 1d5b934bc..c0d8b6dec 100644 --- a/resources/qml/Governikus/CheckResultView/+mobile/ResultEntry.qml +++ b/src/ui/qml/modules/CheckResultView/+mobile/ResultEntry.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -46,9 +46,9 @@ RowLayout { case ResultEntry.Type.IsSuccess: return Style.color.success; case ResultEntry.Type.IsInfo: - return Style.color.text; + return Style.color.textNormal.basic; case ResultEntry.Type.IsError: - return Style.color.text_warning; + return Style.color.warning; } } } @@ -57,15 +57,5 @@ RowLayout { Accessible.ignored: true elide: Text.ElideRight - textStyle: { - switch (resultType) { - case ResultEntry.Type.IsSuccess: - return Style.text.normal; - case ResultEntry.Type.IsInfo: - return Style.text.normal; - case ResultEntry.Type.IsError: - return Style.text.normal_warning; - } - } } } diff --git a/resources/qml/Governikus/CheckResultView/+mobile/SuggestionData.qml b/src/ui/qml/modules/CheckResultView/+mobile/SuggestionData.qml similarity index 84% rename from resources/qml/Governikus/CheckResultView/+mobile/SuggestionData.qml rename to src/ui/qml/modules/CheckResultView/+mobile/SuggestionData.qml index cddad9c7a..ba20e4374 100644 --- a/resources/qml/Governikus/CheckResultView/+mobile/SuggestionData.qml +++ b/src/ui/qml/modules/CheckResultView/+mobile/SuggestionData.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.ResultView @@ -13,6 +13,7 @@ QtObject { property string header property string hintButtonText property string hintText + property string hintTitle: qsTr("Hint") property url icon: "qrc:///images/status_info_%1.svg".arg(Style.currentTheme.name) property string text property int textFormat: Text.AutoText diff --git a/src/ui/qml/modules/EnterPasswordView/EnterPasswordView.qml b/src/ui/qml/modules/EnterPasswordView/EnterPasswordView.qml new file mode 100644 index 000000000..f0e1cd9b2 --- /dev/null +++ b/src/ui/qml/modules/EnterPasswordView/EnterPasswordView.qml @@ -0,0 +1,357 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Animations +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + property string accessibleContinueText + property alias enableTransportPinLink: transportPinLink.visible + property alias moreInformationText: moreInformation.text + required property int passwordType + + signal changePinLength + signal passwordEntered(var pPasswordType) + signal requestPasswordInfo + + fillWidth: true + + Component.onCompleted: d.forceRedraw = 0 + Keys.onPressed: event => { + event.accepted = pinField.handleKeyEvent(event.key, event.modifiers); + } + onVisibleChanged: if (!visible) + pinField.number = "" + + QtObject { + id: d + + property int forceRedraw: 1 + + function setPassword() { + // On desktop the passwordType binding changes once we set any PIN/CAN/whatever. If we + // remove the tmp var it will lead to loops while entering PINs and users cannot reach + // further workflow steps. On mobile this is irrelevant, since passwordType is static there. + let currentPasswordType = baseItem.passwordType; + switch (currentPasswordType) { + case NumberModel.PasswordType.PIN: + case NumberModel.PasswordType.TRANSPORT_PIN: + case NumberModel.PasswordType.SMART_PIN: + NumberModel.pin = pinField.number; + baseItem.passwordEntered(currentPasswordType); + break; + case NumberModel.PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_PIN: + NumberModel.newPin = pinField.number; + mainText.forceActiveFocus(Qt.MouseFocusReason); + baseItem.passwordEntered(currentPasswordType); + break; + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + NumberModel.newPinConfirmation = pinField.number; + mainText.forceActiveFocus(Qt.MouseFocusReason); + baseItem.passwordEntered(currentPasswordType); + break; + case NumberModel.PasswordType.CAN: + NumberModel.can = pinField.number; + baseItem.passwordEntered(currentPasswordType); + break; + case NumberModel.PasswordType.PUK: + NumberModel.puk = pinField.number; + baseItem.passwordEntered(currentPasswordType); + break; + case NumberModel.PasswordType.REMOTE_PIN: + RemoteServiceModel.connectToRememberedServer(pinField.number); + baseItem.passwordEntered(currentPasswordType); + break; + } + pinField.number = ""; + } + } + GridLayout { + id: grid + + readonly property bool isLandscape: width > Math.max(infoLayout.Layout.minimumWidth, pinField.Layout.preferredWidth) + separator.implicitWidth + numberPad.implicitWidth + + Layout.maximumHeight: Number.POSITIVE_INFINITY + Layout.maximumWidth: Number.POSITIVE_INFINITY + Layout.minimumHeight: isLandscape ? Math.max(infoLayout.Layout.minimumHeight, numberPad.Layout.minimumHeight) : (infoLayout.Layout.minimumHeight + rowSpacing + numberPad.Layout.minimumHeight) + Layout.minimumWidth: Math.max(infoLayout.Layout.minimumWidth, numberPad.Layout.minimumWidth) + Layout.preferredHeight: implicitHeight + d.forceRedraw + columnSpacing: 0 + flow: isLandscape ? GridLayout.LeftToRight : GridLayout.TopToBottom + rowSpacing: Constants.component_spacing + + GSpacer { + Layout.fillWidth: true + visible: grid.isLandscape + } + ColumnLayout { + id: infoLayout + + Layout.alignment: Qt.AlignCenter + Layout.maximumWidth: Style.dimens.max_text_width + spacing: 0 + + AnimationLoader { + Layout.alignment: Qt.AlignHCenter + Layout.bottomMargin: Constants.component_spacing + type: { + if (grid.isLandscape && !Constants.is_desktop) { + return AnimationLoader.Type.NONE; + } + switch (baseItem.passwordType) { + case NumberModel.PasswordType.TRANSPORT_PIN: + return AnimationLoader.Type.ENTER_TRANSPORT_PIN; + case NumberModel.PasswordType.CAN: + return AnimationLoader.Type.ENTER_CAN; + case NumberModel.PasswordType.SMART_PIN: + case NumberModel.PasswordType.PIN: + return AnimationLoader.Type.ENTER_PIN; + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: + return AnimationLoader.Type.ENTER_NEW_PIN; + case NumberModel.PasswordType.PUK: + return AnimationLoader.Type.ENTER_PUK; + case NumberModel.PasswordType.REMOTE_PIN: + return AnimationLoader.Type.ENTER_REMOTE_PIN; + default: + return AnimationLoader.Type.NONE; + } + } + } + GText { + id: mainText + + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + text: baseItem.passwordType === NumberModel.PasswordType.CAN ? qsTr("Enter CAN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.PUK ? qsTr("Enter PUK") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.REMOTE_PIN ? qsTr("Enter pairing code") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.NEW_PIN ? qsTr("Choose new ID card PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Confirm ID card PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.TRANSPORT_PIN ? qsTr("Enter Transport PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.SMART_PIN ? qsTr("Enter Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN ? qsTr("Choose new Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Confirm Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the large main text below the icon. + qsTr("Enter ID card PIN") + textStyle: Style.text.headline + + FocusFrame { + } + } + GText { + id: infoText + + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: Constants.text_spacing + activeFocusOnTab: true + elide: Text.ElideRight + horizontalAlignment: Text.AlignHCenter + maximumLineCount: 3 + text: { + if (baseItem.passwordType === NumberModel.PasswordType.CAN) { + //: INFO ALL_PLATFORMS The user is required to enter the 6-digit CAN. This is the description for the main text. + return qsTr("Please enter the CAN. You can find the CAN in the bottom right on the front of the ID card."); + } + if (baseItem.passwordType === NumberModel.PasswordType.PUK) { + //: INFO ALL_PLATFORMS The PUK is required to unlock the ID card since the wrong ID card PIN entered three times. This is the description for the main text. + return qsTr("Please enter your 10-digit PUK."); + } + if (baseItem.passwordType === NumberModel.PasswordType.NEW_PIN) { + //: INFO ALL_PLATFORMS A new 6-digit ID card PIN needs to be supplied. This is the description for the main text. + return qsTr("You will enter this 6-digit PIN every time you want to use your ID card online."); + } + if (baseItem.passwordType === NumberModel.PasswordType.NEW_PIN_CONFIRMATION) { + //: INFO ALL_PLATFORMS The new ID card PIN needs to be confirmed. This is the description for the main text. + return qsTr("The PIN is going to be tied to your ID card. It always stays the same regardless of the device you want to use your ID card with."); + } + if (baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN) { + //: INFO ALL_PLATFORMS A new 6-digit Smart-eID PIN needs to be supplied. This is the description for the main text. + return qsTr("You will enter this 6-digit PIN every time you want to use your Smart-eID."); + } + if (baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION) { + //: INFO ALL_PLATFORMS The new Smart-eID PIN needs to be confirmed. This is the description for the main text. + return qsTr("The PIN is going to be tied to your Smart-eID. It always stays the same regardless of the service you want to use your Smart-eID with."); + } + if (baseItem.passwordType === NumberModel.PasswordType.TRANSPORT_PIN) { + //: INFO ALL_PLATFORMS The Transport PIN is required by AA, it needs to be change to an actual PIN. This is the description for the main text. + return qsTr("Please enter the 5-digit Transport PIN."); + } + if (baseItem.passwordType === NumberModel.PasswordType.REMOTE_PIN) { + return Constants.is_desktop ? + //: INFO DESKTOP The pairing code needs to be supplied. This is the description for the main text. + qsTr("Enter the pairing code shown on your smartphone.") : + //: INFO MOBILE The pairing code for the smartphone is required. This is the description for the main text. + qsTr("Enter the pairing code shown on the device you want to pair."); + } + if (baseItem.passwordType === NumberModel.PasswordType.SMART_PIN) { + if (NumberModel.retryCounter === 1) { + //: INFO ALL_PLATFORMS The wrong Smart-eID PIN was entered twice on the Smart-eID + return qsTr("You have entered an incorrect, 6-digit Smart-eID PIN 2 times. After the next failed attempt you will no longer be able to use your Smart-eID and will need to set it up again."); + } + return ApplicationModel.currentWorkflow === ApplicationModel.Workflow.CHANGE_PIN ? + //: INFO ALL_PLATFORMS The AA expects the current Smart-eID PIN with six digits in a PIN change. This is the description for the main text. + qsTr("Please enter your current 6-digit Smart-eID PIN.") : + //: INFO ALL_PLATFORMS The AA expects a Smart-eID PIN with six digits in an authentication. This is the description for the main text. + qsTr("Please enter your 6-digit Smart-eID PIN."); + } + return ApplicationModel.currentWorkflow === ApplicationModel.Workflow.CHANGE_PIN ? + //: INFO ALL_PLATFORMS The AA2 expects the current ID card PIN with six digits in a PIN change. This is the description for the main text. + qsTr("Please enter your current 6-digit ID card PIN.") : + //: INFO ALL_PLATFORMS The AA2 expects a ID card PIN with six digits in an authentication. This is the description for the main text. + qsTr("Please enter your 6-digit ID card PIN."); + } + + MouseArea { + anchors.fill: parent + anchors.margins: -12 + enabled: infoText.truncated + + onClicked: completeTextPopup.open() + } + FocusFrame { + } + } + GSpacer { + Layout.fillHeight: true + visible: !grid.isLandscape + } + MoreInformationLink { + id: transportPinLink + + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: Constants.text_spacing + text: (baseItem.passwordType === NumberModel.PasswordType.TRANSPORT_PIN ? + //: LABEL ALL_PLATFORMS Button to switch to a 6-digit ID card PIN. + qsTr("Do you have a 6-digit ID card PIN?") : + //: LABEL ALL_PLATFORMS Button to start a change of the Transport PIN. + qsTr("Do you have a 5-digit Transport PIN?")) + visible: false + + onClicked: baseItem.changePinLength() + } + MoreInformationLink { + id: moreInformation + + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: Constants.text_spacing + visible: text !== "" && baseItem.passwordType !== NumberModel.PasswordType.REMOTE_PIN + + onClicked: baseItem.requestPasswordInfo() + } + NumberField { + id: pinField + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.topMargin: Constants.component_spacing + padding: Constants.component_spacing / 2 + passwordLength: baseItem.passwordType === NumberModel.PasswordType.REMOTE_PIN ? 4 : baseItem.passwordType === NumberModel.PasswordType.TRANSPORT_PIN ? 5 : baseItem.passwordType === NumberModel.PasswordType.PUK ? 10 : 6 + + background: Rectangle { + border.color: Style.color.border + border.width: Style.dimens.separator_size + color: Style.color.transparent + radius: Style.dimens.control_radius + } + + onAccepted: d.setPassword() + } + } + ColumnLayout { + id: separator + + visible: grid.isLandscape + + GSpacer { + Layout.fillHeight: true + Layout.preferredHeight: 1 / 8 + } + GSeparator { + Layout.fillHeight: true + Layout.leftMargin: Constants.component_spacing + Layout.preferredHeight: 6 / 8 + Layout.rightMargin: Constants.component_spacing + orientation: Qt.Vertical + } + GSpacer { + Layout.fillHeight: true + Layout.preferredHeight: 1 / 8 + } + } + GSpacer { + Layout.fillWidth: true + Layout.maximumWidth: Constants.component_spacing + visible: grid.isLandscape + } + NumberPad { + id: numberPad + + Layout.alignment: grid.isLandscape ? Qt.AlignCenter : Qt.AlignHCenter | Qt.AlignTop + deleteEnabled: pinField.number.length > 0 + submitAccessibleText: baseItem.accessibleContinueText !== "" ? baseItem.accessibleContinueText : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.CAN ? qsTr("Send CAN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.PUK ? qsTr("Send PUK") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.REMOTE_PIN ? qsTr("Send pairing code") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.NEW_PIN ? qsTr("Send new ID card PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.NEW_PIN_CONFIRMATION ? qsTr("Confirm new ID card PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.TRANSPORT_PIN ? qsTr("Send Transport PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.SMART_PIN ? qsTr("Send Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN ? qsTr("Send new Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + baseItem.passwordType === NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION ? qsTr("Confirm new Smart-eID PIN") : + //: LABEL ALL_PLATFORMS This is the accessible text on the send/confirm button of the number pad. + qsTr("Send ID card PIN") + submitEnabled: pinField.validInput + + onDeletePressed: { + pinField.removeLast(); + if (pinField.number.length === 0) + pinField.forceActiveFocus(); + } + onDigitPressed: digit => pinField.append(digit) + onSubmitPressed: d.setPassword() + } + GSpacer { + Layout.fillWidth: true + visible: grid.isLandscape + } + } + ConfirmationPopup { + id: completeTextPopup + + style: ConfirmationPopup.PopupStyle.OkButton + text: infoText.text + } +} diff --git a/resources/qml/Governikus/EnterPasswordView/+mobile/NumberPad.qml b/src/ui/qml/modules/EnterPasswordView/internal/NumberPad.qml similarity index 79% rename from resources/qml/Governikus/EnterPasswordView/+mobile/NumberPad.qml rename to src/ui/qml/modules/EnterPasswordView/internal/NumberPad.qml index e19fd180f..54e7dce07 100644 --- a/resources/qml/Governikus/EnterPasswordView/+mobile/NumberPad.qml +++ b/src/ui/qml/modules/EnterPasswordView/internal/NumberPad.qml @@ -1,16 +1,16 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global -import Governikus.Type.SettingsModel +import Governikus.Type GridLayout { id: baseItem property bool deleteEnabled: true - property string submitAccessibleText + property alias submitAccessibleText: submitButton.a11yText property bool submitEnabled: true signal deletePressed @@ -55,9 +55,10 @@ GridLayout { //: LABEL ANDROID IOS A11y text for the "delete" button text when the button is disabled. a11yDisabledText: qsTr("Delete last digit, disabled until input is present.") + //: LABEL ANDROID IOS A11y text for the "delete" button image. + a11yText: qsTr("Delete last digit") enabled: baseItem.deleteEnabled - icon.source: "qrc:///images/mobile/material_backspace.svg" - text: qsTr("Delete last digit") + icon.source: "qrc:///images/material_backspace.svg" onClicked: baseItem.deletePressed() } @@ -70,16 +71,18 @@ GridLayout { onClicked: baseItem.digitPressed(text) } - NumberPadButton { + SubmitButton { + id: submitButton + Layout.fillHeight: true Layout.fillWidth: true //: LABEL ANDROID IOS A11y text, appended onto the "submit" button text when the button is disabled. a11yDisabledText: a11yText + qsTr(", disabled until input is complete.") - a11yText: submitAccessibleText !== "" ? submitAccessibleText : text + //: LABEL ANDROID IOS A11y text for the "submit" button image. + a11yText: qsTr("Submit") enabled: baseItem.submitEnabled icon.source: "qrc:///images/material_check.svg" - text: qsTr("Submit") onClicked: baseItem.submitPressed() } diff --git a/src/ui/qml/modules/EnterPasswordView/internal/NumberPadButton.qml b/src/ui/qml/modules/EnterPasswordView/internal/NumberPadButton.qml new file mode 100644 index 000000000..b74ae44f5 --- /dev/null +++ b/src/ui/qml/modules/EnterPasswordView/internal/NumberPadButton.qml @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +AbstractButton { + id: root + + property string a11yDisabledText: qsTr("Disabled") + property string a11yText: "" + readonly property alias colors: colors + property real fontScale: 1 + property bool visualPrivacy: SettingsModel.visualPrivacy + + Accessible.name: root.enabled ? (a11yText === "" ? text : a11yText) : a11yDisabledText + Layout.maximumHeight: implicitHeight + Layout.maximumWidth: implicitWidth + Layout.minimumHeight: 1.2 * Style.dimens.textHeadline + Layout.minimumWidth: Layout.minimumHeight / d.aspectRatio + implicitHeight: 2 * Style.dimens.textHeadline + implicitWidth: implicitHeight / d.aspectRatio + + background: GPaneBackground { + border.color: colors.paneBorder + color: colors.paneBackground + drawShadow: false + radius: Style.dimens.control_radius + + TintableIcon { + anchors.centerIn: parent + source: root.icon.source + sourceSize.height: Math.min(0.8 * root.height, 1.5 * Style.dimens.textHeadline) + tintColor: contentItem.color + visible: !contentItem.visible + } + FocusFrame { + marginFactor: 0.8 + radius: parent.radius * 1.2 + scope: root + } + } + contentItem: GText { + Accessible.ignored: true + color: colors.textHeadline + font.pixelSize: fontScale * Style.dimens.textHeadline + horizontalAlignment: Text.AlignHCenter + text: root.text + textStyle: Style.text.headline + visible: text !== "" + } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + hoveredCondition: !root.visualPrivacy && hoverHandler.hovered + paneStyle: Style.color.paneSublevel + pressedCondition: !root.visualPrivacy && root.pressed + statefulControl: root + } + QtObject { + id: d + + readonly property real aspectRatio: 0.7 + } +} diff --git a/src/ui/qml/modules/EnterPasswordView/internal/SubmitButton.qml b/src/ui/qml/modules/EnterPasswordView/internal/SubmitButton.qml new file mode 100644 index 000000000..5f5a190f4 --- /dev/null +++ b/src/ui/qml/modules/EnterPasswordView/internal/SubmitButton.qml @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import Governikus.Global + +NumberPadButton { + id: root + + colors.paneBackground: colors.controlBackground + colors.paneBorder: colors.controlBorder + colors.textHeadline: colors.controlContent +} diff --git a/resources/qml/Governikus/FeedbackView/+desktop/DetachedLogView.qml b/src/ui/qml/modules/FeedbackView/+desktop/DetachedLogView.qml similarity index 52% rename from resources/qml/Governikus/FeedbackView/+desktop/DetachedLogView.qml rename to src/ui/qml/modules/FeedbackView/+desktop/DetachedLogView.qml index dbe7eca83..db7e446a5 100644 --- a/resources/qml/Governikus/FeedbackView/+desktop/DetachedLogView.qml +++ b/src/ui/qml/modules/FeedbackView/+desktop/DetachedLogView.qml @@ -1,18 +1,22 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.LogModel -import Governikus.Type.LogFilterModel +import Governikus.Type import Governikus.View Rectangle { id: root + readonly property int controlRadius: 15 + readonly property int horizontalPadding: 18 + readonly property int spacing: 10 + readonly property int verticalPadding: 6 + color: Style.color.background Keys.onPressed: event => { @@ -22,6 +26,10 @@ Rectangle { LogFilterModel { id: filterModel + } + LogTextStyle { + id: logTextStyle + } ColumnLayout { anchors.fill: parent @@ -29,37 +37,63 @@ Rectangle { RowLayout { Layout.fillWidth: true - Layout.margins: Constants.groupbox_spacing - spacing: Constants.groupbox_spacing + Layout.margins: root.spacing + spacing: root.spacing - GText { - activeFocusOnTab: true - text: qsTr("Select log:") + ColumnLayout { + GText { + activeFocusOnTab: true + //: LABEL DESKTOP + text: qsTr("Select log:") + textStyle: logTextStyle - FocusFrame { + FocusFrame { + size: logTextStyle.textSize / 8 + } } - } - GComboBox { - Layout.preferredWidth: plugin.scaleFactor * 350 - model: LogModel.logFileNames + GComboBox { + Layout.preferredWidth: 200 + horizontalPadding: root.horizontalPadding + model: LogModel.logFileNames + radius: root.controlRadius + textStyle: logTextStyle + verticalPadding: root.verticalPadding + + background: GPaneBackground { + border.color: logTextStyle.textColor + border.width: 1 + color: Style.color.transparent + drawShadow: false + radius: root.controlRadius + } - onCurrentIndexChanged: LogModel.setLogFile(currentIndex) + onCurrentIndexChanged: LogModel.setLogFile(currentIndex) + } } - GText { - activeFocusOnTab: true - text: qsTr("Font size:") + ColumnLayout { + GText { + activeFocusOnTab: true + //: LABEL DESKTOP + text: qsTr("Zoom:") + textStyle: logTextStyle - FocusFrame { + FocusFrame { + size: logTextStyle.textSize / 8 + } } - } - SpinBox { - id: fontSize + SpinBox { + id: zoomBox - from: 8 - to: 20 - value: 12 + from: 50 + stepSize: 10 + textFromValue: function (value) { + return value + " %"; + } + to: 200 + value: 100 + } } - GButton { + LogButton { id: filterButton property bool filter: false @@ -72,18 +106,16 @@ Rectangle { icon.source: filter ? "qrc:///images/filter_off.svg" : "qrc:///images/filter.svg" //: LABEL DESKTOP text: qsTr("Filter") - tintIcon: true onClicked: filter = !filter } Item { Layout.fillWidth: true } - GButton { + LogButton { icon.source: "qrc:///images/desktop/save_icon.svg" //: LABEL DESKTOP text: qsTr("Save log") - tintIcon: true onClicked: { let filenameSuggestion = LogModel.createLogFileName(LogModel.getCurrentLogFileDate()); @@ -106,14 +138,15 @@ Rectangle { } GSeparator { Layout.fillWidth: true - Layout.leftMargin: Constants.groupbox_spacing - Layout.rightMargin: Constants.groupbox_spacing + Layout.leftMargin: root.spacing + Layout.rightMargin: root.spacing + implicitHeight: 1 visible: filterButton.filter } RowLayout { Layout.fillWidth: true - Layout.margins: Constants.groupbox_spacing - spacing: Constants.groupbox_spacing + Layout.margins: root.spacing + spacing: root.spacing visible: filterButton.filter GText { @@ -122,8 +155,10 @@ Rectangle { //: LABEL DESKTOP text: qsTr("Select level:") + textStyle: logTextStyle FocusFrame { + size: logTextStyle.textSize / 8 } } Repeater { @@ -132,7 +167,10 @@ Rectangle { delegate: GCheckBox { Layout.fillWidth: true checked: filterModel.selectedLevels.indexOf(text) !== -1 + horizontalPadding: 0 text: modelData + textStyle: logTextStyle + verticalPadding: 0 onCheckedChanged: filterModel.configureLevel(text, checked) } @@ -140,14 +178,15 @@ Rectangle { } GSeparator { Layout.fillWidth: true - Layout.leftMargin: Constants.groupbox_spacing - Layout.rightMargin: Constants.groupbox_spacing + Layout.leftMargin: root.spacing + Layout.rightMargin: root.spacing + implicitHeight: 1 visible: filterButton.filter } RowLayout { Layout.fillWidth: true - Layout.margins: Constants.groupbox_spacing - spacing: Constants.groupbox_spacing + Layout.margins: root.spacing + spacing: root.spacing visible: filterButton.filter GText { @@ -156,15 +195,17 @@ Rectangle { //: LABEL DESKTOP text: qsTr("Select category:") + textStyle: logTextStyle FocusFrame { + size: logTextStyle.textSize / 8 } } GridLayout { Layout.fillWidth: true - columnSpacing: Constants.groupbox_spacing + columnSpacing: root.spacing columns: (width + columnSpacing) / (repeater.maxItemWidth + columnSpacing) - rowSpacing: Constants.groupbox_spacing + rowSpacing: root.spacing GRepeater { id: repeater @@ -174,7 +215,10 @@ Rectangle { delegate: GCheckBox { Layout.fillWidth: true checked: filterModel.selectedCategories.indexOf(text) !== -1 + horizontalPadding: 0 text: modelData + textStyle: logTextStyle + verticalPadding: 0 onCheckedChanged: filterModel.configureCategory(text, checked) } @@ -183,25 +227,32 @@ Rectangle { } GSeparator { Layout.fillWidth: true - Layout.leftMargin: Constants.groupbox_spacing - Layout.rightMargin: Constants.groupbox_spacing + Layout.leftMargin: root.spacing + Layout.rightMargin: root.spacing + implicitHeight: 1 } GListView { id: listView - Layout.bottomMargin: Constants.groupbox_spacing + Layout.bottomMargin: root.spacing Layout.fillHeight: true Layout.fillWidth: true - Layout.leftMargin: Constants.groupbox_spacing - Layout.topMargin: Constants.groupbox_spacing + Layout.leftMargin: root.spacing + Layout.topMargin: root.spacing activeFocusOnTab: true clip: true model: filterModel - scrollBarEnabled: true + ScrollBar.vertical: GScrollBar { + borderWidth: 1 + bottomPadding: 0 + implicitWidth: 6 + leftPadding + rightPadding + rightPadding: 3 + topPadding: 0 + } delegate: LogViewDelegate { - font.pixelSize: fontSize.value - width: listView.width - Constants.groupbox_spacing + font.pixelSize: 0.12 * zoomBox.value + width: listView.width - root.spacing } Connections { @@ -221,11 +272,31 @@ Rectangle { anchors { fill: parent - rightMargin: Constants.groupbox_spacing + rightMargin: root.spacing } FocusFrame { + size: logTextStyle.textSize / 8 } } } } + + component LogButton: GButton { + Layout.alignment: Qt.AlignBottom + Layout.minimumWidth: -1 + borderWidth: 1 + horizontalPadding: root.horizontalPadding + radius: root.controlRadius + spacing: root.spacing + tintIcon: true + verticalPadding: root.verticalPadding + + textStyle: LogTextStyle { + textColor: Style.color.control.content.basic + } + } + component LogTextStyle: TextStyle { + lineHeight: 16 + textSize: 16 + } } diff --git a/src/ui/qml/modules/FeedbackView/+desktop/LogView.qml b/src/ui/qml/modules/FeedbackView/+desktop/LogView.qml new file mode 100644 index 000000000..f18296f60 --- /dev/null +++ b/src/ui/qml/modules/FeedbackView/+desktop/LogView.qml @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.Type + +SectionPage { + id: root + + signal keyPressed(int key) + + titleBarAction: TitleBarAction { + //: LABEL DESKTOP + text: qsTr("Logs") + } + + Keys.onPressed: event => { + keyPressed(event.key); + } + + TabbedPane { + id: tabbedPane + + anchors.fill: parent + contentDelegate: logContentDelegate + contentRightMargin: 0 + sectionsModel: LogModel.logFileNames + + footerItem: ColumnLayout { + spacing: Constants.groupbox_spacing + + GButton { + id: saveLog + + Layout.maximumWidth: Number.POSITIVE_INFINITY + enabled: tabbedPane.sectionsModel.length > 0 + icon.source: "qrc:///images/desktop/save_icon.svg" + //: LABEL DESKTOP + text: qsTr("Save log") + tintIcon: true + + onClicked: { + let filenameSuggestion = LogModel.createLogFileName(LogModel.getCurrentLogFileDate()); + fileDialog.selectFile(filenameSuggestion); + } + + GFileDialog { + id: fileDialog + + defaultSuffix: "log" + //: LABEL DESKTOP + nameFilters: qsTr("Logfiles (*.log)") + + //: LABEL DESKTOP + title: qsTr("Save log") + + onAccepted: LogModel.saveCurrentLogFile(file) + } + } + GButton { + Layout.maximumWidth: Number.POSITIVE_INFINITY + disabledTooltipText: qsTr("The current log will be automatically deleted at exit.") + enableButton: tabbedPane.sectionsModel.length > 1 + icon.source: "qrc:///images/trash_icon.svg" + //: LABEL DESKTOP + text: qsTr("Delete all logs") + tintIcon: true + + onClicked: confirmationPopup.open() + } + GButton { + property QtObject detachedLogViewItem: null + + Layout.maximumWidth: Number.POSITIVE_INFINITY + icon.source: "qrc:///images/desktop/material_open_in_browser.svg" + text: qsTr("Detach log viewer") + tintIcon: true + + onClicked: ApplicationWindow.window.showDetachedLogView() + } + } + + onCurrentIndexChanged: LogModel.setLogFile(currentIndex) + } + Component { + id: logContentDelegate + + GListView { + id: logView + + activeFocusOnTab: true + displayMarginBeginning: Constants.pane_padding + displayMarginEnd: Constants.pane_padding + implicitHeight: tabbedPane.availableHeight + model: LogModel + + delegate: FocusScope { + readonly property bool isFirstItem: index === 0 + readonly property bool isLastItem: index === ListView.view.count - 1 + + implicitHeight: logDelegate.implicitHeight + logDelegate.anchors.topMargin + logDelegate.anchors.bottomMargin + width: logView.width - Constants.pane_padding + + RoundedRectangle { + anchors.fill: parent + bottomLeftCorner: isLastItem + bottomRightCorner: isLastItem + color: Style.color.pane.background.basic + topLeftCorner: isFirstItem + topRightCorner: isFirstItem + } + LogViewDelegate { + id: logDelegate + + focus: true + + anchors { + bottomMargin: isLastItem ? Constants.pane_padding : 0 + fill: parent + leftMargin: Constants.pane_padding + rightMargin: Constants.pane_padding + topMargin: isFirstItem ? Constants.pane_padding : Constants.text_spacing + } + } + } + + layer { + enabled: GraphicsInfo.api !== GraphicsInfo.Software + + effect: GDropShadow { + } + } + Connections { + function onFireNewLogMsg() { + if (logView.atYEnd) + logView.positionViewAtEnd(); + } + + target: LogModel + } + Connections { + function onKeyPressed(pKey) { + logView.handleKeyPress(pKey); + } + + target: root + } + } + } + ConfirmationPopup { + id: confirmationPopup + + //: LABEL DESKTOP + okButtonText: qsTr("Delete") + //: INFO DESKTOP All logfiles are about to be removed, user confirmation required. + text: qsTr("All old logs will be deleted.") + //: LABEL DESKTOP + title: qsTr("Delete all logs") + width: UiPluginModel.scaleFactor * 600 + + onConfirmed: LogModel.removeOtherLogFiles() + } +} diff --git a/resources/qml/Governikus/FeedbackView/+desktop/LogViewDelegate.qml b/src/ui/qml/modules/FeedbackView/+desktop/internal/LogViewDelegate.qml similarity index 69% rename from resources/qml/Governikus/FeedbackView/+desktop/LogViewDelegate.qml rename to src/ui/qml/modules/FeedbackView/+desktop/internal/LogViewDelegate.qml index 661274c31..8e8920159 100644 --- a/resources/qml/Governikus/FeedbackView/+desktop/LogViewDelegate.qml +++ b/src/ui/qml/modules/FeedbackView/+desktop/internal/LogViewDelegate.qml @@ -1,11 +1,11 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type GText { id: root @@ -16,9 +16,11 @@ GText { ApplicationModel.showFeedback(qsTr("The log entry was copied to the clipboard.")); } - color: level === "C" ? Style.color.text_warning : (level === "W" ? Style.color.control : textStyle.textColor) + color: level === "C" ? Style.color.warning : (level === "W" ? Style.color.textSubline.basic : textStyle.textColor) font.bold: activeFocus - font.family: plugin.fixedFontFamily + font.family: UiPluginModel.fixedFontFamily + lineHeight: 1.0 + lineHeightMode: Text.ProportionalHeight text: "%1 %2".arg(origin).arg(message) textFormat: Text.PlainText wrapMode: Text.Wrap diff --git a/resources/qml/Governikus/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml b/src/ui/qml/modules/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml similarity index 84% rename from resources/qml/Governikus/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml rename to src/ui/qml/modules/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml index 10cae5e69..efd764991 100644 --- a/resources/qml/Governikus/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml +++ b/src/ui/qml/modules/FeedbackView/+mobile/+android/StoreFeedbackPopup.qml @@ -1,11 +1,11 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type ConfirmationPopup { //: LABEL ANDROID diff --git a/resources/qml/Governikus/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml b/src/ui/qml/modules/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml similarity index 50% rename from resources/qml/Governikus/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml rename to src/ui/qml/modules/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml index f187c9720..59c23e885 100644 --- a/resources/qml/Governikus/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml +++ b/src/ui/qml/modules/FeedbackView/+mobile/+ios/StoreFeedbackPopup.qml @@ -1,8 +1,8 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick -import Governikus.Type.ApplicationModel +import Governikus.Type Item { function open() { diff --git a/resources/qml/Governikus/Global/+mobile/ListItem.qml b/src/ui/qml/modules/FeedbackView/+mobile/ListItem.qml similarity index 64% rename from resources/qml/Governikus/Global/+mobile/ListItem.qml rename to src/ui/qml/modules/FeedbackView/+mobile/ListItem.qml index 413419f36..36b3139ab 100644 --- a/resources/qml/Governikus/Global/+mobile/ListItem.qml +++ b/src/ui/qml/modules/FeedbackView/+mobile/ListItem.qml @@ -1,39 +1,33 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.Type Rectangle { id: baseItem property real contentMarginLeft: Constants.groupbox_spacing property real contentMarginRight: Constants.groupbox_spacing - property bool fixedHeight: true property alias footerText: footerItem.text property alias headerText: headerItem.text property alias icon: imageItem.source - property string linkIconSource: "qrc:///images/material_arrow_right.svg" property alias mouseAreaEnabled: mouseArea.enabled - property bool pressed: mouseArea.pressed - property bool showLinkIcon: Constants.is_layout_ios property bool showSeparator: true property alias text: textItem.text property alias tintIcon: imageItem.tintEnabled - signal clicked signal pressAndHold Accessible.name: headerText + ". " + text + ". " + footerText Accessible.role: Accessible.ListItem - color: pressed ? Style.color.pane_active : Style.color.pane - height: fixedHeight ? Style.dimens.list_item_height : (content.implicitHeight + Constants.text_spacing) + color: colors.paneBackground + height: content.implicitHeight + Constants.text_spacing width: parent ? parent.width : 0 - Accessible.onPressAction: mouseArea.clicked(null) - GSeparator { anchors.right: parent.right anchors.top: parent.bottom @@ -53,7 +47,7 @@ Rectangle { id: imageItem sourceSize.height: parent.height - 2 * Constants.groupbox_spacing - tintColor: Style.color.text + tintColor: colors.textNormal tintEnabled: false visible: baseItem.icon !== "" } @@ -69,9 +63,9 @@ Rectangle { Accessible.ignored: true Layout.alignment: Qt.AlignLeft - color: baseItem.pressed ? Style.color.text_pressed : Style.color.text_subline + color: colors.textSubline elide: Text.ElideRight - maximumLineCount: fixedHeight ? 1 : 8 + maximumLineCount: 8 visible: baseItem.headerText !== "" } GText { @@ -79,9 +73,9 @@ Rectangle { Accessible.ignored: true Layout.alignment: Qt.AlignLeft - color: baseItem.pressed ? Style.color.text_pressed : Style.color.text + color: colors.textNormal elide: Text.ElideRight - maximumLineCount: fixedHeight ? (headerText === "" ? 2 : 1) : 64 + maximumLineCount: 64 visible: baseItem.text !== "" } GText { @@ -89,25 +83,26 @@ Rectangle { Accessible.ignored: true Layout.alignment: Qt.AlignLeft - color: baseItem.pressed ? Style.color.text_pressed : Style.color.text + color: colors.textNormal elide: Text.ElideRight - maximumLineCount: fixedHeight ? (headerText === "" ? 2 : 1) : 8 + maximumLineCount: 8 visible: baseItem.footerText !== "" } } - TintableIcon { - source: linkIconSource - sourceSize.height: Style.dimens.small_icon_size - tintColor: Style.color.text - visible: showLinkIcon - } } MouseArea { id: mouseArea anchors.fill: parent + hoverEnabled: UiPluginModel.isChromeOS - onClicked: baseItem.clicked() onPressAndHold: baseItem.pressAndHold() } + StatefulColors { + id: colors + + checkedCondition: false + hoveredCondition: mouseArea.containsMouse + statefulControl: mouseArea + } } diff --git a/resources/qml/Governikus/FeedbackView/+mobile/LogView.qml b/src/ui/qml/modules/FeedbackView/+mobile/LogView.qml similarity index 82% rename from resources/qml/Governikus/FeedbackView/+mobile/LogView.qml rename to src/ui/qml/modules/FeedbackView/+mobile/LogView.qml index 3ca4d4e88..6a0150362 100644 --- a/resources/qml/Governikus/FeedbackView/+mobile/LogView.qml +++ b/src/ui/qml/modules/FeedbackView/+mobile/LogView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,9 +8,7 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.LogModel -import Governikus.Type.LogFilterModel -import Governikus.Type.ApplicationModel +import Governikus.Type SectionPage { id: root @@ -24,15 +22,9 @@ SectionPage { onClicked: pop() } rightTitleBarAction: LogTitleBarControls { - allowRemove: comboBox.currentIndex > 0 allowRemoveAll: comboBox.model.length > 1 // comboBox.count doesn't seem to update reliably - onRemove: { - confirmationPopup.deleteAll = false; - confirmationPopup.open(); - } onRemoveAll: { - confirmationPopup.deleteAll = true; confirmationPopup.open(); } onShare: pPopupPosition => { @@ -58,7 +50,7 @@ SectionPage { Layout.fillWidth: true Layout.preferredHeight: comboBox.height + Constants.pane_padding * 2 - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic GComboBox { id: comboBox @@ -85,7 +77,7 @@ SectionPage { Accessible.checked: filter Accessible.name: qsTr("Filter") Accessible.role: Accessible.CheckBox - icon: filter ? "qrc:///images/filter_off.svg" : "qrc:///images/filter.svg" + icon.source: filter ? "qrc:///images/filter_off.svg" : "qrc:///images/filter.svg" iconTintColor: comboBox.textStyle.textColor onClicked: filter = !filter @@ -112,7 +104,6 @@ SectionPage { title: qsTr("Filter") GText { - font.bold: true //: LABEL ANDROID IOS text: qsTr("Level") textStyle: Style.text.subline @@ -138,7 +129,6 @@ SectionPage { } } GText { - font.bold: true //: LABEL ANDROID IOS text: qsTr("Category") textStyle: Style.text.subline @@ -168,6 +158,7 @@ SectionPage { GListView { id: logView + Accessible.ignored: false Layout.fillHeight: true Layout.fillWidth: true clip: true @@ -177,9 +168,7 @@ SectionPage { delegate: ListItem { readonly property bool isLastItem: index === ListView.view.count - 1 - fixedHeight: false headerText: origin - showLinkIcon: false showSeparator: !isLastItem text: message @@ -213,20 +202,13 @@ SectionPage { ConfirmationPopup { id: confirmationPopup - property bool deleteAll: true - //: LABEL ANDROID IOS okButtonText: qsTr("Delete") //: INFO ANDROID IOS All logfiles are about to be removed, user confirmation required. - text: (deleteAll ? qsTr("All old logs will be deleted.") : - //: INFO ANDROID IOS The current logfile is about to be removed, user confirmation required. - qsTr("The log will be deleted.")) - title: (deleteAll ? - //: LABEL ANDROID IOS - qsTr("Delete all logs") : - //: LABEL ANDROID IOS - qsTr("Delete log")) - - onConfirmed: deleteAll ? LogModel.removeOtherLogFiles() : LogModel.removeCurrentLogFile() + text: qsTr("All old logs will be deleted.") + //: LABEL ANDROID IOS + title: qsTr("Delete all logs") + + onConfirmed: LogModel.removeOtherLogFiles() } } diff --git a/resources/qml/Governikus/FeedbackView/+mobile/LogTitleBarControls.qml b/src/ui/qml/modules/FeedbackView/+mobile/internal/LogTitleBarControls.qml similarity index 60% rename from resources/qml/Governikus/FeedbackView/+mobile/LogTitleBarControls.qml rename to src/ui/qml/modules/FeedbackView/+mobile/internal/LogTitleBarControls.qml index d28f74305..0cedb5d3c 100644 --- a/resources/qml/Governikus/FeedbackView/+mobile/LogTitleBarControls.qml +++ b/src/ui/qml/modules/FeedbackView/+mobile/internal/LogTitleBarControls.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -10,10 +10,8 @@ import Governikus.TitleBar Row { id: logControls - property alias allowRemove: removeButton.visible property alias allowRemoveAll: removeAllButton.visible - signal remove signal removeAll signal share(point popupPosition) @@ -21,23 +19,15 @@ Row { TitleBarAction { Accessible.name: qsTr("Share log") - icon: "qrc:///images/mobile/share.svg" + icon.source: "qrc:///images/mobile/share.svg" onClicked: logControls.share(mapToGlobal(width / 2, height)) } - TitleBarAction { - id: removeButton - - Accessible.name: qsTr("Delete log") - icon: "qrc:///images/trash_icon.svg" - - onClicked: logControls.remove() - } TitleBarAction { id: removeAllButton Accessible.name: qsTr("Delete all logs") - icon: "qrc:///images/trash_icon_old.svg" + icon.source: "qrc:///images/trash_icon.svg" onClicked: logControls.removeAll() } diff --git a/src/ui/qml/modules/Global/+6.5/GDropShadow.qml b/src/ui/qml/modules/Global/+6.5/GDropShadow.qml new file mode 100644 index 000000000..555220baf --- /dev/null +++ b/src/ui/qml/modules/Global/+6.5/GDropShadow.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +ShaderEffect { + property bool autoPaddingEnabled + property rect paddingRect + property real shadowOpacity + property real shadowScale + property real shadowVerticalOffset +} diff --git a/resources/qml/Governikus/Global/+desktop/ConfirmationPopup.qml b/src/ui/qml/modules/Global/+desktop/ConfirmationPopup.qml similarity index 68% rename from resources/qml/Governikus/Global/+desktop/ConfirmationPopup.qml rename to src/ui/qml/modules/Global/+desktop/ConfirmationPopup.qml index 4e479fbc7..d7f840e9e 100644 --- a/resources/qml/Governikus/Global/+desktop/ConfirmationPopup.qml +++ b/src/ui/qml/modules/Global/+desktop/ConfirmationPopup.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -17,13 +17,13 @@ BaseConfirmationPopup { GButton { text: root.okButtonText - visible: style & ConfirmationPopup.PopupStyle.OkButton + visible: root.style & ConfirmationPopup.PopupStyle.OkButton onClicked: root.accept() } GButton { text: root.cancelButtonText - visible: style & ConfirmationPopup.PopupStyle.CancelButton + visible: root.style & ConfirmationPopup.PopupStyle.CancelButton onClicked: root.cancel() } diff --git a/resources/qml/Governikus/Global/+desktop/DecisionView.qml b/src/ui/qml/modules/Global/+desktop/DecisionView.qml similarity index 84% rename from resources/qml/Governikus/Global/+desktop/DecisionView.qml rename to src/ui/qml/modules/Global/+desktop/DecisionView.qml index c095b6a78..22444b42c 100644 --- a/resources/qml/Governikus/Global/+desktop/DecisionView.qml +++ b/src/ui/qml/modules/Global/+desktop/DecisionView.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type SectionPage { id: baseItem @@ -17,17 +17,14 @@ SectionPage { DisagreeButton } - property alias agreeButton: agreeButton - property alias agreeText: agreeButton.subText - property alias disagreeButton: disagreeButton - property alias disagreeText: disagreeButton.subText + readonly property alias agreeButton: agreeButton + readonly property alias disagreeButton: disagreeButton property alias mainIconSource: image.source property alias moreInformationText: moreInformation.text property alias moreInformationVisible: moreInformation.visible property alias questionSubText: subTextElement.text property alias questionText: mainTextElement.text property int style: DecisionView.ButtonStyle.AgreeButton | DecisionView.ButtonStyle.DisagreeButton - property alias tintEnabled: image.tintEnabled signal agree signal disagree @@ -47,7 +44,7 @@ SectionPage { Layout.topMargin: Constants.pane_padding source: "qrc:///images/info.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image } GText { id: mainTextElement @@ -103,10 +100,9 @@ SectionPage { activeFocusOnTab: true buttonType: NavigationButton.Type.Cancel - size: Style.dimens.huge_icon_size //: LABEL DESKTOP - subText: qsTr("No") + text: qsTr("No") visible: style & DecisionView.ButtonStyle.DisagreeButton onClicked: baseItem.disagree() @@ -116,10 +112,9 @@ SectionPage { activeFocusOnTab: true buttonType: NavigationButton.Type.Check - size: Style.dimens.huge_icon_size //: LABEL DESKTOP - subText: qsTr("Yes") + text: qsTr("Yes") visible: style & DecisionView.ButtonStyle.AgreeButton onClicked: baseItem.agree() diff --git a/resources/qml/Governikus/Global/+desktop/GFileDialog.qml b/src/ui/qml/modules/Global/+desktop/GFileDialog.qml similarity index 84% rename from resources/qml/Governikus/Global/+desktop/GFileDialog.qml rename to src/ui/qml/modules/Global/+desktop/GFileDialog.qml index c25107d1f..785763e48 100644 --- a/resources/qml/Governikus/Global/+desktop/GFileDialog.qml +++ b/src/ui/qml/modules/Global/+desktop/GFileDialog.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Qt.labs.platform as Labs diff --git a/resources/qml/Governikus/MoreView/+desktop/MoreViewMenuItem.qml b/src/ui/qml/modules/Global/+desktop/GMenuItem.qml similarity index 82% rename from resources/qml/Governikus/MoreView/+desktop/MoreViewMenuItem.qml rename to src/ui/qml/modules/Global/+desktop/GMenuItem.qml index 39a9e77f5..ff4731ca9 100644 --- a/resources/qml/Governikus/MoreView/+desktop/MoreViewMenuItem.qml +++ b/src/ui/qml/modules/Global/+desktop/GMenuItem.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -24,7 +24,7 @@ RowLayout { id: icon sourceSize.width: Style.dimens.icon_size - tintColor: Style.color.text_subline + tintColor: Style.color.textSubline.basic } LabeledText { id: labeledText @@ -34,7 +34,6 @@ RowLayout { GButton { id: button - iconSize: Style.dimens.small_icon_size tintIcon: true onClicked: baseItem.clicked() diff --git a/resources/qml/Governikus/Global/+desktop/GPane.qml b/src/ui/qml/modules/Global/+desktop/GPane.qml similarity index 54% rename from resources/qml/Governikus/Global/+desktop/GPane.qml rename to src/ui/qml/modules/Global/+desktop/GPane.qml index d72ea36f0..12eaa5b46 100644 --- a/resources/qml/Governikus/Global/+desktop/GPane.qml +++ b/src/ui/qml/modules/Global/+desktop/GPane.qml @@ -1,18 +1,19 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts +import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type GPaneBackground { id: root property alias content: paneContent + property int contentPadding: Constants.pane_padding default property alias data: paneContent.data - property bool drawShadow: true property alias spacing: paneContent.spacing property alias title: titleText.text property alias titleTextStyle: titleText.textStyle @@ -20,34 +21,27 @@ GPaneBackground { Accessible.focusable: title !== "" Accessible.name: title Accessible.role: Accessible.Grouping + Layout.maximumHeight: containerCol.Layout.maximumHeight activeFocusOnTab: title !== "" implicitHeight: containerCol.implicitHeight implicitWidth: containerCol.implicitWidth - layer { - enabled: GraphicsInfo.api !== GraphicsInfo.Software && drawShadow - - effect: GDropShadow { - } - } - Column { + ColumnLayout { id: containerCol - anchors.left: parent.left - anchors.leftMargin: Constants.pane_padding - anchors.right: parent.right - anchors.rightMargin: Constants.pane_padding - bottomPadding: Constants.pane_padding - spacing: Constants.pane_spacing - topPadding: Constants.pane_padding + anchors.fill: parent + spacing: 0 GText { id: titleText + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + Layout.topMargin: Constants.pane_padding elide: Text.ElideRight maximumLineCount: 1 textStyle: Style.text.subline - width: Math.min(parent.width, Math.ceil(implicitWidth)) + visible: text !== "" FocusFrame { scope: root @@ -56,8 +50,12 @@ GPaneBackground { ColumnLayout { id: paneContent + Layout.bottomMargin: root.contentPadding + Layout.leftMargin: root.contentPadding + Layout.maximumWidth: Number.POSITIVE_INFINITY + Layout.rightMargin: root.contentPadding + Layout.topMargin: titleText.visible ? Constants.pane_spacing : root.contentPadding spacing: Constants.pane_spacing - width: parent.width } } } diff --git a/resources/qml/Governikus/Global/+desktop/Hint.qml b/src/ui/qml/modules/Global/+desktop/Hint.qml similarity index 81% rename from resources/qml/Governikus/Global/+desktop/Hint.qml rename to src/ui/qml/modules/Global/+desktop/Hint.qml index 8e5f97057..c4fc42969 100644 --- a/resources/qml/Governikus/Global/+desktop/Hint.qml +++ b/src/ui/qml/modules/Global/+desktop/Hint.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -17,11 +17,9 @@ GPane { signal clicked - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic drawShadow: false spacing: 0 - //: LABEL DESKTOP - title: qsTr("Hint") GText { id: hintText @@ -39,7 +37,6 @@ GPane { Layout.alignment: Qt.AlignHCenter Layout.topMargin: Constants.component_spacing icon.source: "qrc:///images/open_website.svg" - iconSize: Style.dimens.small_icon_size tintIcon: hintText.color visible: text !== "" diff --git a/resources/qml/Governikus/Global/+desktop/LocationButton.qml b/src/ui/qml/modules/Global/+desktop/LocationButton.qml similarity index 57% rename from resources/qml/Governikus/Global/+desktop/LocationButton.qml rename to src/ui/qml/modules/Global/+desktop/LocationButton.qml index ad31089ef..7488d8a85 100644 --- a/resources/qml/Governikus/Global/+desktop/LocationButton.qml +++ b/src/ui/qml/modules/Global/+desktop/LocationButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -7,27 +7,28 @@ import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type -GButton { +AbstractButton { id: root property alias image: icon.source property string language - readonly property bool selected: SettingsModel.language === language Accessible.checkable: true - Accessible.checked: selected + Accessible.checked: checked Layout.maximumWidth: Number.POSITIVE_INFINITY - cursorShape: selected ? Qt.ArrowCursor : Qt.PointingHandCursor + checked: SettingsModel.language === language padding: Constants.groupbox_spacing - background: RoundedRectangle { - color: root.selected ? Style.color.pane_active : Style.color.pane + background: GPaneBackground { + id: pane + + border.color: colors.paneBorder + color: colors.paneBackground + drawShadow: false FocusFrame { - borderColor: Style.color.control_border marginFactor: 0.8 radius: parent.radius * 1.2 scope: root @@ -43,11 +44,20 @@ GButton { sourceSize.height: Style.dimens.icon_size } GText { + id: description + Layout.alignment: Qt.AlignHCenter - color: selected ? Style.color.control_content : Style.color.text + color: colors.textNormal text: root.text } } onClicked: SettingsModel.language = language + + StatefulColors { + id: colors + + groupMember: true + statefulControl: root + } } diff --git a/src/ui/qml/modules/Global/+desktop/NavigationButton.qml b/src/ui/qml/modules/Global/+desktop/NavigationButton.qml new file mode 100644 index 000000000..02f8c9ccb --- /dev/null +++ b/src/ui/qml/modules/Global/+desktop/NavigationButton.qml @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +AbstractButton { + id: control + + enum Type { + Forward, + Check, + Cancel + } + + property int buttonType: NavigationButton.Type.Forward + property double size: Style.dimens.huge_icon_size + + icon.source: buttonType === NavigationButton.Type.Check ? "qrc:///images/material_check.svg" : buttonType === NavigationButton.Type.Cancel ? "qrc:///images/material_clear.svg" : "qrc:///images/desktop/material_arrow_forward.svg" + + background: Item { + } + contentItem: Column { + spacing: Constants.text_spacing + + Rectangle { + id: circle + + anchors.horizontalCenter: parent.horizontalCenter + border.color: Style.color.control.border.basic + border.width: Style.dimens.border_width + color: Style.color.control.background.basic + implicitHeight: control.size + implicitWidth: control.size + radius: height / 2 + + TintableIcon { + id: icon + + anchors.centerIn: parent + source: control.icon.source + sourceSize.height: Style.dimens.large_icon_size + tintColor: Style.color.control.content.basic + } + FocusFrame { + marginFactor: 0.8 + radius: parent.radius * 1.2 + scope: control + } + } + GText { + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + text: control.text + textStyle: Style.text.subline + visible: text !== "" + } + } + + Item { + id: d + + states: [ + State { + name: "disabled" + when: !control.enabled + + PropertyChanges { + circle.border.color: Style.color.control.border.disabled + circle.color: Style.color.control.background.disabled + icon.tintColor: Style.color.control.content.disabled + } + }, + State { + name: "pressed" + when: control.pressed + + PropertyChanges { + circle.border.color: Style.color.control.border.pressed + circle.color: Style.color.control.background.pressed + icon.tintColor: Style.color.control.content.pressed + } + }, + State { + name: "hovered" + when: control.hovered + + PropertyChanges { + circle.border.color: Style.color.control.border.hovered + circle.color: Style.color.control.background.hovered + icon.tintColor: Style.color.control.content.hovered + } + } + ] + } +} diff --git a/resources/qml/Governikus/Global/+desktop/ScrollGradients.qml b/src/ui/qml/modules/Global/+desktop/ScrollGradients.qml similarity index 94% rename from resources/qml/Governikus/Global/+desktop/ScrollGradients.qml rename to src/ui/qml/modules/Global/+desktop/ScrollGradients.qml index 5a0c304fa..4c0fa93a7 100644 --- a/resources/qml/Governikus/Global/+desktop/ScrollGradients.qml +++ b/src/ui/qml/modules/Global/+desktop/ScrollGradients.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global diff --git a/resources/qml/Governikus/Global/+desktop/TabbedPane.qml b/src/ui/qml/modules/Global/+desktop/TabbedPane.qml similarity index 69% rename from resources/qml/Governikus/Global/+desktop/TabbedPane.qml rename to src/ui/qml/modules/Global/+desktop/TabbedPane.qml index a91d83d10..e76de4028 100644 --- a/resources/qml/Governikus/Global/+desktop/TabbedPane.qml +++ b/src/ui/qml/modules/Global/+desktop/TabbedPane.qml @@ -1,13 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.View Item { @@ -21,6 +20,7 @@ Item { property alias currentIndex: sectionNameList.currentIndex readonly property var currentItemModel: sectionNameList.currentItem ? sectionNameList.currentItem.itemModel : null property Component footerItem: null + property int highlightedIndex: -1 readonly property real relativeListViewWidth: 0.3 property alias sectionCount: sectionNameList.count property var sectionsModel: undefined @@ -87,7 +87,7 @@ Item { Loader { Layout.alignment: Qt.AlignLeft Layout.fillWidth: true - Layout.preferredHeight: status === Loader.Ready ? item.height : 0 + Layout.preferredHeight: status === Loader.Ready ? item.implicitHeight : 0 sourceComponent: footerItem } } @@ -134,27 +134,43 @@ Item { Item { id: delegateItem - readonly property bool isCurrentItem: ListView.isCurrentItem + //: LABEL DESKTOP %1 is the current selected Page of %2 Pages + readonly property string a11yPageIndicator: qsTr("%1 of %2").arg(index + 1).arg(ListView.view.count) readonly property bool isFirstItem: index === 0 readonly property bool isLastItem: index === ListView.view.count - 1 - readonly property bool isPreviousToCurrentItem: index === ListView.view.currentIndex - 1 readonly property var itemModel: model + readonly property bool nextItemIsHighlighted: index === ListView.view.currentIndex - 1 || index === root.highlightedIndex - 1 + Accessible.description: Qt.platform.os === "windows" ? a11yPageIndicator : "" Accessible.focusable: true - Accessible.name: sectionName.text - Accessible.role: Accessible.Button + Accessible.name: { + if (Qt.platform.os === "windows") { + return sectionName.text; + } + //: LABEL DESKTOP + return sectionName.text + ", " + qsTr("Tab selected") + ", " + a11yPageIndicator; + } + Accessible.role: Accessible.PageTab activeFocusOnTab: false height: sectionName.height + 2 * Constants.pane_padding width: sectionNameList.width - RoundedRectangle { - id: background + StatefulColors { + id: colors + checkedCondition: delegateItem.ListView.isCurrentItem + disabledCondition: false + groupMember: true + hoveredCondition: mouseArea.containsMouse + pressedCondition: mouseArea.pressed + statefulControl: delegateItem + } + RoundedRectangle { anchors.fill: parent - borderColor: Style.color.pane_border + borderColor: colors.paneBorder bottomLeftCorner: isLastItem bottomRightCorner: isLastItem - color: isCurrentItem ? Style.color.control : Style.color.pane + color: colors.paneBackground radius: Style.dimens.pane_radius topLeftCorner: isFirstItem topRightCorner: isFirstItem @@ -162,7 +178,7 @@ Item { GText { id: sectionName - color: isCurrentItem ? Style.color.control_content : Style.color.text + color: colors.textNormal elide: Text.ElideRight maximumLineCount: 2 text: model.display ? model.display : model.modelData @@ -179,7 +195,34 @@ Item { GSeparator { id: horizontalSeparator - visible: !isLastItem && !isCurrentItem && !isPreviousToCurrentItem + visible: !isLastItem && !nextItemIsHighlighted && GraphicsInfo.api !== GraphicsInfo.Software + + states: [ + State { + name: "active" + when: delegateItem.ListView.isCurrentItem + + PropertyChanges { + horizontalSeparator.visible: false + } + }, + State { + name: "pressed" + when: mouseArea.pressed + + PropertyChanges { + horizontalSeparator.visible: false + } + }, + State { + name: "hovered" + when: mouseArea.containsMouse + + PropertyChanges { + horizontalSeparator.visible: false + } + } + ] anchors { bottom: parent.bottom @@ -194,13 +237,27 @@ Item { framee: sectionName } MouseArea { + id: mouseArea + + function updateHighlight() { + if (containsMouse || pressed) { + root.highlightedIndex = index; + } else { + if (root.highlightedIndex === index) { + root.highlightedIndex = -1; + } + } + } + anchors.fill: parent - cursorShape: index === currentIndex ? Qt.ArrowCursor : Qt.PointingHandCursor + hoverEnabled: true onClicked: { delegateItem.ListView.view.itemAtIndex(index).forceActiveFocus(Qt.MouseFocusReason); delegateItem.ListView.view.currentIndex = index; } + onContainsMouseChanged: updateHighlight() + onPressedChanged: updateHighlight() } } } diff --git a/src/ui/qml/modules/Global/+desktop/internal/PlatformConstants.qml b/src/ui/qml/modules/Global/+desktop/internal/PlatformConstants.qml new file mode 100644 index 000000000..1f33dc923 --- /dev/null +++ b/src/ui/qml/modules/Global/+desktop/internal/PlatformConstants.qml @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Type + +Item { + readonly property int component_spacing: UiPluginModel.scaleFactor * 30 + readonly property int control_horizontalPadding: UiPluginModel.scaleFactor * 30 + readonly property int control_verticalPadding: UiPluginModel.scaleFactor * 10 + readonly property int groupbox_spacing: UiPluginModel.scaleFactor * 20 + readonly property bool is_desktop: true + readonly property int pane_border_highlight_width: UiPluginModel.scaleFactor * 4 + readonly property int pane_padding: UiPluginModel.scaleFactor * 30 + readonly property int pane_spacing: UiPluginModel.scaleFactor * 30 + readonly property int subtext_spacing: Math.max(1, UiPluginModel.scaleFactor * 3) + readonly property int text_spacing: UiPluginModel.scaleFactor * 10 +} diff --git a/src/ui/qml/modules/Global/+mobile/+android/ConfirmationPopup.qml b/src/ui/qml/modules/Global/+mobile/+android/ConfirmationPopup.qml new file mode 100644 index 000000000..b521c88e2 --- /dev/null +++ b/src/ui/qml/modules/Global/+mobile/+android/ConfirmationPopup.qml @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import Governikus.Global + +BaseConfirmationPopup { + id: root + + buttons: Flow { + layoutDirection: Qt.RightToLeft + spacing: 0 + width: parent.width + + GLink { + text: root.okButtonText + visible: root.style & ConfirmationPopup.PopupStyle.OkButton + + onClicked: root.accept() + } + GLink { + text: root.cancelButtonText + visible: root.style & ConfirmationPopup.PopupStyle.CancelButton + + onClicked: root.cancel() + } + } +} diff --git a/resources/qml/Governikus/Global/+mobile/+android/BrandConstants.qml b/src/ui/qml/modules/Global/+mobile/+android/internal/BrandConstants.qml similarity index 73% rename from resources/qml/Governikus/Global/+mobile/+android/BrandConstants.qml rename to src/ui/qml/modules/Global/+mobile/+android/internal/BrandConstants.qml index 990b7a8d4..54f123bf8 100644 --- a/resources/qml/Governikus/Global/+mobile/+android/BrandConstants.qml +++ b/src/ui/qml/modules/Global/+mobile/+android/internal/BrandConstants.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/src/ui/qml/modules/Global/+mobile/+ios/ConfirmationPopup.qml b/src/ui/qml/modules/Global/+mobile/+ios/ConfirmationPopup.qml new file mode 100644 index 000000000..5d997c842 --- /dev/null +++ b/src/ui/qml/modules/Global/+mobile/+ios/ConfirmationPopup.qml @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global + +BaseConfirmationPopup { + id: root + + horizontalTextAlignment: Text.AlignHCenter + + buttons: ColumnLayout { + spacing: 0 + width: parent.width + + GSeparator { + Layout.fillWidth: true + visible: root.style !== ConfirmationPopup.PopupStyle.NoButtons + } + RowLayout { + spacing: 0 + + GLink { + Layout.maximumWidth: Number.POSITIVE_INFINITY + implicitWidth: 1 + text: root.cancelButtonText + visible: root.style & ConfirmationPopup.PopupStyle.CancelButton + + onClicked: root.cancel() + } + GSeparator { + Layout.fillHeight: true + orientation: Qt.Vertical + visible: root.style & ConfirmationPopup.PopupStyle.CancelButton && root.style & ConfirmationPopup.PopupStyle.OkButton + } + GLink { + Layout.maximumWidth: Number.POSITIVE_INFINITY + implicitWidth: 1 + text: root.okButtonText + visible: root.style & ConfirmationPopup.PopupStyle.OkButton + + onClicked: root.accept() + } + } + } +} diff --git a/resources/qml/Governikus/Global/+mobile/+ios/BrandConstants.qml b/src/ui/qml/modules/Global/+mobile/+ios/internal/BrandConstants.qml similarity index 73% rename from resources/qml/Governikus/Global/+mobile/+ios/BrandConstants.qml rename to src/ui/qml/modules/Global/+mobile/+ios/internal/BrandConstants.qml index 2a2e04d68..f600d7fbe 100644 --- a/resources/qml/Governikus/Global/+mobile/+ios/BrandConstants.qml +++ b/src/ui/qml/modules/Global/+mobile/+ios/internal/BrandConstants.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/Global/+mobile/GCollapsibleSubButton.qml b/src/ui/qml/modules/Global/+mobile/GCollapsibleSubButton.qml similarity index 50% rename from resources/qml/Governikus/Global/+mobile/GCollapsibleSubButton.qml rename to src/ui/qml/modules/Global/+mobile/GCollapsibleSubButton.qml index 3ed9b4b18..47662f9a2 100644 --- a/resources/qml/Governikus/Global/+mobile/GCollapsibleSubButton.qml +++ b/src/ui/qml/modules/Global/+mobile/GCollapsibleSubButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -7,8 +7,7 @@ import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type AbstractButton { id: root @@ -17,18 +16,13 @@ AbstractButton { property alias tintIcon: icon.tintEnabled property alias title: label.text - implicitHeight: layout.implicitHeight + Constants.component_spacing - implicitWidth: layout.implicitWidth + 2 * Constants.component_spacing + horizontalPadding: Constants.component_spacing * 2 + verticalPadding: Constants.component_spacing / 2 background: Rectangle { - color: root.pressed ? Style.color.control_content_pressed : Style.color.transparent + color: colors.paneBackground } contentItem: RowLayout { - id: layout - - anchors.left: parent.left - anchors.leftMargin: Constants.component_spacing * 2 - anchors.verticalCenter: parent.verticalCenter spacing: Constants.component_spacing TintableIcon { @@ -41,8 +35,19 @@ AbstractButton { GText { id: label + Accessible.ignored: true Layout.maximumWidth: Number.POSITIVE_INFINITY - color: root.pressed ? Style.color.control_content_hover : Style.color.text + color: colors.textNormal } } + + StatefulColors { + id: colors + + paneStyle: Style.color.paneSublevel + statefulControl: root + } + FocusFrame { + marginFactor: -1 + } } diff --git a/src/ui/qml/modules/Global/+mobile/GMenuItem.qml b/src/ui/qml/modules/Global/+mobile/GMenuItem.qml new file mode 100644 index 000000000..0b63609e9 --- /dev/null +++ b/src/ui/qml/modules/Global/+mobile/GMenuItem.qml @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +AbstractButton { + id: root + + property alias description: descriptionText.text + property bool drawBottomCorners: false + property bool drawTopCorners: false + property alias tintIcon: iconItem.tintEnabled + property alias title: titleText.text + + Accessible.name: title + ". " + description + Accessible.role: Accessible.Button + icon.source: "qrc:///images/material_arrow_right.svg" + padding: Constants.pane_padding + + background: RoundedRectangle { + bottomLeftCorner: root.drawBottomCorners + bottomRightCorner: root.drawBottomCorners + color: colors.paneBackground + topLeftCorner: root.drawTopCorners + topRightCorner: root.drawTopCorners + + FocusFrame { + anchors.margins: Constants.component_spacing / 2 + scope: root + } + } + contentItem: RowLayout { + id: layout + + anchors.margins: Constants.pane_padding + spacing: 0 + + ColumnLayout { + Layout.maximumWidth: Number.POSITIVE_INFINITY + + GText { + id: titleText + + Accessible.ignored: true + textStyle: Style.text.subline + visible: text !== "" + } + GText { + id: descriptionText + + Accessible.ignored: true + visible: text !== "" + } + } + TintableIcon { + id: iconItem + + Accessible.ignored: true + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + source: root.icon.source + sourceSize.height: Style.dimens.small_icon_size + } + } + + StatefulColors { + id: colors + + statefulControl: root + } +} diff --git a/resources/qml/Governikus/Global/+mobile/GOptionsContainer.qml b/src/ui/qml/modules/Global/+mobile/GOptionsContainer.qml similarity index 83% rename from resources/qml/Governikus/Global/+mobile/GOptionsContainer.qml rename to src/ui/qml/modules/Global/+mobile/GOptionsContainer.qml index 2d2dc07b2..d58b9e461 100644 --- a/resources/qml/Governikus/Global/+mobile/GOptionsContainer.qml +++ b/src/ui/qml/modules/Global/+mobile/GOptionsContainer.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick @@ -26,7 +26,7 @@ ColumnLayout { id: pane Layout.fillWidth: true - color: Style.color.pane + color: Style.color.pane.background.basic padding: 0 spacing: 0 } diff --git a/resources/qml/Governikus/Global/+mobile/GPane.qml b/src/ui/qml/modules/Global/+mobile/GPane.qml similarity index 52% rename from resources/qml/Governikus/Global/+mobile/GPane.qml rename to src/ui/qml/modules/Global/+mobile/GPane.qml index 40288eff4..4ca340750 100644 --- a/resources/qml/Governikus/Global/+mobile/GPane.qml +++ b/src/ui/qml/modules/Global/+mobile/GPane.qml @@ -1,16 +1,15 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style +import QtQuick.Layouts GPaneBackground { id: root - property alias bold: titleText.font.bold property alias contentSpacing: paneContent.spacing - property bool drawShadow: true property alias horizontalTitleAlignment: titleText.horizontalAlignment property int padding: Constants.pane_padding default property alias paneData: paneContent.data @@ -18,36 +17,28 @@ GPaneBackground { property alias textStyle: titleText.textStyle property alias title: titleText.text - height: childrenRect.height - implicitHeight: content.implicitHeight + implicitHeight: content.implicitHeight + 2 * padding + implicitWidth: content.implicitWidth + 2 * padding - Column { + ColumnLayout { id: content - anchors.left: parent.left - anchors.leftMargin: root.padding - anchors.right: parent.right - anchors.rightMargin: root.padding - bottomPadding: root.padding spacing: root.spacing - topPadding: root.padding + anchors { + fill: parent + margins: root.padding + } PaneTitle { id: titleText - width: parent.width + Layout.fillWidth: true } Column { id: paneContent + Layout.fillWidth: true spacing: root.spacing - width: parent.width - } - } - layer { - enabled: GraphicsInfo.api !== GraphicsInfo.Software && drawShadow - - effect: GDropShadow { } } } diff --git a/resources/qml/Governikus/Global/+mobile/Hint.qml b/src/ui/qml/modules/Global/+mobile/Hint.qml similarity index 73% rename from resources/qml/Governikus/Global/+mobile/Hint.qml rename to src/ui/qml/modules/Global/+mobile/Hint.qml index 6af6bb4c0..3e9584613 100644 --- a/resources/qml/Governikus/Global/+mobile/Hint.qml +++ b/src/ui/qml/modules/Global/+mobile/Hint.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -15,13 +15,11 @@ GPane { property alias text: hintText.text signal clicked + signal receivedFocus(var pItem) - bold: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic drawShadow: false textStyle: Style.text.subline - //: LABEL ANDROID IOS - title: qsTr("Hint") ColumnLayout { spacing: 0 @@ -30,11 +28,7 @@ GPane { GText { id: hintText - activeFocusOnTab: true visible: text !== "" - - FocusFrame { - } } GButton { id: hintButton @@ -42,11 +36,12 @@ GPane { Layout.alignment: Qt.AlignHCenter Layout.topMargin: Constants.groupbox_spacing icon.source: "qrc:///images/open_website.svg" - iconSize: Style.dimens.navigation_bar_icon_size tintIcon: hintText.color visible: text !== "" onClicked: root.clicked() + onFocusChanged: if (focus) + root.receivedFocus(this) } } } diff --git a/resources/qml/Governikus/Global/+mobile/IosBackGestureMouseArea.qml b/src/ui/qml/modules/Global/+mobile/IosBackGestureMouseArea.qml similarity index 93% rename from resources/qml/Governikus/Global/+mobile/IosBackGestureMouseArea.qml rename to src/ui/qml/modules/Global/+mobile/IosBackGestureMouseArea.qml index 81c27dba8..a0fbb2759 100644 --- a/resources/qml/Governikus/Global/+mobile/IosBackGestureMouseArea.qml +++ b/src/ui/qml/modules/Global/+mobile/IosBackGestureMouseArea.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/Global/+mobile/PaneTitle.qml b/src/ui/qml/modules/Global/+mobile/PaneTitle.qml similarity index 76% rename from resources/qml/Governikus/Global/+mobile/PaneTitle.qml rename to src/ui/qml/modules/Global/+mobile/PaneTitle.qml index da0c8de18..44ec4aaa6 100644 --- a/resources/qml/Governikus/Global/+mobile/PaneTitle.qml +++ b/src/ui/qml/modules/Global/+mobile/PaneTitle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style diff --git a/resources/qml/Governikus/Global/+mobile/PlatformConstants.qml b/src/ui/qml/modules/Global/+mobile/PlatformConstants.qml similarity index 60% rename from resources/qml/Governikus/Global/+mobile/PlatformConstants.qml rename to src/ui/qml/modules/Global/+mobile/PlatformConstants.qml index 2d13e8de7..286a4cda3 100644 --- a/resources/qml/Governikus/Global/+mobile/PlatformConstants.qml +++ b/src/ui/qml/modules/Global/+mobile/PlatformConstants.qml @@ -1,12 +1,15 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick BrandConstants { readonly property int component_spacing: 20 + readonly property int control_horizontalPadding: 20 + readonly property int control_verticalPadding: 6 readonly property int groupbox_spacing: 10 readonly property bool is_desktop: false + readonly property int pane_border_highlight_width: 3 readonly property int pane_padding: 20 readonly property int pane_spacing: 20 readonly property int subtext_spacing: 2 diff --git a/resources/qml/Governikus/Global/+mobile/TitledSeparator.qml b/src/ui/qml/modules/Global/+mobile/TitledSeparator.qml similarity index 93% rename from resources/qml/Governikus/Global/+mobile/TitledSeparator.qml rename to src/ui/qml/modules/Global/+mobile/TitledSeparator.qml index 1e186c458..a0d67a558 100644 --- a/resources/qml/Governikus/Global/+mobile/TitledSeparator.qml +++ b/src/ui/qml/modules/Global/+mobile/TitledSeparator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts diff --git a/resources/qml/Governikus/Global/Constants.qml b/src/ui/qml/modules/Global/Constants.qml similarity index 79% rename from resources/qml/Governikus/Global/Constants.qml rename to src/ui/qml/modules/Global/Constants.qml index 5b1b80eb0..1abaa479a 100644 --- a/resources/qml/Governikus/Global/Constants.qml +++ b/src/ui/qml/modules/Global/Constants.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ pragma Singleton import QtQuick @@ -8,12 +8,11 @@ PlatformConstants { readonly property int animation_duration: 250 readonly property color black: "#000000" readonly property color blue: "#164a8c" + readonly property int eased_in_pressed_duration: 150 readonly property var flickDeceleration: Constants.is_desktop ? 7500.0 : 1500.0 readonly property color green: "#327509" - readonly property color grey: "#8e8e93" readonly property real highlightDarkerFactor: 1.3 readonly property int maximumDeviceNameLength: 33 - readonly property color red: "#9d0100" readonly property double scrolling_speed: 7500.0 readonly property int toolTipDelay: 500 readonly property color white: "#ffffff" diff --git a/resources/qml/Governikus/Global/Crossed.qml b/src/ui/qml/modules/Global/Crossed.qml similarity index 88% rename from resources/qml/Governikus/Global/Crossed.qml rename to src/ui/qml/modules/Global/Crossed.qml index 4479deab0..c72fa8c1a 100644 --- a/resources/qml/Governikus/Global/Crossed.qml +++ b/src/ui/qml/modules/Global/Crossed.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style @@ -58,14 +58,14 @@ Item { anchors.bottomMargin: d.gap anchors.left: parent.left anchors.leftMargin: d.gap - source: "qrc:///images/desktop/warning.svg" + source: "qrc:///images/status_warning.svg" sourceSize.height: Style.dimens.huge_icon_size - 10 - tintColor: Style.color.text_warning + tintColor: Style.color.warning } component Line: Rectangle { antialiasing: true - color: Style.color.text_warning + color: Style.color.warning height: Style.dimens.separator_size_large width: d.c } diff --git a/src/ui/qml/modules/Global/EaseInPressedTransition.qml b/src/ui/qml/modules/Global/EaseInPressedTransition.qml new file mode 100644 index 000000000..18805eb11 --- /dev/null +++ b/src/ui/qml/modules/Global/EaseInPressedTransition.qml @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick + +Transition { + property alias target: animation.target + property alias targets: animation.targets + + to: "pressed" + + ColorAnimation { + id: animation + + duration: Constants.eased_in_pressed_duration + easing.type: Easing.InCubic + } +} diff --git a/src/ui/qml/modules/Global/FadeInAnimation.qml b/src/ui/qml/modules/Global/FadeInAnimation.qml new file mode 100644 index 000000000..4938914b7 --- /dev/null +++ b/src/ui/qml/modules/Global/FadeInAnimation.qml @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global + +Item { + id: root + + required property QtObject target + + states: [ + State { + name: "visible" + when: root.target.visible + + PropertyChanges { + opacity: 1.0 + target: root.target + } + }, + State { + name: "invisible" + when: !root.target.visible + + PropertyChanges { + opacity: 0.0 + target: root.target + } + } + ] + transitions: [ + Transition { + from: "invisible" + to: "visible" + + PropertyAnimation { + duration: Constants.animation_duration * 4 + easing.type: Easing.OutCubic + property: "opacity" + target: root.target + to: 1 + } + } + ] +} diff --git a/src/ui/qml/modules/Global/FormattedTextView.qml b/src/ui/qml/modules/Global/FormattedTextView.qml new file mode 100644 index 000000000..9404ea75b --- /dev/null +++ b/src/ui/qml/modules/Global/FormattedTextView.qml @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.View +import Governikus.Style +import Governikus.Type + +Item { + id: root + + property alias color: delegate.color + property alias idx: delegate.idx + property var lineType + property real maximumContentWidth: Number.POSITIVE_INFINITY + property alias text: contentText.text + property alias totalItemCount: delegate.count + + Accessible.ignored: contentText.text === "" + Accessible.name: ApplicationModel.stripHtmlTags(contentText.text) + Accessible.role: { + switch (root.lineType) { + case FormattedTextModel.LineType.HEADER: + return Accessible.Heading; + case FormattedTextModel.LineType.SECTION: + case FormattedTextModel.LineType.SUBSECTION: + return Accessible.Section; + case FormattedTextModel.LineType.LISTITEM: + return Accessible.ListItem; + default: + return Accessible.StaticText; + } + } + implicitHeight: delegate.implicitHeight + z: 0 + + GPaneBackgroundDelegate { + id: delegate + + anchors.centerIn: parent + anchors.horizontalCenterOffset: -Constants.pane_padding / 2 + implicitHeight: row.implicitHeight + width: Math.min(root.width - Constants.pane_padding, root.maximumContentWidth) + + RowLayout { + id: row + + readonly property int horizontalPadding: Constants.pane_padding + + anchors.fill: parent + + GText { + id: prefix + + Accessible.ignored: true + Layout.fillHeight: true + fontSizeMode: Text.Fit + leftPadding: row.horizontalPadding + text: "•" + textStyle: contentText.textStyle + verticalAlignment: Text.AlignTop + visible: root.lineType === FormattedTextModel.LineType.LISTITEM + } + GText { + id: contentText + + Accessible.ignored: true + Layout.maximumWidth: Number.POSITIVE_INFINITY + bottomPadding: delegate.isLast ? Constants.pane_padding : 0 + font.underline: lineType === FormattedTextModel.LineType.SECTION + leftPadding: prefix.visible ? 0 : row.horizontalPadding + rightPadding: row.horizontalPadding + textStyle: { + switch (root.lineType) { + case FormattedTextModel.LineType.HEADER: + return Style.text.title; + case FormattedTextModel.LineType.SECTION: + return Style.text.headline; + case FormattedTextModel.LineType.SUBSECTION: + return Style.text.subline; + default: + return Style.text.normal; + } + } + topPadding: delegate.isFirst ? Constants.pane_padding : 0 + } + } + } +} diff --git a/resources/qml/Governikus/Global/GBusyIndicator.qml b/src/ui/qml/modules/Global/GBusyIndicator.qml similarity index 94% rename from resources/qml/Governikus/Global/GBusyIndicator.qml rename to src/ui/qml/modules/Global/GBusyIndicator.qml index 75f98c882..8f814b558 100644 --- a/resources/qml/Governikus/Global/GBusyIndicator.qml +++ b/src/ui/qml/modules/Global/GBusyIndicator.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type BusyIndicator { id: root diff --git a/src/ui/qml/modules/Global/GButton.qml b/src/ui/qml/modules/Global/GButton.qml new file mode 100644 index 000000000..e9fd32e8e --- /dev/null +++ b/src/ui/qml/modules/Global/GButton.qml @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +AbstractButton { + id: root + + property int borderWidth: Style.dimens.border_width + property alias buttonColor: colors.controlBackground + property alias cursorShape: mouseArea.cursorShape + property string disabledTooltipText + + // Similar to "enabled", but tooltips will continue to work + property bool enableButton: true + property string enabledTooltipText + property alias iconSize: buttonIcon.sourceSize.height + property alias layoutDirection: contentLayout.layoutDirection + property alias maximumLineCount: buttonText.maximumLineCount + property real radius: Style.dimens.control_radius + property alias style: colors.controlStyle + property TextStyle textStyle: Style.text.button + property bool tintIcon: false + + Accessible.name: text + Layout.fillWidth: true + Layout.maximumWidth: Math.ceil(implicitWidth) + Layout.minimumWidth: background ? Style.dimens.min_button_width : -1 + ToolTip.delay: Constants.toolTipDelay + ToolTip.text: enableButton ? enabledTooltipText : disabledTooltipText + ToolTip.visible: hovered && ToolTip.text !== "" + activeFocusOnTab: enableButton + font.pixelSize: textStyle.textSize + font.weight: textStyle.fontWeight + horizontalPadding: Constants.control_horizontalPadding + spacing: Constants.groupbox_spacing + verticalPadding: Constants.control_verticalPadding + + background: Rectangle { + border.color: colors.controlBorder + border.width: root.borderWidth + color: colors.controlBackground + radius: root.radius + } + contentItem: RowLayout { + RowLayout { + id: contentLayout + + Layout.maximumWidth: Number.POSITIVE_INFINITY + Layout.minimumHeight: root.font.pixelSize + topPadding + bottomPadding + Layout.minimumWidth: background ? root.Layout.minimumWidth - leftPadding - rightPadding : -1 + spacing: root.spacing + z: 1 + + TintableIcon { + id: buttonIcon + + source: root.icon.source + sourceSize.height: 1.2 * buttonText.effectiveFirstLineHeight + tintColor: colors.controlContent + tintEnabled: tintIcon + visible: source != "" + } + GText { + id: buttonText + + Accessible.ignored: true + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: Number.POSITIVE_INFINITY + color: colors.controlContent + elide: Text.ElideRight + font: root.font + horizontalAlignment: { + if (!buttonIcon.visible) { + return Text.AlignHCenter; + } + return layoutDirection === Qt.LeftToRight ? Text.AlignLeft : Text.AlignRight; + } + lineHeight: root.textStyle.lineHeight + maximumLineCount: 1 + text: root.text + visible: text !== "" + } + } + } + + onActiveFocusOnTabChanged: if (!activeFocusOnTab) + focus = false + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + controlBorder: controlBackground === controlStyle.background.basic ? controlStyle.border.basic : controlBackground + disabledCondition: !root.enableButton || !root.enabled + hoveredCondition: hoverHandler.hovered + statefulControl: root + } + FocusFrame { + marginFactor: root.background ? 0.8 : 1 + radius: root.background ? (1.2 * root.radius) : Math.min(height / 4, Style.dimens.control_radius) + size: root.font.pixelSize / 8 + } + MouseArea { + id: mouseArea + + anchors.fill: parent + z: 2 + + onPressed: mouse => { + mouse.accepted = !enableButton; + } + } +} diff --git a/src/ui/qml/modules/Global/GCheckBox.qml b/src/ui/qml/modules/Global/GCheckBox.qml new file mode 100644 index 000000000..6658e0b00 --- /dev/null +++ b/src/ui/qml/modules/Global/GCheckBox.qml @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +CheckBox { + id: control + + property alias focusFrameVisible: focusFrame.visible + property alias layoutDirection: contentLayout.layoutDirection + property alias maximumLineCount: description.maximumLineCount + readonly property color preferredBackgroundColor: colors.controlPreferredPaneBackground + property alias textStyle: description.textStyle + + horizontalPadding: Constants.component_spacing + indicator: null + verticalPadding: Constants.component_spacing / 2 + + contentItem: RowLayout { + id: contentLayout + + readonly property int focusWidth: layoutDirection === Qt.RightToLeft ? width : implicitWidth + + spacing: control.spacing + + Rectangle { + border.color: colors.controlBorder + border.width: Math.max(checkmark.implicitHeight / 16, 1) + color: colors.controlBackground + implicitHeight: checkmark.implicitHeight + 4 * border.width + implicitWidth: implicitHeight + radius: Math.max(height / 6, 1) + + TintableIcon { + id: checkmark + + anchors.centerIn: parent + source: "qrc:///images/checkbox_indicator.svg" + sourceSize.height: 1.2 * description.font.pixelSize + tintColor: colors.controlContent + visible: control.checked + } + } + GText { + id: description + + Accessible.ignored: true + Layout.maximumWidth: Number.POSITIVE_INFINITY + elide: Text.ElideRight + maximumLineCount: 1 + text: control.text + visible: text !== "" + } + } + + Accessible.onPressAction: { + toggle(); + toggled(); + } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + controlStyle: Style.color.controlCheckbox + hoveredCondition: hoverHandler.hovered + statefulControl: control + } + FocusFrame { + id: focusFrame + + size: textStyle.textSize / 8 + } +} diff --git a/resources/qml/Governikus/Global/GCollapsible.qml b/src/ui/qml/modules/Global/GCollapsible.qml similarity index 65% rename from resources/qml/Governikus/Global/GCollapsible.qml rename to src/ui/qml/modules/Global/GCollapsible.qml index d64f488c1..6817c4fc3 100644 --- a/resources/qml/Governikus/Global/GCollapsible.qml +++ b/src/ui/qml/modules/Global/GCollapsible.qml @@ -1,18 +1,21 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.View ColumnLayout { id: root - property bool alwaysReserveSelectionTitleHight: false - property alias backgroundColor: background.color + property bool alwaysReserveSelectionTitleHeight: false + property bool arrowToLeft: false + property alias backgroundColor: collapsibleContentBackground.color property int contentBottomMargin: Constants.groupbox_spacing + property int contentHorizontalMargin: horizontalMargin property alias contentSpacing: contentItem.spacing property int contentTopMargin: Constants.groupbox_spacing property bool drawBottomCorners: false @@ -25,6 +28,8 @@ ColumnLayout { property alias tintIcon: selectionIcon.tintEnabled property alias title: title.text + signal receivedFocus(var pItem) + spacing: 0 AbstractButton { @@ -43,11 +48,18 @@ ColumnLayout { implicitWidth: bannerLayout.implicitWidth background: RoundedRectangle { + id: background + bottomLeftCorner: drawBottomCorners && !expanded bottomRightCorner: drawBottomCorners && !expanded - color: expandButton.pressed ? Style.color.pane_active : Style.color.transparent + color: colors.paneBackground topLeftCorner: drawTopCorners topRightCorner: drawTopCorners + + FocusFrame { + anchors.margins: Constants.component_spacing / 2 + scope: expandButton + } } contentItem: RowLayout { id: bannerLayout @@ -57,15 +69,18 @@ ColumnLayout { anchors.verticalCenter: parent.verticalCenter spacing: 0 + LeftRightArrow { + isLeft: root.arrowToLeft + visible: root.arrowToLeft + } ColumnLayout { - Layout.leftMargin: horizontalMargin + Layout.leftMargin: root.arrowToLeft ? 0 : root.horizontalMargin spacing: Constants.subtext_spacing GText { id: title Accessible.ignored: true - color: expandButton.pressed ? Style.color.text_subline_pressed : textStyle.textColor textStyle: Style.text.subline visible: text !== "" } @@ -73,8 +88,7 @@ ColumnLayout { id: selectionTitle Accessible.ignored: true - color: expandButton.pressed ? Style.color.text_pressed : textStyle.textColor - visible: alwaysReserveSelectionTitleHight || text !== "" + visible: alwaysReserveSelectionTitleHeight || text !== "" Behavior on text { SequentialAnimation { @@ -106,40 +120,41 @@ ColumnLayout { TintableIcon { id: selectionIcon - Layout.maximumHeight: Style.dimens.small_icon_size - Layout.maximumWidth: Math.ceil(paintedWidth) - Layout.preferredHeight: Style.dimens.small_icon_size - tintColor: arrow.tintColor + Layout.rightMargin: root.arrowToLeft ? root.horizontalMargin : 0 + sourceSize.height: Style.dimens.small_icon_size + tintColor: Style.color.textNormal.basic tintEnabled: false + visible: source.toString() !== "" } - TintableIcon { - id: arrow - - Layout.maximumHeight: Style.dimens.small_icon_size - Layout.maximumWidth: Layout.maximumHeight - Layout.preferredHeight: Style.dimens.small_icon_size - Layout.preferredWidth: Layout.preferredHeight - Layout.rightMargin: horizontalMargin - source: expanded ? "qrc:///images/material_expand_less.svg" : "qrc:///images/material_expand_more.svg" - tintColor: expandButton.pressed ? Style.color.text_pressed : Style.color.text - tintEnabled: true + LeftRightArrow { + isLeft: root.arrowToLeft + visible: !root.arrowToLeft } } onClicked: expanded = !expanded + onFocusChanged: if (focus) + root.receivedFocus(this) + + StatefulColors { + id: colors + + statefulControl: expandButton + } } RoundedRectangle { - id: background + id: collapsibleContentBackground Layout.fillWidth: true bottomLeftCorner: drawBottomCorners bottomRightCorner: drawBottomCorners clip: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic implicitHeight: expanded ? (contentItem.implicitHeight + contentItem.anchors.topMargin + contentItem.anchors.bottomMargin) : 0 implicitWidth: contentItem.implicitWidth + contentItem.anchors.leftMargin + contentItem.anchors.rightMargin topLeftCorner: false topRightCorner: false + visible: expanded Behavior on implicitHeight { NumberAnimation { @@ -155,10 +170,21 @@ ColumnLayout { anchors { bottomMargin: contentBottomMargin fill: parent - leftMargin: root.horizontalMargin - rightMargin: root.horizontalMargin + leftMargin: contentHorizontalMargin + rightMargin: contentHorizontalMargin topMargin: contentTopMargin } } } + + component LeftRightArrow: TintableIcon { + property bool isLeft: false + + Layout.leftMargin: isLeft ? root.horizontalMargin : Constants.text_spacing + Layout.rightMargin: isLeft ? Constants.text_spacing : root.horizontalMargin + source: expanded ? "qrc:///images/material_expand_less.svg" : "qrc:///images/material_expand_more.svg" + sourceSize.height: Style.text.normal.textSize + tintColor: Style.color.textNormal.basic + tintEnabled: true + } } diff --git a/src/ui/qml/modules/Global/GComboBox.qml b/src/ui/qml/modules/Global/GComboBox.qml new file mode 100644 index 000000000..541e67758 --- /dev/null +++ b/src/ui/qml/modules/Global/GComboBox.qml @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import Governikus.View +import Governikus.Style +import Governikus.Type + +ComboBox { + id: control + + property int radius: Style.dimens.pane_radius + property TextStyle textStyle: Style.text.normal + + Accessible.name: displayText + Accessible.role: Accessible.ComboBox + font.pixelSize: textStyle.textSize + horizontalPadding: Constants.control_horizontalPadding + leftPadding: horizontalPadding + popup.bottomMargin: UiPluginModel.safeAreaMargins.bottom + popup.leftMargin: UiPluginModel.safeAreaMargins.left + popup.rightMargin: UiPluginModel.safeAreaMargins.right + popup.topMargin: UiPluginModel.safeAreaMargins.top + rightPadding: horizontalPadding + spacing: Constants.groupbox_spacing + verticalPadding: Constants.control_verticalPadding + + background: GPaneBackground { + border.color: control.textStyle.textColor + color: Style.color.transparent + drawShadow: false + radius: control.radius + } + contentItem: GText { + elide: Text.ElideRight + font.pixelSize: control.font.pixelSize + maximumLineCount: 1 + rightPadding: control.indicator.width + control.spacing + text: control.displayText + textStyle: control.textStyle + } + delegate: ItemDelegate { + highlighted: control.highlightedIndex === index + width: control.width + + background: Rectangle { + color: highlighted ? Style.color.control.background.basic : Style.color.paneSublevel.background.basic + + GSeparator { + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } + } + contentItem: GText { + color: highlighted ? Style.color.control.content.hovered : control.textStyle.textColor + elide: Text.ElideRight + font.pixelSize: control.font.pixelSize + text: modelData + textStyle: control.textStyle + } + } + indicator: Item { + TintableIcon { + source: down ? "qrc:///images/material_expand_less.svg" : "qrc:///images/material_expand_more.svg" + sourceSize.height: control.font.pixelSize + tintColor: control.textStyle.textColor + x: Math.round(control.width - width - control.rightPadding) + y: Math.round(control.topPadding + (control.availableHeight - height) / 2) + } + } + + FocusFrame { + marginFactor: 1 + radius: 1.2 * control.radius + size: control.font.pixelSize / 8 + } +} diff --git a/resources/qml/Governikus/Global/GConicalGradient.qml b/src/ui/qml/modules/Global/GConicalGradient.qml similarity index 94% rename from resources/qml/Governikus/Global/GConicalGradient.qml rename to src/ui/qml/modules/Global/GConicalGradient.qml index 8a20aca1f..9991a3dab 100644 --- a/resources/qml/Governikus/Global/GConicalGradient.qml +++ b/src/ui/qml/modules/Global/GConicalGradient.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/src/ui/qml/modules/Global/GCrossBlendedText.qml b/src/ui/qml/modules/Global/GCrossBlendedText.qml new file mode 100644 index 000000000..09cf922c7 --- /dev/null +++ b/src/ui/qml/modules/Global/GCrossBlendedText.qml @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.Type + +Item { + id: root + + property alias color: mainText.color + property alias elide: mainText.elide + property alias font: mainText.font + property alias horizontalAlignment: mainText.horizontalAlignment + property alias lineHeight: mainText.lineHeight + property alias maximumLineCount: mainText.maximumLineCount + property alias text: mainText.text + property alias textStyle: mainText.textStyle + property alias wrapMode: mainText.wrapMode + + Accessible.ignored: text === "" + Accessible.name: mainText.Accessible.name + Accessible.role: mainText.Accessible.role + Layout.fillWidth: true + Layout.maximumWidth: Style.dimens.max_text_width + implicitHeight: Math.max(mainText.implicitHeight, tempText.implicitHeight) + implicitWidth: Math.max(mainText.implicitWidth, tempText.implicitWidth) + + Behavior on implicitHeight { + enabled: SettingsModel.useAnimations && !Constants.is_desktop + + NumberAnimation { + duration: mainText.text === "" ? 0 : Constants.animation_duration + } + } + + GText { + id: mainText + + Accessible.ignored: true + anchors.fill: parent + + Behavior on text { + enabled: SettingsModel.useAnimations && !Constants.is_desktop + + SequentialAnimation { + PropertyAction { + property: "text" + target: tempText + value: mainText.text + } + PropertyAction { + property: "text" + target: mainText + } + PropertyAction { + property: "opacity" + target: mainText + value: 0 + } + PropertyAction { + property: "opacity" + target: tempText + value: 1 + } + PropertyAnimation { + duration: mainText.text === "" ? 0 : Constants.animation_duration + easing.type: Easing.OutCubic + property: "opacity" + target: tempText + to: 0 + } + PropertyAnimation { + duration: mainText.text === "" ? Constants.animation_duration * 2 : Constants.animation_duration + easing.type: mainText.text === "" ? Easing.InOutCubic : Easing.InCubic + property: "opacity" + target: mainText + to: 1 + } + PropertyAction { + property: "text" + target: tempText + value: "" + } + } + } + } + GText { + id: tempText + + Accessible.ignored: true + color: mainText.color + elide: mainText.elide + font: mainText.font + horizontalAlignment: mainText.horizontalAlignment + lineHeight: mainText.lineHeight + maximumLineCount: mainText.maximumLineCount + textStyle: mainText.textStyle + wrapMode: mainText.wrapMode + + anchors { + left: parent.left + right: parent.right + top: parent.top + } + } +} diff --git a/src/ui/qml/modules/Global/GDropShadow.qml b/src/ui/qml/modules/Global/GDropShadow.qml new file mode 100644 index 000000000..22d9cbf0a --- /dev/null +++ b/src/ui/qml/modules/Global/GDropShadow.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Effects + +MultiEffect { + shadowEnabled: true + shadowOpacity: 0.15 + shadowScale: 1.025 + shadowVerticalOffset: 7 +} diff --git a/resources/qml/Governikus/Global/GFlickable.qml b/src/ui/qml/modules/Global/GFlickable.qml similarity index 63% rename from resources/qml/Governikus/Global/GFlickable.qml rename to src/ui/qml/modules/Global/GFlickable.qml index 799f2b64b..3ccc05a54 100644 --- a/resources/qml/Governikus/Global/GFlickable.qml +++ b/src/ui/qml/modules/Global/GFlickable.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -9,14 +9,10 @@ import Governikus.Style Flickable { id: baseItem - property real scrollBarBottomPadding: 0 - property bool scrollBarEnabled: true - property real scrollBarTopPadding: 0 - function handleKeyPress(key) { - if (key === Qt.Key_PageDown) + if (key === Qt.Key_PageDown || key === Qt.Key_Down) baseItem.scrollPageDown(); - else if (key === Qt.Key_PageUp) + else if (key === Qt.Key_PageUp || key === Qt.Key_Up) baseItem.scrollPageUp(); else if (key === Qt.Key_End) baseItem.contentY = baseItem.contentHeight - baseItem.height; @@ -30,6 +26,18 @@ Flickable { function positionViewAtBeginning() { contentY = originY; } + function positionViewAtItem(pItem) { + let item = pItem.parent ? pItem.parent : pItem; + let mappedPosition = this.mapFromItem(item, pItem.x, pItem.y); + if (mappedPosition.y < 0) { + contentY = Math.max(0, contentY + mappedPosition.y); + return; + } + let viewDifference = mappedPosition.y + pItem.height - height; + if (viewDifference > 0) { + contentY = Math.min(contentY + viewDifference, contentHeight - height); + } + } function scrollPageDown() { Utils.scrollPageDown(baseItem); } @@ -38,28 +46,24 @@ Flickable { } Accessible.focusable: false + Accessible.ignored: Constants.is_desktop Accessible.role: Accessible.ScrollBar - ScrollBar.vertical: scrollBarEnabled ? scrollBar.createObject() : null boundsBehavior: Constants.is_desktop ? Flickable.StopAtBounds : (contentHeight <= height ? Flickable.StopAtBounds : Flickable.DragAndOvershootBounds) boundsMovement: Flickable.FollowBoundsBehavior flickDeceleration: Constants.flickDeceleration flickableDirection: Flickable.VerticalFlick maximumFlickVelocity: Constants.scrolling_speed + ScrollBar.vertical: GScrollBar { + } + Accessible.onDecreaseAction: scrollPageUp() Accessible.onIncreaseAction: scrollPageDown() + Accessible.onScrollDownAction: scrollPageDown() + Accessible.onScrollUpAction: scrollPageUp() Keys.onPressed: event => { handleKeyPress(event.key); } onVisibleChanged: if (visible) highlightScrollbar() - - Component { - id: scrollBar - - GScrollBar { - bottomPadding: baseItem.scrollBarBottomPadding + Style.dimens.scrollbar_padding_vertical - topPadding: baseItem.scrollBarTopPadding + Style.dimens.scrollbar_padding_vertical - } - } } diff --git a/resources/qml/Governikus/Global/GFlickableColumnLayout.qml b/src/ui/qml/modules/Global/GFlickableColumnLayout.qml similarity index 93% rename from resources/qml/Governikus/Global/GFlickableColumnLayout.qml rename to src/ui/qml/modules/Global/GFlickableColumnLayout.qml index 724730429..4da0553c7 100644 --- a/resources/qml/Governikus/Global/GFlickableColumnLayout.qml +++ b/src/ui/qml/modules/Global/GFlickableColumnLayout.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts diff --git a/src/ui/qml/modules/Global/GInformativeButton.qml b/src/ui/qml/modules/Global/GInformativeButton.qml new file mode 100644 index 000000000..27c60dd3a --- /dev/null +++ b/src/ui/qml/modules/Global/GInformativeButton.qml @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Style +import Governikus.View + +AbstractButton { + id: root + + property alias description: descriptionText.text + + Accessible.name: root.text + ". " + root.description + horizontalPadding: Constants.component_spacing + verticalPadding: Constants.component_spacing + + background: GPaneBackground { + id: pane + + border.color: colors.paneBorder + color: colors.paneBackground + + FocusFrame { + marginFactor: 0.8 + radius: parent.radius * 1.2 + scope: root + } + } + contentItem: RowLayout { + id: rowLayout + + spacing: Constants.component_spacing + + TintableIcon { + source: root.icon.source + sourceSize.height: Constants.is_desktop ? Style.dimens.icon_size : Style.dimens.small_icon_size + tintColor: title.color + } + ColumnLayout { + Layout.maximumWidth: Number.POSITIVE_INFINITY + spacing: Constants.text_spacing / 2 + + GText { + id: title + + Accessible.ignored: true + elide: Text.ElideRight + text: root.text + textStyle: Style.text.subline + } + GText { + id: descriptionText + + Accessible.ignored: true + elide: Text.ElideRight + } + } + TintableIcon { + source: "qrc:///images/material_arrow_right.svg" + sourceSize.height: Constants.is_desktop ? Style.dimens.icon_size : Style.dimens.small_icon_size + tintColor: descriptionText.color + } + } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + hoveredCondition: hoverHandler.hovered + statefulControl: root + } +} diff --git a/src/ui/qml/modules/Global/GLink.qml b/src/ui/qml/modules/Global/GLink.qml new file mode 100644 index 000000000..e34b3aec9 --- /dev/null +++ b/src/ui/qml/modules/Global/GLink.qml @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +AbstractButton { + id: root + + property alias colorStyle: colors.linkStyle + property alias cursorShape: mouseArea.cursorShape + property alias iconSize: linkIcon.sourceSize.height + property alias iconTintColor: linkIcon.tintColor + property alias layoutDirection: contentLayout.layoutDirection + property alias maximumLineCount: linkText.maximumLineCount + property alias textStyle: linkText.textStyle + property alias tintIcon: linkIcon.tintEnabled + + Accessible.name: text + Layout.fillWidth: true + Layout.maximumWidth: Math.ceil(implicitWidth) + activeFocusOnTab: true + background: null + font.pixelSize: linkText.textStyle.textSize + font.weight: linkText.textStyle.fontWeight + horizontalPadding: Constants.control_horizontalPadding + verticalPadding: Constants.control_verticalPadding + + contentItem: RowLayout { + RowLayout { + id: contentLayout + + Layout.maximumWidth: Number.POSITIVE_INFINITY + Layout.minimumHeight: root.font.pixelSize + topPadding + bottomPadding + spacing: Constants.groupbox_spacing + z: 1 + + TintableIcon { + id: linkIcon + + source: root.icon.source + sourceSize.height: 1.2 * linkText.effectiveFirstLineHeight + tintColor: colors.linkColor + tintEnabled: true + visible: root.icon.source != "" + + Behavior on source { + enabled: SettingsModel.useAnimations && !Constants.is_desktop + + SequentialAnimation { + PropertyAction { + property: "opacity" + target: linkIcon + value: 0 + } + PropertyAction { + property: "source" + target: linkIcon + } + PropertyAnimation { + duration: Constants.animation_duration * 2 + easing.type: Easing.InCubic + property: "opacity" + target: linkIcon + to: 1 + } + } + } + } + GCrossBlendedText { + id: linkText + + Accessible.ignored: true + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: Number.POSITIVE_INFINITY + color: colors.linkColor + elide: Text.ElideRight + font: root.font + horizontalAlignment: { + if (!linkIcon.visible) { + return Text.AlignHCenter; + } + return layoutDirection === Qt.LeftToRight ? Text.AlignLeft : Text.AlignRight; + } + lineHeight: root.textStyle.lineHeight + maximumLineCount: 1 + text: root.text + textStyle: Style.text.link + visible: text !== "" + } + } + } + + onActiveFocusOnTabChanged: if (!activeFocusOnTab) + focus = false + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + statefulControl: root + } + FocusFrame { + } + MouseArea { + id: mouseArea + + anchors.fill: parent + z: 2 + + onPressed: mouse => { + mouse.accepted = false; + } + } +} diff --git a/resources/qml/Governikus/Global/GListView.qml b/src/ui/qml/modules/Global/GListView.qml similarity index 68% rename from resources/qml/Governikus/Global/GListView.qml rename to src/ui/qml/modules/Global/GListView.qml index ab7621e1f..5aa1158c9 100644 --- a/resources/qml/Governikus/Global/GListView.qml +++ b/src/ui/qml/modules/Global/GListView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -11,8 +11,7 @@ ListView { property bool scrollBarAutohide: !Constants.is_desktop property real scrollBarBottomPadding: 0 - property color scrollBarColor: Style.color.control - property bool scrollBarEnabled: true + property alias scrollBarColor: scrollbar.color property real scrollBarTopPadding: 0 function handleKeyPress(key) { @@ -32,35 +31,38 @@ ListView { function scrollPageDown() { Utils.scrollPageDown(baseItem); } + function scrollPageLeft() { + Utils.scrollPageLeft(baseItem); + } + function scrollPageRight() { + Utils.scrollPageRight(baseItem); + } function scrollPageUp() { Utils.scrollPageUp(baseItem); } - Accessible.focusable: false - Accessible.role: Accessible.ScrollBar - ScrollBar.vertical: scrollBarEnabled ? scrollBar.createObject() : null + Accessible.ignored: true boundsBehavior: Constants.is_desktop ? Flickable.StopAtBounds : (contentHeight <= height ? Flickable.StopAtBounds : Flickable.DragAndOvershootBounds) boundsMovement: Flickable.FollowBoundsBehavior flickDeceleration: Constants.flickDeceleration flickableDirection: Flickable.VerticalFlick maximumFlickVelocity: Constants.scrolling_speed + ScrollBar.vertical: GScrollBar { + id: scrollbar + + autohide: scrollBarAutohide + bottomPadding: baseItem.scrollBarBottomPadding + Style.dimens.scrollbar_padding_vertical + topPadding: baseItem.scrollBarTopPadding + Style.dimens.scrollbar_padding_vertical + } + Accessible.onDecreaseAction: scrollPageUp() Accessible.onIncreaseAction: scrollPageDown() + Accessible.onScrollDownAction: scrollPageDown() + Accessible.onScrollUpAction: scrollPageUp() Keys.onPressed: event => { handleKeyPress(event.key); } onVisibleChanged: if (visible) highlightScrollbar() - - Component { - id: scrollBar - - GScrollBar { - autohide: scrollBarAutohide - bottomPadding: baseItem.scrollBarBottomPadding + Style.dimens.scrollbar_padding_vertical - color: baseItem.scrollBarColor - topPadding: baseItem.scrollBarTopPadding + Style.dimens.scrollbar_padding_vertical - } - } } diff --git a/src/ui/qml/modules/Global/GPaneBackground.qml b/src/ui/qml/modules/Global/GPaneBackground.qml new file mode 100644 index 000000000..b9e27ce69 --- /dev/null +++ b/src/ui/qml/modules/Global/GPaneBackground.qml @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Style + +Rectangle { + id: root + + property bool drawShadow: true + property real shadowScale: 1.025 + + border.color: Style.color.pane.border.basic + border.width: Style.dimens.border_width + color: Style.color.pane.background.basic + radius: Style.dimens.pane_radius + + layer { + enabled: GraphicsInfo.api !== GraphicsInfo.Software && drawShadow + + effect: GDropShadow { + shadowScale: root.shadowScale + } + } +} diff --git a/resources/qml/Governikus/Global/GPaneBackgroundDelegate.qml b/src/ui/qml/modules/Global/GPaneBackgroundDelegate.qml similarity index 81% rename from resources/qml/Governikus/Global/GPaneBackgroundDelegate.qml rename to src/ui/qml/modules/Global/GPaneBackgroundDelegate.qml index 14d1d7a2c..e0151f3aa 100644 --- a/resources/qml/Governikus/Global/GPaneBackgroundDelegate.qml +++ b/src/ui/qml/modules/Global/GPaneBackgroundDelegate.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -14,7 +14,7 @@ RoundedRectangle { bottomLeftCorner: isLast || isOnlyElement bottomRightCorner: isLast || isOnlyElement - color: Style.color.pane + color: Style.color.pane.background.basic topLeftCorner: isFirst || isOnlyElement topRightCorner: isFirst || isOnlyElement } diff --git a/resources/qml/Governikus/Global/GProgressBar.qml b/src/ui/qml/modules/Global/GProgressBar.qml similarity index 59% rename from resources/qml/Governikus/Global/GProgressBar.qml rename to src/ui/qml/modules/Global/GProgressBar.qml index e6e67ef9b..c20fcf5d9 100644 --- a/resources/qml/Governikus/Global/GProgressBar.qml +++ b/src/ui/qml/modules/Global/GProgressBar.qml @@ -1,51 +1,51 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style +import Governikus.Type import Governikus.View ProgressBar { id: progressBar - property color backgroundColor: Style.color.background + readonly property alias effectiveVisualPosition: bar.mutableVisualPosition property alias text: progressText.text Accessible.name: qsTr("%1 percent done").arg(value) Accessible.role: Accessible.ProgressBar + background: null from: 0 to: 100 - background: Rectangle { - border.color: Style.color.control_border + contentItem: Rectangle { + border.color: Style.color.control.border.basic border.width: Style.dimens.progress_bar_border - color: Style.color.transparent - radius: height / 2 - } - contentItem: Item { + color: Style.color.background implicitHeight: Style.dimens.progress_bar_height + radius: height / 2 Item { anchors.fill: parent anchors.margins: Style.dimens.progress_bar_border * 3 Rectangle { - color: progressBar.backgroundColor - height: parent.height - radius: height / 2 - width: parent.width - } - Rectangle { - property real mutableVisualPosition: visualPosition + id: bar - color: Style.color.control + property real mutableVisualPosition: SettingsModel.useAnimations || visualPosition === 1 ? visualPosition : 0.25 + + border.color: Style.color.control.border.basic + border.width: Style.dimens.border_width + color: Style.color.control.background.basic height: parent.height radius: height / 2 width: parent.width * mutableVisualPosition Behavior on mutableVisualPosition { + enabled: SettingsModel.useAnimations + SmoothedAnimation { velocity: 0.5 } @@ -55,7 +55,9 @@ ProgressBar { GText { id: progressText + color: Style.color.progressbar_text elide: Text.ElideMiddle + font.weight: Font.Bold horizontalAlignment: Text.AlignHCenter maximumLineCount: 1 diff --git a/src/ui/qml/modules/Global/GRadioButton.qml b/src/ui/qml/modules/Global/GRadioButton.qml new file mode 100644 index 000000000..9440bcfed --- /dev/null +++ b/src/ui/qml/modules/Global/GRadioButton.qml @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +RadioButton { + id: root + + property bool drawBottomCorners: false + property bool drawTopCorners: false + readonly property int indicatorHeight: Style.dimens.small_icon_size + property bool tintIcon: false + + Accessible.name: text + horizontalPadding: Constants.component_spacing + indicator: null + spacing: Constants.groupbox_spacing + verticalPadding: Constants.component_spacing / 2 + + background: RoundedRectangle { + bottomLeftCorner: root.drawBottomCorners + bottomRightCorner: root.drawBottomCorners + color: colors.controlPreferredPaneBackground + topLeftCorner: root.drawTopCorners + topRightCorner: root.drawTopCorners + } + contentItem: RowLayout { + spacing: root.spacing + + Rectangle { + border.color: colors.controlBorder + border.width: Style.dimens.border_width + color: colors.controlBackground + implicitHeight: root.indicatorHeight + implicitWidth: root.indicatorHeight + radius: height / 2 + + Rectangle { + anchors.centerIn: parent + color: colors.controlContent + height: parent.height / 2.5 + radius: height / 2 + visible: root.checked + width: height + } + } + TintableIcon { + Layout.preferredHeight: sourceSize.height + source: root.icon.source + sourceSize.height: root.indicatorHeight + tintColor: description.color + tintEnabled: tintIcon + visible: source.toString() !== "" + } + GText { + id: description + + Accessible.ignored: true + text: root.text + visible: text !== "" + } + GSpacer { + Layout.fillWidth: true + visible: root.text !== "" + } + } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + controlStyle: Style.color.controlRadiobutton + groupMember: true + hoveredCondition: hoverHandler.hovered + statefulControl: root + } + FocusFrame { + anchors { + bottomMargin: root.bottomPadding / 2 + leftMargin: root.leftPadding / 2 + rightMargin: Math.max(0, contentItem.width - contentItem.implicitWidth) + root.rightPadding / 2 + topMargin: root.topPadding / 2 + } + } +} diff --git a/src/ui/qml/modules/Global/GRepeater.qml b/src/ui/qml/modules/Global/GRepeater.qml new file mode 100644 index 000000000..ca521a110 --- /dev/null +++ b/src/ui/qml/modules/Global/GRepeater.qml @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQml +import QtQuick + +Repeater { + id: root + + property bool autoConsiderItems: true + property list consideredItems + readonly property real maxItemWidth: { + var maxWidth = 0; + for (let i in consideredItems) { + maxWidth = Math.max(maxWidth, consideredItems[i].implicitWidth); + } + return maxWidth; + } + + function addConsideredItem(pItem) { + consideredItems.push(pItem); + } + function removeConsideredItem(pItemToRemove) { + var newList = []; + for (let i in consideredItems) { + if (consideredItems[i] !== pItemToRemove) { + newList.push(consideredItems[i]); + } + } + consideredItems = newList; + } + + onItemAdded: (pIndex, pItem) => { + if (autoConsiderItems) { + addConsideredItem(pItem); + } + } + onItemRemoved: (pIndex, pItemToRemove) => { + removeConsideredItem(pItemToRemove); + } +} diff --git a/resources/qml/Governikus/Global/GScrollBar.qml b/src/ui/qml/modules/Global/GScrollBar.qml similarity index 55% rename from resources/qml/Governikus/Global/GScrollBar.qml rename to src/ui/qml/modules/Global/GScrollBar.qml index fdbfb419a..d2761c445 100644 --- a/resources/qml/Governikus/Global/GScrollBar.qml +++ b/src/ui/qml/modules/Global/GScrollBar.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -9,7 +9,8 @@ ScrollBar { id: baseItem property bool autohide: !Constants.is_desktop - property alias color: handler.color + property alias borderWidth: customContent.border.width + property alias color: customContent.color property bool highlighted: false function highlight() { @@ -18,15 +19,23 @@ ScrollBar { } Accessible.ignored: true + bottomPadding: Style.dimens.scrollbar_padding_vertical minimumSize: Style.dimens.minimumScrollBarSize - // Using only ScrollBar.AsNeeded leads to the scrollbar becoming visible when highlighted policy: size < 1.0 ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff + rightPadding: Style.dimens.scrollbar_padding_horizontal + topPadding: Style.dimens.scrollbar_padding_vertical + + contentItem: Rectangle { + id: customContent - contentItem: Item { + border.color: colors.controlBorder + border.width: 2 * Style.dimens.border_width + color: colors.controlBackground implicitHeight: 100 - implicitWidth: Style.dimens.scrollbar_width + Style.dimens.scrollbar_padding_horizontal + implicitWidth: Style.dimens.scrollbar_width opacity: (!autohide || active || highlighted) ? 1.0 : 0.0 + radius: width / 2 Behavior on opacity { NumberAnimation { @@ -34,21 +43,18 @@ ScrollBar { easing.type: Easing.InOutCubic } } - - Rectangle { - id: handler - - anchors.left: parent.left - color: Style.color.control - height: parent.height - radius: width / 2 - width: Style.dimens.scrollbar_width - } } onPolicyChanged: if (policy === ScrollBar.AlwaysOn) highlight() + StatefulColors { + id: colors + + checkedCondition: false + controlStyle: Style.color.controlScrollbar + statefulControl: baseItem + } Timer { id: highlightTimer diff --git a/resources/qml/Governikus/Global/GSeparator.qml b/src/ui/qml/modules/Global/GSeparator.qml similarity index 83% rename from resources/qml/Governikus/Global/GSeparator.qml rename to src/ui/qml/modules/Global/GSeparator.qml index 58554c11e..b1715fe28 100644 --- a/resources/qml/Governikus/Global/GSeparator.qml +++ b/src/ui/qml/modules/Global/GSeparator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style diff --git a/src/ui/qml/modules/Global/GSpacer.qml b/src/ui/qml/modules/Global/GSpacer.qml new file mode 100644 index 000000000..02144be38 --- /dev/null +++ b/src/ui/qml/modules/Global/GSpacer.qml @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +Item { +} diff --git a/src/ui/qml/modules/Global/GSwitch.qml b/src/ui/qml/modules/Global/GSwitch.qml new file mode 100644 index 000000000..0f7e7446d --- /dev/null +++ b/src/ui/qml/modules/Global/GSwitch.qml @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Governikus.Style +import Governikus.View + +Switch { + id: control + + property alias description: descriptionText.text + property bool drawBottomCorners: false + property bool drawTopCorners: false + + Accessible.name: text + ". " + description + horizontalPadding: Constants.component_spacing + indicator: null + verticalPadding: Constants.component_spacing + + background: RoundedRectangle { + bottomLeftCorner: control.drawBottomCorners + bottomRightCorner: control.drawBottomCorners + color: colors.controlPreferredPaneBackground + topLeftCorner: control.drawTopCorners + topRightCorner: control.drawTopCorners + } + contentItem: RowLayout { + readonly property int focusWidth: layoutDirection === Qt.LeftToRight ? width : implicitWidth + + layoutDirection: Constants.is_desktop ? Qt.RightToLeft : Qt.LeftToRight + spacing: Constants.component_spacing + + ColumnLayout { + spacing: Constants.subtext_spacing + visible: titleText.text !== "" || descriptionText.text !== "" + + GText { + id: titleText + + Accessible.ignored: true + Layout.maximumWidth: Number.POSITIVE_INFINITY + text: control.text + textStyle: Style.text.subline + visible: text !== "" + } + GText { + id: descriptionText + + Accessible.ignored: true + Layout.maximumWidth: Number.POSITIVE_INFINITY + visible: text !== "" + } + } + Rectangle { + border.color: colors.controlBorder + color: colors.controlBackground + implicitHeight: implicitWidth / 2 + implicitWidth: Style.dimens.switch_width + radius: height / 2 + + Rectangle { + id: ball + + readonly property int distanceBallBorder: 3 + + anchors.verticalCenter: parent.verticalCenter + color: colors.controlContent + height: parent.height - 2 * distanceBallBorder + radius: height / 2 + width: height + x: control.checked ? parent.width - width - distanceBallBorder : distanceBallBorder + + Behavior on x { + enabled: hoverHandler.hovered + + NumberAnimation { + duration: 200 + easing.type: Easing.InOutQuad + } + } + } + } + } + + Accessible.onPressAction: toggle() + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + controlStyle: Style.color.controlSwitch + hoveredCondition: hoverHandler.hovered + statefulControl: control + } + FocusFrame { + anchors { + bottomMargin: control.bottomPadding / 2 + leftMargin: control.leftPadding / 2 + rightMargin: Math.max(0, contentItem.width - contentItem.focusWidth) + control.rightPadding / 2 + topMargin: control.topPadding / 2 + } + } +} diff --git a/resources/qml/Governikus/Global/GText.qml b/src/ui/qml/modules/Global/GText.qml similarity index 73% rename from resources/qml/Governikus/Global/GText.qml rename to src/ui/qml/modules/Global/GText.qml index c770f9fba..4474eb9d5 100644 --- a/resources/qml/Governikus/Global/GText.qml +++ b/src/ui/qml/modules/Global/GText.qml @@ -1,28 +1,39 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type Text { id: root readonly property real effectiveFirstLineHeight: topPadding + Math.ceil(lineHeight) + bottomPadding readonly property real effectiveMaxLinesHeight: topPadding + maximumLineCount * Math.ceil(lineHeight) + bottomPadding + readonly property bool hasLink: link !== "" + readonly property string link: d.link property TextStyle textStyle: Style.text.normal + function tryActivateLink() { + if (hasLink) { + linkActivated(d.link); + } + } + + Accessible.focusable: true Accessible.ignored: text === "" - //: INFO ALL_PLATFORMS Text read by screen reader if the text contains a weblink which may be opened. - Accessible.name: ApplicationModel.stripHtmlTags(text) + (Constants.is_desktop && d.hasLink ? " " + qsTr("Press space to open link: %1").arg(d.link) : "") - Accessible.role: Accessible.StaticText + Accessible.name: ApplicationModel.stripHtmlTags(text) + (Constants.is_desktop && hasLink ? + //: INFO DESKTOP Text read by screen reader if the text contains a weblink which may be opened. + " %1: %2".arg(qsTr("Press space to open link")).arg(d.link) : "") + Accessible.role: Constants.is_desktop && hasLink ? Accessible.Button : d.isHeadline ? Accessible.Heading : Accessible.StaticText Layout.fillWidth: true Layout.maximumWidth: Math.ceil(implicitWidth) color: textStyle.textColor font.pixelSize: textStyle.textSize + font.weight: textStyle.fontWeight lineHeight: textStyle.lineHeight lineHeightMode: Text.FixedHeight linkColor: color @@ -30,11 +41,7 @@ Text { wrapMode: d.nonMultilineElided ? Text.NoWrap : Text.Wrap Component.onCompleted: d.checkForLinks() - Keys.onSpacePressed: { - if (d.hasLink) { - linkActivated(d.link); - } - } + Keys.onSpacePressed: tryActivateLink() onLinkActivated: pLink => { Qt.openUrlExternally(pLink); } @@ -43,7 +50,7 @@ Text { QtObject { id: d - readonly property bool hasLink: link !== "" + readonly property bool isHeadline: [Style.text.headline, Style.text.subline].includes(root.textStyle) property string link: "" readonly property bool nonMultilineElided: maximumLineCount === 1 && elide !== Text.ElideNone diff --git a/resources/qml/Governikus/Global/GTextField.qml b/src/ui/qml/modules/Global/GTextField.qml similarity index 69% rename from resources/qml/Governikus/Global/GTextField.qml rename to src/ui/qml/modules/Global/GTextField.qml index a9b79011a..1b5649a42 100644 --- a/resources/qml/Governikus/Global/GTextField.qml +++ b/src/ui/qml/modules/Global/GTextField.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -11,7 +11,6 @@ TextField { property int enterKeyType: Qt.EnterKeyDefault property var textStyle: Style.text.normal - property bool valid: true Accessible.editable: true Accessible.name: echoMode === TextInput.Normal ? displayText : "" @@ -22,15 +21,15 @@ TextField { activeFocusOnTab: true color: textStyle.textColor font.pixelSize: textStyle.textSize - placeholderTextColor: Style.color.text + placeholderTextColor: Style.color.textNormal.basic selectByMouse: true - selectedTextColor: Style.color.text - selectionColor: Style.color.control + selectedTextColor: Style.color.textNormal.basic + selectionColor: Style.color.control.background.basic background: Rectangle { - border.color: baseItem.valid ? Style.color.border : Constants.red + border.color: Style.color.border border.width: Style.dimens.separator_size - color: baseItem.enabled ? Style.color.pane : Constants.grey + color: Style.color.pane.background.basic radius: Style.dimens.control_radius } diff --git a/resources/qml/Governikus/Global/LabeledText.qml b/src/ui/qml/modules/Global/LabeledText.qml similarity index 82% rename from resources/qml/Governikus/Global/LabeledText.qml rename to src/ui/qml/modules/Global/LabeledText.qml index 97ddaaff9..8dc668c22 100644 --- a/resources/qml/Governikus/Global/LabeledText.qml +++ b/src/ui/qml/modules/Global/LabeledText.qml @@ -1,23 +1,24 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style import Governikus.View +import Governikus.Type Item { property int alignment: Text.AlignLeft property alias bodyElide: bodyText.elide readonly property double focusFrameMargins: focusFrame.anchors.margins property alias label: labelText.text + property alias labelColor: labelText.color property alias labelStyle: labelText.textStyle property alias maximumBodyLineCount: bodyText.maximumLineCount property alias text: bodyText.text + property alias textColor: bodyText.color property alias textFormat: bodyText.textFormat property alias textUppercase: bodyText.font.capitalization - signal linkActivated(string link) - Accessible.name: labelText.text + d.effectiveSeparator + bodyText.text Accessible.role: Accessible.StaticText activeFocusOnTab: true @@ -55,12 +56,14 @@ Item { GText { id: bodyText - Accessible.ignored: true + Accessible.ignored: !hasLink + activeFocusOnTab: hasLink && (Constants.is_desktop || UiPluginModel.isChromeOS) horizontalAlignment: alignment visible: !!text width: parent.width - onLinkActivated: parent.linkActivated(link) + FocusFrame { + } } } } diff --git a/resources/qml/Governikus/Global/MoreInformationLink.qml b/src/ui/qml/modules/Global/MoreInformationLink.qml similarity index 82% rename from resources/qml/Governikus/Global/MoreInformationLink.qml rename to src/ui/qml/modules/Global/MoreInformationLink.qml index 3fabdc075..1345d7677 100644 --- a/resources/qml/Governikus/Global/MoreInformationLink.qml +++ b/src/ui/qml/modules/Global/MoreInformationLink.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,13 +7,12 @@ import Governikus.Global import Governikus.View import Governikus.Style -GButton { +GLink { id: root property bool iconVisible: true Layout.fillWidth: true - background: null font.underline: true horizontalPadding: 0 icon.source: iconVisible ? "qrc:///images/info.svg" : "" diff --git a/resources/qml/Governikus/Global/NumberField.qml b/src/ui/qml/modules/Global/NumberField.qml similarity index 80% rename from resources/qml/Governikus/Global/NumberField.qml rename to src/ui/qml/modules/Global/NumberField.qml index 43e6b8fff..d6b4377ea 100644 --- a/resources/qml/Governikus/Global/NumberField.qml +++ b/src/ui/qml/modules/Global/NumberField.qml @@ -1,14 +1,15 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.Type import Governikus.View -GControl { +Control { id: root readonly property real eyeWidth: eye.width + eye.Layout.leftMargin + eye.Layout.rightMargin @@ -54,15 +55,14 @@ GControl { Accessible.name: (eye.activated ? //: LABEL DESKTOP Screenreader text for the password field - qsTr("The password is visible. Digits entered so far: %1").arg(root.number.split("").join(" ")) : + qsTr("The number is visible. Digits entered so far: %1").arg(root.number.split("").join(" ")) : //: LABEL DESKTOP Screenreader text for the password field - qsTr("The password is hidden.")) + (text === undefined ? " " + passwordState : "") - Accessible.role: Accessible.EditableText + qsTr("The number is hidden.")) + (text === undefined ? " " + passwordState : "") + Accessible.role: Accessible.StaticText Layout.maximumWidth: contentItem.Layout.maximumWidth + leftPadding + rightPadding Layout.minimumWidth: contentItem.Layout.minimumWidth + leftPadding + rightPadding Layout.preferredWidth: implicitWidth activeFocusOnTab: true - implicitHeight: Math.max(grid.implicitHeight, eye.Layout.preferredHeight) + topPadding + bottomPadding contentItem: RowLayout { id: layout @@ -93,14 +93,14 @@ GControl { Layout.minimumWidth: Layout.preferredWidth Layout.preferredHeight: fontMetrics.height + Constants.text_spacing Layout.preferredWidth: grid.markerWidth - color: Style.color.text + color: Style.color.textNormal.basic font: fontMetrics.font horizontalAlignment: Text.AlignHCenter text: eye.activated ? root.number.substr(index, 1) : "" verticalAlignment: Text.AlignTop Rectangle { - readonly property int normalHeight: Constants.is_desktop ? Math.max(plugin.scaleFactor * 4, 1) : 1 + readonly property int normalHeight: Constants.is_desktop ? Math.max(UiPluginModel.scaleFactor * 4, 1) : 1 color: parent.color height: index === root.number.length ? normalHeight * 3 : normalHeight @@ -131,28 +131,20 @@ GControl { property bool activated: false - Layout.maximumHeight: Layout.preferredHeight - Layout.maximumWidth: Layout.preferredWidth - Layout.minimumHeight: Layout.preferredHeight - Layout.minimumWidth: Layout.preferredWidth - Layout.preferredHeight: implicitBackgroundHeight + (Constants.is_desktop ? 0 : Constants.text_spacing) - Layout.preferredWidth: implicitBackgroundWidth + (Constants.is_desktop ? 0 : Constants.text_spacing) + background: null + padding: Constants.text_spacing / 2 text: (activated ? //: LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - qsTr("Press to hide the password") : + qsTr("Press to hide the number") : //: LABEL DESKTOP Screenreader text for the eye icon to change the password visibility - qsTr("Press to show the password")) + qsTr("Press to show the number")) - background: TintableIcon { - fillMode: Image.Pad + contentItem: TintableIcon { source: eye.activated ? "qrc:///images/eye_visibility_on.svg" : "qrc:///images/eye_visibility_off.svg" sourceSize.height: Constants.is_desktop ? Style.dimens.icon_size : Style.dimens.small_icon_size - tintColor: Style.color.text - } - contentItem: Item { + tintColor: Style.color.textNormal.basic } - Accessible.onPressAction: clicked() onClicked: eye.activated = !eye.activated onVisibleChanged: if (visible) activated = false @@ -176,7 +168,7 @@ GControl { id: fontMetrics font.bold: true - font.pixelSize: Constants.is_desktop ? plugin.scaleFactor * 50 : 24 + font.pixelSize: Constants.is_desktop ? UiPluginModel.scaleFactor * 50 : 24 } TextInput { id: echoField @@ -184,8 +176,8 @@ GControl { maximumLength: 6 visible: false - validator: RegExpValidatorCompat { - expression: new RegExp("[0-9]{" + echoField.maximumLength + "}") + validator: RegularExpressionValidator { + regularExpression: new RegExp("[0-9]{" + echoField.maximumLength + "}") } } FocusFrame { diff --git a/resources/qml/Governikus/Global/PkiSwitch.qml b/src/ui/qml/modules/Global/PkiSwitch.qml similarity index 89% rename from resources/qml/Governikus/Global/PkiSwitch.qml rename to src/ui/qml/modules/Global/PkiSwitch.qml index d207561f9..ee8233a01 100644 --- a/resources/qml/Governikus/Global/PkiSwitch.qml +++ b/src/ui/qml/modules/Global/PkiSwitch.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import QtQuick -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type MouseArea { id: root diff --git a/resources/qml/Governikus/Global/PrivacyStatement.qml b/src/ui/qml/modules/Global/PrivacyStatement.qml similarity index 90% rename from resources/qml/Governikus/Global/PrivacyStatement.qml rename to src/ui/qml/modules/Global/PrivacyStatement.qml index f2eeab2f1..d30ed64f9 100644 --- a/resources/qml/Governikus/Global/PrivacyStatement.qml +++ b/src/ui/qml/modules/Global/PrivacyStatement.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.Style GText { diff --git a/resources/qml/Governikus/Global/ProxyCredentialsPopup.qml b/src/ui/qml/modules/Global/ProxyCredentialsPopup.qml similarity index 90% rename from resources/qml/Governikus/Global/ProxyCredentialsPopup.qml rename to src/ui/qml/modules/Global/ProxyCredentialsPopup.qml index e82c2b46d..32032bdfc 100644 --- a/resources/qml/Governikus/Global/ProxyCredentialsPopup.qml +++ b/src/ui/qml/modules/Global/ProxyCredentialsPopup.qml @@ -1,9 +1,10 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style +import Governikus.Type import Governikus.View ConfirmationPopup { @@ -57,7 +58,7 @@ ConfirmationPopup { GTextField { id: userInput - width: 500 * plugin.scaleFactor + width: 500 * UiPluginModel.scaleFactor } GText { //: LABEL DESKTOP Accessible name. @@ -74,7 +75,7 @@ ConfirmationPopup { id: passwordInput echoMode: TextInput.Password - width: 500 * plugin.scaleFactor + width: 500 * UiPluginModel.scaleFactor } } } diff --git a/resources/qml/Governikus/Global/RoundedRectangle.qml b/src/ui/qml/modules/Global/RoundedRectangle.qml similarity index 97% rename from resources/qml/Governikus/Global/RoundedRectangle.qml rename to src/ui/qml/modules/Global/RoundedRectangle.qml index 778281b56..1034c1057 100644 --- a/resources/qml/Governikus/Global/RoundedRectangle.qml +++ b/src/ui/qml/modules/Global/RoundedRectangle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global diff --git a/src/ui/qml/modules/Global/StatefulColors.qml b/src/ui/qml/modules/Global/StatefulColors.qml new file mode 100644 index 000000000..1afb623d7 --- /dev/null +++ b/src/ui/qml/modules/Global/StatefulColors.qml @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import QtQuick.Controls +import Governikus.Style + +Item { + id: root + + property bool checkedCondition: statefulControl.checked + property color controlBackground: controlStyle.background.basic + property color controlBorder: controlStyle.border.basic + property color controlContent: controlStyle.content.basic + property color controlPreferredPaneBackground: Style.color.transparent + property ControlComponents controlStyle: Style.color.control + property bool disabledCondition: !statefulControl.enabled + property bool groupMember: false + property bool hoveredCondition: statefulControl.hovered + property color linkColor: linkStyle.basic + property ComponentColors linkStyle: Style.color.linkBasic + property color paneBackground: paneStyle.background.basic + property color paneBorder: paneStyle.border.basic + property CoreComponents paneStyle: Style.color.pane + property bool pressedCondition: statefulControl.pressed + required property var statefulControl + property color textHeadline: Style.color.textHeadline.basic + property color textNormal: Style.color.textNormal.basic + property color textSubline: Style.color.textSubline.basic + property color textTitle: Style.color.textTitle.basic + + states: [ + State { + name: "disabled" + when: disabledCondition + + PropertyChanges { + root.controlBackground: controlStyle.background.disabled + root.controlBorder: controlStyle.border.disabled + root.controlContent: controlStyle.content.disabled + root.linkColor: linkStyle.disabled + root.paneBackground: paneStyle.background.disabled + root.paneBorder: paneStyle.border.disabled + root.textHeadline: Style.color.textHeadline.disabled + root.textNormal: Style.color.textNormal.disabled + root.textSubline: Style.color.textSubline.disabled + root.textTitle: Style.color.textTitle.disabled + } + }, + State { + name: "pressed" + when: pressedCondition && !(groupMember && checkedCondition) + + PropertyChanges { + root.controlBackground: controlStyle.background.pressed + root.controlBorder: controlStyle.border.pressed + root.controlContent: controlStyle.content.pressed + root.controlPreferredPaneBackground: paneStyle.background.pressed + root.linkColor: linkStyle.pressed + root.paneBackground: paneStyle.background.pressed + root.paneBorder: paneStyle.border.pressed + root.textHeadline: Style.color.textHeadline.pressed + root.textNormal: Style.color.textNormal.pressed + root.textSubline: Style.color.textSubline.pressed + root.textTitle: Style.color.textTitle.pressed + } + }, + State { + name: "hovered" + when: hoveredCondition && !(groupMember && checkedCondition) + + PropertyChanges { + root.controlBackground: controlStyle.background.hovered + root.controlBorder: controlStyle.border.hovered + root.controlContent: controlStyle.content.hovered + root.controlPreferredPaneBackground: paneStyle.background.hovered + root.linkColor: linkStyle.hovered + root.paneBackground: paneStyle.background.hovered + root.paneBorder: paneStyle.border.hovered + root.textHeadline: Style.color.textHeadline.hovered + root.textNormal: Style.color.textNormal.hovered + root.textSubline: Style.color.textSubline.hovered + root.textTitle: Style.color.textTitle.hovered + } + }, + State { + name: "checked" + when: checkedCondition + + PropertyChanges { + root.controlBackground: controlStyle.background.checked + root.controlBorder: controlStyle.border.checked + root.controlContent: controlStyle.content.checked + root.linkColor: linkStyle.checked + root.paneBackground: paneStyle.background.checked + root.paneBorder: paneStyle.border.checked + root.textHeadline: Style.color.textHeadline.checked + root.textNormal: Style.color.textNormal.checked + root.textSubline: Style.color.textSubline.checked + root.textTitle: Style.color.textTitle.checked + } + } + ] + transitions: [ + EaseInPressedTransition { + target: root + } + ] +} diff --git a/src/ui/qml/modules/Global/TintableIcon.qml b/src/ui/qml/modules/Global/TintableIcon.qml new file mode 100644 index 000000000..d5cfc19c9 --- /dev/null +++ b/src/ui/qml/modules/Global/TintableIcon.qml @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import Governikus.Style + +Item { + id: root + + property bool desaturate: false + property alias playAnimation: animation.enabled + property alias source: image.source + property alias sourceSize: image.sourceSize + property color tintColor: Style.color.textNormal.basic + property bool tintEnabled: true + + implicitHeight: image.implicitHeight + implicitWidth: image.implicitWidth + + Behavior on source { + id: animation + + enabled: false + + SequentialAnimation { + PropertyAnimation { + duration: source == "" ? 0 : Constants.animation_duration + easing.type: Easing.InCubic + property: "opacity" + targets: root + to: 0 + } + PropertyAction { + property: "source" + target: root + } + PropertyAnimation { + duration: source == "" ? Constants.animation_duration * 2 : Constants.animation_duration + easing.type: source == "" ? Easing.InOutCubic : Easing.InCubic + property: "opacity" + targets: root + to: 1 + } + } + } + + Image { + id: image + + anchors.fill: parent + fillMode: Image.PreserveAspectFit + visible: !root.tintEnabled || GraphicsInfo.api !== GraphicsInfo.Software + + layer { + enabled: root.tintEnabled + + effect: ShaderEffect { + property color color: root.tintColor + + fragmentShader: root.desaturate ? "qrc:/shader/DesaturateShader.frag" : "qrc:/shader/ColorOverlayShader.frag" + } + } + } + Button { + anchors.fill: parent + background: null + enabled: false + icon.color: root.tintColor + icon.height: root.height + icon.source: root.source + icon.width: root.width + padding: 0 + visible: !image.visible + } +} diff --git a/resources/qml/Governikus/Global/Utils.qml b/src/ui/qml/modules/Global/Utils.qml similarity index 71% rename from resources/qml/Governikus/Global/Utils.qml rename to src/ui/qml/modules/Global/Utils.qml index 5a9b185eb..f43503e5b 100644 --- a/resources/qml/Governikus/Global/Utils.qml +++ b/src/ui/qml/modules/Global/Utils.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ pragma Singleton import QtQuick -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type QtObject { function escapeHtml(pStr) { @@ -37,6 +36,24 @@ QtObject { } pFlickable.contentY = Math.min(pFlickable.contentY + pFlickable.height, pFlickable.originY + pFlickable.contentHeight - pFlickable.height); } + function scrollPageLeft(pFlickable) { + if (pFlickable.width >= pFlickable.contentWidth) { + return; + } + if (pFlickable.atXBeginning) { + return; + } + pFlickable.contentX = Math.max(pFlickable.contentX - pFlickable.width, pFlickable.originX); + } + function scrollPageRight(pFlickable) { + if (pFlickable.width >= pFlickable.contentWidth) { + return; + } + if (pFlickable.atXEnd) { + return; + } + pFlickable.contentX = Math.min(pFlickable.contentX + pFlickable.width, pFlickable.contentWidth - pFlickable.width - pFlickable.originX); + } function scrollPageUp(pFlickable) { if (pFlickable.height >= pFlickable.contentHeight) { return; diff --git a/resources/qml/Governikus/Global/BaseConfirmationPopup.qml b/src/ui/qml/modules/Global/internal/BaseConfirmationPopup.qml similarity index 87% rename from resources/qml/Governikus/Global/BaseConfirmationPopup.qml rename to src/ui/qml/modules/Global/internal/BaseConfirmationPopup.qml index df3e2394e..6e90e76ba 100644 --- a/resources/qml/Governikus/Global/BaseConfirmationPopup.qml +++ b/src/ui/qml/modules/Global/internal/BaseConfirmationPopup.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -7,7 +7,7 @@ import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel +import Governikus.Type Popup { id: root @@ -23,6 +23,7 @@ Popup { property string cancelButtonText: qsTr("Cancel") default property alias children: customContent.children property int horizontalTextAlignment: Text.AlignLeft + property alias mainTextFormat: mainText.textFormat //: LABEL ALL_PLATFORMS property string okButtonText: qsTr("OK") property int style: ConfirmationPopup.PopupStyle.OkButton | ConfirmationPopup.PopupStyle.CancelButton @@ -81,7 +82,6 @@ Popup { activeFocusOnTab: true elide: Text.ElideRight focus: true - font.bold: true horizontalAlignment: root.horizontalTextAlignment maximumLineCount: 5 text: root.title @@ -92,13 +92,24 @@ Popup { } } GText { + id: mainText + + Layout.maximumWidth: Number.POSITIVE_INFINITY + Layout.preferredWidth: Math.ceil(hiddenText.implicitWidth) activeFocusOnTab: true horizontalAlignment: root.horizontalTextAlignment text: root.text + textFormat: Text.RichText visible: root.text !== "" FocusFrame { } + GText { + id: hiddenText + + text: root.text + visible: false + } } Item { id: customContent diff --git a/resources/qml/Governikus/InformationView/+desktop/DiagnosisView.qml b/src/ui/qml/modules/InformationView/+desktop/DiagnosisView.qml similarity index 55% rename from resources/qml/Governikus/InformationView/+desktop/DiagnosisView.qml rename to src/ui/qml/modules/InformationView/+desktop/DiagnosisView.qml index 9811c4742..98b4c33d7 100644 --- a/resources/qml/Governikus/InformationView/+desktop/DiagnosisView.qml +++ b/src/ui/qml/modules/InformationView/+desktop/DiagnosisView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,8 +8,7 @@ import Governikus.View import Governikus.Global import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.DiagnosisModel +import Governikus.Type SectionPage { id: sectionPage @@ -67,42 +66,38 @@ SectionPage { Component { id: footerDelegate - Item { - height: saveToFile.height + GButton { + id: saveToFile + + Accessible.description: qsTr("Save system data to textfile") + anchors.fill: parent + anchors.rightMargin: Constants.groupbox_spacing + //: LABEL DESKTOP + disabledTooltipText: qsTr("Diagnosis is still running") + enableButton: !diagnosisModel.running || !timeout.running + //: LABEL DESKTOP + enabledTooltipText: diagnosisModel.running ? qsTr("Diagnosis may be incomplete") : "" + icon.source: "qrc:///images/desktop/save_icon.svg" + //: LABEL DESKTOP + text: qsTr("Save to file") + tintIcon: true + + onClicked: { + let filenameSuggestion = "%1.%2.%3.txt".arg(Qt.application.name).arg(qsTr("SystemData")).arg(diagnosisModel.getCreationTime()); + fileDialog.selectFile(filenameSuggestion); + } - GButton { - id: saveToFile + GFileDialog { + id: fileDialog - Accessible.description: qsTr("Save system data to textfile") - anchors.fill: parent - anchors.rightMargin: Constants.groupbox_spacing - //: LABEL DESKTOP - disabledTooltipText: qsTr("Diagnosis is still running") - enableButton: !diagnosisModel.running || !timeout.running - //: LABEL DESKTOP - enabledTooltipText: diagnosisModel.running ? qsTr("Diagnosis may be incomplete") : "" - icon.source: "qrc:///images/desktop/save_icon.svg" + defaultSuffix: "txt" //: LABEL DESKTOP - text: qsTr("Save to file") - tintIcon: true - - onClicked: { - let filenameSuggestion = "%1.%2.%3.txt".arg(Qt.application.name).arg(qsTr("SystemData")).arg(diagnosisModel.getCreationTime()); - fileDialog.selectFile(filenameSuggestion); - } + nameFilters: qsTr("Textfiles (*.txt)") - GFileDialog { - id: fileDialog - - defaultSuffix: "txt" - //: LABEL DESKTOP - nameFilters: qsTr("Textfiles (*.txt)") - - //: LABEL DESKTOP - title: qsTr("Save system data") + //: LABEL DESKTOP + title: qsTr("Save system data") - onAccepted: diagnosisModel.saveToFile(file) - } + onAccepted: diagnosisModel.saveToFile(file) } Timer { id: timeout diff --git a/resources/qml/Governikus/InformationView/+desktop/LicenseInformation.qml b/src/ui/qml/modules/InformationView/+desktop/LicenseInformation.qml similarity index 69% rename from resources/qml/Governikus/InformationView/+desktop/LicenseInformation.qml rename to src/ui/qml/modules/InformationView/+desktop/LicenseInformation.qml index d0ef38f46..ab666f1fb 100644 --- a/resources/qml/Governikus/InformationView/+desktop/LicenseInformation.qml +++ b/src/ui/qml/modules/InformationView/+desktop/LicenseInformation.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type GListView { id: listView @@ -20,20 +20,24 @@ GListView { delegate: RoundedRectangle { readonly property bool isFirstItem: index === 0 readonly property bool isLastItem: index === ListView.view.count - 1 + readonly property alias text: delegateText.text + Accessible.ignored: delegateText.text === "" + Accessible.name: delegateText.text + Accessible.role: Accessible.StaticText bottomLeftCorner: isLastItem bottomRightCorner: isLastItem - color: Style.color.pane - implicitHeight: delegateText.implicitHeight + delegateText.anchors.bottomMargin + delegateText.anchors.topMargin + color: Style.color.pane.background.basic + implicitHeight: Math.ceil(delegateText.implicitHeight) + delegateText.anchors.bottomMargin + delegateText.anchors.topMargin topLeftCorner: isFirstItem topRightCorner: isFirstItem width: listView.width - Constants.pane_padding - z: currentIndex === index ? 1 : 0 + z: 0 GText { id: delegateText - Accessible.ignored: text === "" + Accessible.ignored: true text: model.modelData anchors { @@ -44,8 +48,14 @@ GListView { topMargin: isFirstItem ? Constants.pane_padding : Constants.text_spacing } } + } + highlight: Item { + z: 2 + FocusFrame { - framee: delegateText + anchors.leftMargin: 0 + anchors.rightMargin: 0 + scope: listView } } diff --git a/resources/qml/Governikus/InformationView/+desktop/ReleaseNotes.qml b/src/ui/qml/modules/InformationView/+desktop/ReleaseNotes.qml similarity index 88% rename from resources/qml/Governikus/InformationView/+desktop/ReleaseNotes.qml rename to src/ui/qml/modules/InformationView/+desktop/ReleaseNotes.qml index 9bcc78b74..f432f729b 100644 --- a/resources/qml/Governikus/InformationView/+desktop/ReleaseNotes.qml +++ b/src/ui/qml/modules/InformationView/+desktop/ReleaseNotes.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.ReleaseInformationModel +import Governikus.Type ColumnLayout { id: root diff --git a/src/ui/qml/modules/InformationView/+desktop/VersionInformation.qml b/src/ui/qml/modules/InformationView/+desktop/VersionInformation.qml new file mode 100644 index 000000000..bb7d6ae94 --- /dev/null +++ b/src/ui/qml/modules/InformationView/+desktop/VersionInformation.qml @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.View +import Governikus.Type + +ColumnLayout { + spacing: Constants.component_spacing + + GPane { + Layout.fillWidth: true + spacing: Constants.component_spacing + + GMenuItem { + Layout.fillWidth: true + buttonIconSource: "qrc:///images/open_website.svg" + //: LABEL DESKTOP + buttonText: qsTr("Open website") + buttonTooltip: "https://www.ausweisapp.bund.de/%1/aa2/privacy".arg(SettingsModel.language) + iconSource: "qrc:/images/desktop/privacy_icon.svg" + + //: LABEL DESKTOP + title: qsTr("Privacy statement") + + onClicked: Qt.openUrlExternally(buttonTooltip) + } + GSeparator { + Layout.fillWidth: true + } + GMenuItem { + Layout.fillWidth: true + buttonIconSource: "qrc:///images/open_website.svg" + //: LABEL DESKTOP + buttonText: qsTr("Open website") + buttonTooltip: "https://www.ausweisapp.bund.de/%1/aa2/a11y".arg(SettingsModel.language) + iconSource: "qrc:/images/desktop/a11y_icon.svg" + + //: LABEL DESKTOP + title: qsTr("Accessibility statement") + + onClicked: Qt.openUrlExternally(buttonTooltip) + } + } + Item { + id: baseItem + + Layout.fillWidth: true + Layout.preferredHeight: column.implicitHeight + + GPane { + id: column + + anchors.fill: parent + spacing: Constants.component_spacing + + Repeater { + id: repeater + + model: VersionInformationModel + + delegate: LabeledText { + id: delegate + + Accessible.name: model.label + ": " + model.text + label: model.label + text: model.text + width: baseItem.width + } + } + } + MouseArea { + property int counter: 0 + + anchors.fill: parent + + onClicked: { + counter += 1; + if (counter === 10) { + SettingsModel.developerOptions = !SettingsModel.developerOptions; + ApplicationModel.showFeedback((SettingsModel.developerOptions ? + //: LABEL DESKTOP + qsTr("Developer options activated.") : + //: LABEL DESKTOP + qsTr("Developer options deactivated."))); + counter = 0; + } + } + } + } +} diff --git a/resources/qml/Governikus/InformationView/+mobile/LicenseInformation.qml b/src/ui/qml/modules/InformationView/+mobile/LicenseInformation.qml similarity index 93% rename from resources/qml/Governikus/InformationView/+mobile/LicenseInformation.qml rename to src/ui/qml/modules/InformationView/+mobile/LicenseInformation.qml index 84adec3ce..310749f6d 100644 --- a/resources/qml/Governikus/InformationView/+mobile/LicenseInformation.qml +++ b/src/ui/qml/modules/InformationView/+mobile/LicenseInformation.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.ApplicationModel +import Governikus.Type SectionPage { id: root @@ -30,6 +30,7 @@ SectionPage { GListView { id: listView + Accessible.ignored: false displayMarginBeginning: Constants.pane_padding displayMarginEnd: Constants.pane_padding model: ApplicationModel.getLicenseText() diff --git a/resources/qml/Governikus/InformationView/+mobile/ReleaseNotes.qml b/src/ui/qml/modules/InformationView/+mobile/ReleaseNotes.qml similarity index 92% rename from resources/qml/Governikus/InformationView/+mobile/ReleaseNotes.qml rename to src/ui/qml/modules/InformationView/+mobile/ReleaseNotes.qml index d787280c5..5434af61b 100644 --- a/resources/qml/Governikus/InformationView/+mobile/ReleaseNotes.qml +++ b/src/ui/qml/modules/InformationView/+mobile/ReleaseNotes.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,7 +7,7 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.ReleaseInformationModel +import Governikus.Type SectionPage { id: root diff --git a/resources/qml/Governikus/InformationView/+mobile/VersionInformation.qml b/src/ui/qml/modules/InformationView/+mobile/VersionInformation.qml similarity index 81% rename from resources/qml/Governikus/InformationView/+mobile/VersionInformation.qml rename to src/ui/qml/modules/InformationView/+mobile/VersionInformation.qml index c4460c776..394d3a57f 100644 --- a/resources/qml/Governikus/InformationView/+mobile/VersionInformation.qml +++ b/src/ui/qml/modules/InformationView/+mobile/VersionInformation.qml @@ -1,14 +1,12 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.TitleBar import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.VersionInformationModel +import Governikus.Type FlickableSectionPage { id: root @@ -39,11 +37,11 @@ FlickableSectionPage { break; case 10: SettingsModel.advancedSettings = !SettingsModel.advancedSettings; - ApplicationModel.showFeedback(SettingsModel.advancedSettings ? + ApplicationModel.showFeedback((SettingsModel.advancedSettings ? //: LABEL ANDROID IOS qsTr("Advanced settings activated.") : //: LABEL ANDROID IOS - qsTr("Advanced settings deactivated."), true); + qsTr("Advanced settings deactivated.")), true); advancedSettingsCounter = 0; break; } diff --git a/src/ui/qml/modules/InformationView/ReleaseNotesView.qml b/src/ui/qml/modules/InformationView/ReleaseNotesView.qml new file mode 100644 index 000000000..b4520009b --- /dev/null +++ b/src/ui/qml/modules/InformationView/ReleaseNotesView.qml @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.View +import Governikus.Style +import Governikus.Type + +GListView { + id: root + + property real maximumContentWidth: Number.POSITIVE_INFINITY + + Accessible.ignored: false + activeFocusOnTab: true + displayMarginBeginning: Constants.pane_padding + displayMarginEnd: Constants.pane_padding + + delegate: FormattedTextView { + idx: index + lineType: model.lineType + maximumContentWidth: root.maximumContentWidth + text: model.content + totalItemCount: count + width: root.width + } + highlight: Item { + z: 2 + + FocusFrame { + anchors.leftMargin: 0 + anchors.rightMargin: Constants.pane_padding + scope: root + } + } + + Keys.onDownPressed: { + do { + root.incrementCurrentIndex(); + } while (currentItem.text === "") + } + Keys.onUpPressed: { + do { + root.decrementCurrentIndex(); + } while (currentItem.text === "") + } + + layer { + enabled: true + + effect: GDropShadow { + } + } +} diff --git a/resources/qml/+desktop/main.qml b/src/ui/qml/modules/Init/+desktop/App.qml similarity index 78% rename from resources/qml/+desktop/main.qml rename to src/ui/qml/modules/Init/+desktop/App.qml index 9b1fceec0..dae1cbe0b 100644 --- a/resources/qml/+desktop/main.qml +++ b/src/ui/qml/modules/Init/+desktop/App.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import Governikus.Global import Governikus.TitleBar @@ -14,12 +14,7 @@ import Governikus.SettingsView import Governikus.SetupAssistantView import Governikus.UpdateView import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.UiModule -import Governikus.Type.SettingsModel -import Governikus.Type.SelfAuthModel -import Governikus.Type.ChangePinModel +import Governikus.Type import Governikus.Style import QtQml import QtQml.Models @@ -42,7 +37,7 @@ ApplicationWindow { d.hideUiAndTaskbarEntry(); return; } - plugin.fireQuitApplicationRequest(); + UiPluginModel.fireQuitApplicationRequest(); } function showDetachedLogView() { if (d.detachedLogView === null) { @@ -66,13 +61,13 @@ ApplicationWindow { Component.onCompleted: menuBar.forceActiveFocus(Qt.MouseFocusReason) onClosing: close => { - if (ApplicationModel.currentWorkflow !== ApplicationModel.WORKFLOW_NONE && !d.suppressAbortWarning) { + if (ApplicationModel.currentWorkflow !== ApplicationModel.Workflow.NONE && !d.suppressAbortWarning) { abortWorkflowWarning.open(); close.accepted = false; return; } if (d.detachedLogView !== null) { - visibility = ApplicationWindow.Minimized; + showMinimized(); close.accepted = false; return; } @@ -113,25 +108,61 @@ ApplicationWindow { property bool suppressAbortWarning: false function abortCurrentWorkflow() { - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_AUTHENTICATION) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.AUTHENTICATION) { AuthModel.cancelWorkflow(); - } else if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_SELF_AUTHENTICATION) { + } else if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.SELF_AUTHENTICATION) { SelfAuthModel.cancelWorkflow(); - } else if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN) { + } else if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.CHANGE_PIN) { ChangePinModel.cancelWorkflow(); } } function closeOpenDialogs() { closeWarning.close(); + quitWarning.close(); abortWorkflowWarning.close(); } + function ensureHeight(pMargin) { + let preferredScreenHeight = appWindow.screen.height - 2 * pMargin; + if (appWindow.height > preferredScreenHeight) { + appWindow.height = preferredScreenHeight; + } + } + function ensureScreenFit() { + let windowMargin = 50; + let screenMinX = appWindow.screen.virtualX; + if (appWindow.x < screenMinX) { + ensureWidth(windowMargin); + appWindow.x = screenMinX + windowMargin; + } + let screenMinY = appWindow.screen.virtualY; + if (appWindow.y < screenMinY) { + ensureHeight(windowMargin); + appWindow.y = screenMinY + windowMargin; + } + let screenMaxX = screenMinX + appWindow.screen.width; + if (appWindow.x + appWindow.width > screenMaxX) { + ensureWidth(windowMargin); + appWindow.x = screenMaxX - appWindow.width - windowMargin; + } + let screenMaxY = screenMinY + appWindow.screen.height; + if (appWindow.y + appWindow.height > screenMaxY) { + ensureHeight(windowMargin); + appWindow.y = screenMaxY - appWindow.height - windowMargin; + } + } + function ensureWidth(pMargin) { + let preferredScreenWidth = appWindow.screen.width - 2 * pMargin; + if (appWindow.width > preferredScreenWidth) { + appWindow.width = preferredScreenWidth; + } + } function hideUiAndTaskbarEntry() { hide(); - plugin.hideFromTaskbar(); + UiPluginModel.hideFromTaskbar(); } function setScaleFactor() { - let initialSize = plugin.initialWindowSize; - plugin.scaleFactor = Math.min(width / initialSize.width, height / initialSize.height); + let initialSize = UiPluginModel.initialWindowSize; + UiPluginModel.scaleFactor = Math.min(width / initialSize.width, height / initialSize.height); } function showDetachedLogViewIfPresent() { if (d.detachedLogView !== null) { @@ -163,6 +194,7 @@ ApplicationWindow { ConfirmationPopup { closePolicy: Popup.NoAutoClose + mainTextFormat: Text.PlainText style: ConfirmationPopup.PopupStyle.NoButtons //: INFO DESKTOP The AA2 is currently remote controlled via the SDK interface, concurrent usage of the AA2 is not possible. title: qsTr("Another application uses %1").arg(Qt.application.name) @@ -238,15 +270,23 @@ ApplicationWindow { dominationPopup.destroy(); dominationPopup = null; } - if (plugin.dominated) { + if (UiPluginModel.dominated) { dominationPopup = domination.createObject(appWindow, { - "text": plugin.dominator - }); + "text": UiPluginModel.dominator + }); dominationPopup.open(); } } function onFireHideRequest() { - hide(); + if (SettingsModel.showTrayIcon) { + d.hideUiAndTaskbarEntry(); + return; + } + if (Qt.platform.os === "osx") { + hide(); + } else { + showMinimized(); + } } function onFireShowRequest(pModule) { d.showMainWindow(); @@ -256,32 +296,33 @@ ApplicationWindow { case UiModule.CURRENT: break; case UiModule.IDENTIFY: - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE) { d.activeView = UiModule.SELF_AUTHENTICATION; } - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_AUTHENTICATION || ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_SELF_AUTHENTICATION) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.AUTHENTICATION || ApplicationModel.currentWorkflow === ApplicationModel.Workflow.SELF_AUTHENTICATION) { d.activeView = UiModule.IDENTIFY; } break; case UiModule.PINMANAGEMENT: - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE || ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_CHANGE_PIN) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE || ApplicationModel.currentWorkflow === ApplicationModel.Workflow.CHANGE_PIN) { d.activeView = UiModule.PINMANAGEMENT; } break; case UiModule.UPDATEINFORMATION: - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE && d.activeView === UiModule.DEFAULT) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE && d.activeView === UiModule.DEFAULT) { d.activeView = UiModule.UPDATEINFORMATION; } break; default: - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE) { d.activeView = pModule; } break; } + d.ensureScreenFit(); } - target: plugin + target: UiPluginModel } Connections { function onFireAppUpdateDataChanged() { @@ -308,7 +349,7 @@ ApplicationWindow { height: 0.8 * parent.height opacity: 0.2 source: "qrc:///images/logo_beta_testing.svg" - visible: plugin.developerVersion && SettingsModel.showBetaTesting + visible: UiPluginModel.developerVersion && SettingsModel.showBetaTesting width: 0.8 * parent.width } Loader { @@ -408,7 +449,7 @@ ApplicationWindow { } } Rectangle { - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic height: childrenRect.height opacity: 0.7 radius: Style.dimens.pane_radius @@ -429,7 +470,6 @@ ApplicationWindow { //: LABEL DESKTOP text: qsTr("Developer Mode: Enabled!") - textStyle: Style.text.normal_warning } GButton { //: LABEL DESKTOP Global button to disable developer mode. @@ -450,7 +490,7 @@ ApplicationWindow { proxyCredentials.open(); } - target: plugin + target: UiPluginModel } ProxyCredentialsPopup { id: proxyCredentials @@ -460,12 +500,12 @@ ApplicationWindow { id: detachedLogViewWindow ApplicationWindow { - height: plugin.initialWindowSize.height - minimumHeight: appWindow.minimumHeight - minimumWidth: appWindow.minimumWidth + height: UiPluginModel.initialWindowSize.height + minimumHeight: UiPluginModel.initialWindowSize.height + minimumWidth: UiPluginModel.initialWindowSize.width title: qsTr("Detached log viewer") visible: true - width: plugin.initialWindowSize.width + width: UiPluginModel.initialWindowSize.width onClosing: { d.detachedLogView.destroy(); diff --git a/resources/qml/+mobile/main.qml b/src/ui/qml/modules/Init/+mobile/App.qml similarity index 66% rename from resources/qml/+mobile/main.qml rename to src/ui/qml/modules/Init/+mobile/App.qml index 5eed94ccf..62bc063df 100644 --- a/resources/qml/+mobile/main.qml +++ b/src/ui/qml/modules/Init/+mobile/App.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,10 +8,7 @@ import Governikus.TitleBar import Governikus.Navigation import Governikus.View import Governikus.FeedbackView -import Governikus.Type.ApplicationModel -import Governikus.Type.RemoteServiceModel -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule +import Governikus.Type import Governikus.Style ApplicationWindow { @@ -19,10 +16,6 @@ ApplicationWindow { property var feedbackPopup: null - // Workaround for qt 5.12 not calculating the highdpi scaling factor correctly. On some devices (like the pixel 3) - // this leads to a small light stripe above the dark statusbar. By setting the background to black and filling the - // rest of the window with the background color, it's still there but not noticeable. - color: "#000000" flags: Qt.platform.os === "ios" ? Qt.Window | Qt.MaximizeUsingFullscreenGeometryHint : Qt.Window visible: true @@ -33,19 +26,19 @@ ApplicationWindow { readonly property var currentSectionPage: contentArea.currentSectionPage readonly property bool isBackAction: navigationAction && navigationAction.action === NavigationAction.Action.Back + enableTileStyle: currentSectionPage ? currentSectionPage.enableTileStyle : false navigationAction: currentSectionPage ? currentSectionPage.navigationAction : null rightAction: currentSectionPage ? currentSectionPage.rightTitleBarAction : null + showContent: currentSectionPage ? currentSectionPage.showTitleBarContent : true showSeparator: currentSectionPage ? currentSectionPage.contentIsScrolled : false smartEidUsed: currentSectionPage ? currentSectionPage.smartEidUsed : false title: currentSectionPage ? currentSectionPage.title : "" - titleBarOpacity: currentSectionPage ? currentSectionPage.titleBarOpacity : 1 - visible: !currentSectionPage || currentSectionPage.titleBarVisible } Component.onCompleted: { Style.dimens.screenHeight = Qt.binding(function () { - return appWindow.height; - }); + return appWindow.height; + }); feedback.showIfNecessary(); } onClosing: pClose => { @@ -53,22 +46,22 @@ ApplicationWindow { pClose.accepted = false; if (contentArea.visibleItem) { if (contentArea.activeModule === UiModule.DEFAULT) { - let currentTime = new Date().getTime(); + let currentTime = new Date(); if (currentTime - d.lastCloseInvocation < 1000) { - plugin.fireQuitApplicationRequest(); + UiPluginModel.fireQuitApplicationRequest(); pClose.accepted = true; return; } d.lastCloseInvocation = currentTime; //: INFO ANDROID IOS Hint that is shown if the users pressed the "back" button on the top-most navigation level for the first time (a second press closes the app). - ApplicationModel.showFeedback(qsTr("To close the app, quickly press the back button twice.")); + ApplicationModel.showFeedback(qsTr("To close the app, press the back button 2 times.")); return; } let activeStackView = contentArea.visibleItem; let navigationAction = contentArea.currentSectionPage.navigationAction; if (activeStackView.depth <= 1 && (!navigationAction || navigationAction.action !== NavigationAction.Action.Cancel)) { navigation.show(UiModule.DEFAULT); - } else if (navigationAction) { + } else if (navigationAction && navigationAction.action !== NavigationAction.Action.None) { navigationAction.clicked(undefined); } } @@ -77,14 +70,10 @@ ApplicationWindow { QtObject { id: d - property var lastCloseInvocation: 0 - } - Action { - shortcut: "Ctrl+Alt+R" - - onTriggered: plugin.debugBuild ? plugin.doRefresh() : "" + property date lastCloseInvocation: new Date(0) } Action { + enabled: UiPluginModel.debugBuild shortcut: "Escape" onTriggered: appWindow.close() @@ -94,7 +83,7 @@ ApplicationWindow { feedback.showIfNecessary(); } - target: plugin + target: UiPluginModel } Connections { function onFireShowRequest(pModule) { @@ -108,7 +97,7 @@ ApplicationWindow { navigation.show(UiModule.HELP); break; case UiModule.IDENTIFY: - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE) { navigation.show(UiModule.SELF_AUTHENTICATION); break; } @@ -118,34 +107,22 @@ ApplicationWindow { } } - target: plugin + target: UiPluginModel } ContentArea { id: contentArea function reset() { currentSectionPage.popAll(); - currentSectionPage.reset(); } activeModule: navigation.activeModule anchors { - bottom: navigation.top - bottomMargin: !navigation.lockedAndHidden || !currentSectionPage ? 0 : plugin.safeAreaMargins.bottom + (currentSectionPage.hiddenNavbarPadding ? navigation.height : 0) - left: parent.left - leftMargin: plugin.safeAreaMargins.left - right: parent.right - rightMargin: plugin.safeAreaMargins.right - top: parent.top - - Behavior on bottomMargin { - enabled: !ApplicationModel.isScreenReaderRunning() - - NumberAnimation { - duration: Constants.animation_duration - } - } + bottomMargin: navigation.effectiveHeight + fill: parent + leftMargin: UiPluginModel.safeAreaMargins.left + rightMargin: UiPluginModel.safeAreaMargins.right } } Navigation { @@ -156,9 +133,9 @@ ApplicationWindow { anchors { bottom: parent.bottom left: parent.left - leftMargin: plugin.safeAreaMargins.left + leftMargin: UiPluginModel.safeAreaMargins.left right: parent.right - rightMargin: plugin.safeAreaMargins.right + rightMargin: UiPluginModel.safeAreaMargins.right } } IosBackGestureMouseArea { @@ -176,8 +153,8 @@ ApplicationWindow { } if (ApplicationModel.feedback !== "") { feedbackPopup = toast.createObject(appWindow, { - "text": ApplicationModel.feedback - }); + "text": ApplicationModel.feedback + }); feedbackPopup.open(); } } @@ -200,7 +177,7 @@ ApplicationWindow { id: feedback function showIfNecessary() { - if (ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_NONE && !RemoteServiceModel.running && SettingsModel.requestStoreFeedback()) { + if (ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE && !RemoteServiceModel.running && SettingsModel.requestStoreFeedback()) { SettingsModel.hideFutureStoreFeedbackDialogs(); feedback.open(); } diff --git a/resources/qml/Governikus/MainView/+desktop/MainView.qml b/src/ui/qml/modules/MainView/+desktop/MainView.qml similarity index 62% rename from resources/qml/Governikus/MainView/+desktop/MainView.qml rename to src/ui/qml/modules/MainView/+desktop/MainView.qml index 7fff5d202..6d6ee9777 100644 --- a/resources/qml/Governikus/MainView/+desktop/MainView.qml +++ b/src/ui/qml/modules/MainView/+desktop/MainView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,9 +7,7 @@ import QtQuick.Controls import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SelfAuthModel -import Governikus.Type.UiModule +import Governikus.Type SectionPage { id: sectionPage @@ -28,46 +26,38 @@ SectionPage { topMargin: Constants.component_spacing + Math.max(0, (sectionPage.height - sectionPage.width) / 2) } Tile { - Layout.fillHeight: true - Layout.fillWidth: true activeFocusOnTab: true - image: "qrc:/images/lock.svg" + icon.source: "qrc:/images/lock.svg" //: LABEL DESKTOP - title: qsTr("Change PIN") + text: qsTr("Change PIN") onClicked: sectionPage.nextView(UiModule.PINMANAGEMENT) } Tile { - Layout.fillHeight: true - Layout.fillWidth: true activeFocusOnTab: true - image: "qrc:/images/mydata.svg" + icon.source: "qrc:/images/mydata_tile.svg" //: LABEL DESKTOP - title: qsTr("See my
personal data") + text: qsTr("See my
personal data") onClicked: sectionPage.nextView(UiModule.SELF_AUTHENTICATION) } Tile { - Layout.fillHeight: true - Layout.fillWidth: true activeFocusOnTab: true - image: "qrc:/images/desktop/settings.svg" + icon.source: "qrc:/images/desktop/settings.svg" //: LABEL DESKTOP - title: qsTr("Settings") + text: qsTr("Settings") onClicked: sectionPage.nextView(UiModule.SETTINGS) } Tile { - Layout.fillHeight: true - Layout.fillWidth: true activeFocusOnTab: true - image: "qrc:/images/desktop/help.svg" + icon.source: "qrc:/images/desktop/help.svg" //: LABEL DESKTOP - title: qsTr("Help") + text: qsTr("Help") onClicked: sectionPage.nextView(UiModule.HELP) } diff --git a/src/ui/qml/modules/MainView/+desktop/internal/Tile.qml b/src/ui/qml/modules/MainView/+desktop/internal/Tile.qml new file mode 100644 index 000000000..a794781bb --- /dev/null +++ b/src/ui/qml/modules/MainView/+desktop/internal/Tile.qml @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +AbstractButton { + id: root + + Accessible.name: ApplicationModel.stripHtmlTags(text) + Layout.fillHeight: true + Layout.fillWidth: true + implicitHeight: 1 + implicitWidth: 1 + padding: 2 * Constants.pane_padding + + background: GPaneBackground { + id: pane + + border.color: colors.paneBorder + color: colors.paneBackground + opacity: SettingsModel.showBetaTesting ? 0.9 : 1.0 + + FocusFrame { + marginFactor: 0.8 + radius: parent.radius * 1.2 + scope: root + } + } + contentItem: Column { + spacing: Constants.component_spacing + + TintableIcon { + id: image + + source: root.icon.source + sourceSize.height: Style.dimens.huge_icon_size + tintColor: Style.color.textTitle.checked + } + GText { + id: label + + color: root.activeFocus && UiPluginModel.showFocusIndicator ? Style.color.textTitle.checked : Style.color.textTitle.basic + horizontalAlignment: Text.AlignLeft + text: root.text + textStyle: Style.text.tile + width: parent.width + } + } + + StatefulColors { + id: colors + + statefulControl: root + } +} diff --git a/resources/qml/Governikus/MainView/+mobile/MainView.qml b/src/ui/qml/modules/MainView/+mobile/MainView.qml similarity index 61% rename from resources/qml/Governikus/MainView/+mobile/MainView.qml rename to src/ui/qml/modules/MainView/+mobile/MainView.qml index 8a5d59753..6ae12b396 100644 --- a/resources/qml/Governikus/MainView/+mobile/MainView.qml +++ b/src/ui/qml/modules/MainView/+mobile/MainView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,50 +8,71 @@ import Governikus.Global import Governikus.View import Governikus.Style import Governikus.TitleBar -import Governikus.Type.UiModule -import Governikus.Type.ApplicationModel -import Governikus.Type.WorkflowModel +import Governikus.Type FlickableSectionPage { id: root + enableTileStyle: false fillWidth: true margins: 0 + showTitleBarContent: false + title: "" - //: LABEL ANDROID IOS - title: qsTr("Start page") + DelegateModel { + id: tileModel - Component.onCompleted: { - if (WorkflowModel.isSmartSupported) { - tileModel.append({ - "imagePath": "qrc:///images/mobile/smarteid.svg", - "module": UiModule.SMART_EID, - //: LABEL ANDROID IOS - "titleText": qsTr("Smart-eID") - }); - } - } + delegate: Tile { + id: tileDelegate - ListModel { - id: tileModel + Accessible.ignored: tileView.allItemsVisible ? false : index !== tileView.currentIndex + Accessible.name: titleText + ". " + qsTr("Item %1 of %2").arg(index + 1).arg(tileView.count) + (tileView.allItemsVisible ? "" : " . " + tileView.scrollHint) + activeFocusOnTab: false + focusPolicy: Qt.TabFocus + height: ListView.view.height + image: imagePath + title: titleText + width: tileView.itemWidth - ListElement { - imagePath: "qrc:///images/mobile/device.svg" - module: UiModule.CHECK_ID_CARD - //: LABEL ANDROID IOS - titleText: qsTr("Check device and ID card") - } - ListElement { - imagePath: "qrc:///images/lock.svg" - module: UiModule.PINMANAGEMENT - //: LABEL ANDROID IOS - titleText: qsTr("Change PIN") + Accessible.onScrollLeftAction: if (tileView.isIos) + tileView.scrollPageLeft() + Accessible.onScrollRightAction: if (tileView.isIos) + tileView.scrollPageRight() + Component.onCompleted: tileDelegate.DelegateModel.inItems = module !== UiModule.SMART_EID || ApplicationModel.isSmartSupported + onClicked: root.show(module) + + PointHandler { + onGrabChanged: tileView.focus = false + } + FocusFrame { + marginFactor: -2 + } } - ListElement { - imagePath: "qrc:///images/mydata.svg" - module: UiModule.SELF_AUTHENTICATION - //: LABEL ANDROID IOS - titleText: qsTr("See my personal data") + model: ListModel { + ListElement { + imagePath: "qrc:///images/mobile/device_tile.svg" + module: UiModule.CHECK_ID_CARD + //: LABEL ANDROID IOS + titleText: qsTr("Check device and ID card") + } + ListElement { + imagePath: "qrc:///images/lock.svg" + module: UiModule.PINMANAGEMENT + //: LABEL ANDROID IOS + titleText: qsTr("Change PIN") + } + ListElement { + imagePath: "qrc:///images/mydata_tile.svg" + module: UiModule.SELF_AUTHENTICATION + //: LABEL ANDROID IOS + titleText: qsTr("See my personal data") + } + ListElement { + imagePath: "qrc:///images/mobile/smarteid.svg" + module: UiModule.SMART_EID + //: LABEL ANDROID IOS + titleText: qsTr("Smart-eID") + } } } GSpacer { @@ -69,7 +90,7 @@ FlickableSectionPage { property real minItemHeight: 1 property real minItemWidth: 1 readonly property real overlapFactor: 0.72 - readonly property string scrollHint: qsTr("Two finger swipe to scroll.") + readonly property string scrollHint: isIos ? qsTr("Three finger swipe to scroll.") : qsTr("Two finger swipe to scroll.") function updateTileLimits() { var newMaximumItemWidth = -1; @@ -101,7 +122,7 @@ FlickableSectionPage { clip: true highlightMoveDuration: 250 highlightRangeMode: allItemsVisible ? ListView.NoHighlightRange : ListView.StrictlyEnforceRange - interactive: !allItemsVisible + interactive: !allItemsVisible || UiPluginModel.isChromeOS maximumFlickVelocity: 4 * width model: tileModel orientation: Qt.Horizontal @@ -109,20 +130,9 @@ FlickableSectionPage { preferredHighlightEnd: width / 2 + itemWidth / 2 snapMode: ListView.SnapOneItem - delegate: Tile { - Accessible.ignored: tileView.isIos ? false : index !== tileView.currentIndex - Accessible.name: titleText + ". " + qsTr("Item %1 of %2").arg(index + 1).arg(tileView.count) + (tileView.isIos ? "" : " . " + tileView.scrollHint) - height: ListView.view.height - image: imagePath - title: titleText - width: tileView.itemWidth - - onClicked: show(module) - } - - Component.onCompleted: { + onCountChanged: { updateTileLimits(); - currentIndex = ApplicationModel.isScreenReaderRunning() && isIos ? 1 : 0; + currentIndex = 1; } onHeightChanged: updateTileLimits() onWidthChanged: updateTileLimits() @@ -136,7 +146,7 @@ FlickableSectionPage { opacity: tileView.allItemsVisible ? 0 : 1 delegate: Rectangle { - color: index === indicator.currentIndex ? Style.color.control_border : Style.color.control_border_disabled + color: index === indicator.currentIndex ? Style.color.control.border.basic : Style.color.control.border.disabled implicitHeight: Style.dimens.pageindicator_size implicitWidth: Style.dimens.pageindicator_size radius: width / 2 diff --git a/resources/qml/Governikus/MainView/+mobile/Tile.qml b/src/ui/qml/modules/MainView/+mobile/internal/Tile.qml similarity index 81% rename from resources/qml/Governikus/MainView/+mobile/Tile.qml rename to src/ui/qml/modules/MainView/+mobile/internal/Tile.qml index 666ebbadc..6fa09ea5c 100644 --- a/resources/qml/Governikus/MainView/+mobile/Tile.qml +++ b/src/ui/qml/modules/MainView/+mobile/internal/Tile.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -34,14 +34,10 @@ AbstractButton { topPadding: topInset + paddingBaseValue background: GPaneBackground { - Accessible.ignored: true - color: root.pressed ? Style.color.control : Style.color.pane - layer.enabled: GraphicsInfo.api !== GraphicsInfo.Software - - layer.effect: GDropShadow { - } + id: pane - Accessible.onPressAction: clicked() + Accessible.ignored: true + color: colors.paneBackground } contentItem: GridLayout { id: layout @@ -59,22 +55,32 @@ AbstractButton { Accessible.ignored: true sourceSize.height: Style.dimens.medium_icon_size - tintColor: root.pressed ? Style.color.mainbutton_content_pressed : Style.color.text_subline + tintColor: Style.color.textTitle.checked } GText { id: text Accessible.ignored: true - color: root.pressed ? Style.color.mainbutton_content_pressed : Style.color.text_title elide: Text.ElideRight horizontalAlignment: Text.AlignLeft maximumLineCount: 3 rightPadding: root.flowVertically ? paddingBaseValue : 0 - textStyle: Style.text.title + textStyle: Style.text.tile } GSpacer { Layout.fillHeight: true visible: root.flowVertically } } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + hoveredCondition: hoverHandler.hovered + statefulControl: root + } } diff --git a/resources/qml/Governikus/MoreView/+desktop/MoreView.qml b/src/ui/qml/modules/MoreView/+desktop/MoreView.qml similarity index 94% rename from resources/qml/Governikus/MoreView/+desktop/MoreView.qml rename to src/ui/qml/modules/MoreView/+desktop/MoreView.qml index eef81e978..d0e5eef77 100644 --- a/resources/qml/Governikus/MoreView/+desktop/MoreView.qml +++ b/src/ui/qml/modules/MoreView/+desktop/MoreView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -10,7 +10,7 @@ import Governikus.View import Governikus.TitleBar import Governikus.FeedbackView import Governikus.InformationView -import Governikus.Type.ApplicationModel +import Governikus.Type SectionPage { id: sectionPage @@ -49,7 +49,7 @@ SectionPage { //: LABEL DESKTOP qsTr("Data and logs"), //: LABEL DESKTOP - qsTr("Version information"), + qsTr("Information"), //: LABEL DESKTOP qsTr("Software license"), //: LABEL DESKTOP diff --git a/resources/qml/Governikus/MoreView/+desktop/MoreViewDiagnosis.qml b/src/ui/qml/modules/MoreView/+desktop/internal/MoreViewDiagnosis.qml similarity index 81% rename from resources/qml/Governikus/MoreView/+desktop/MoreViewDiagnosis.qml rename to src/ui/qml/modules/MoreView/+desktop/internal/MoreViewDiagnosis.qml index 46f32f26d..f6d998622 100644 --- a/resources/qml/Governikus/MoreView/+desktop/MoreViewDiagnosis.qml +++ b/src/ui/qml/modules/MoreView/+desktop/internal/MoreViewDiagnosis.qml @@ -1,11 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.View -import Governikus.Type.SettingsModel +import Governikus.Type GPane { signal showDiagnosis @@ -13,7 +13,7 @@ GPane { spacing: Constants.component_spacing - MoreViewMenuItem { + GMenuItem { Layout.fillWidth: true //: LABEL DESKTOP buttonText: qsTr("Show system data") @@ -27,7 +27,7 @@ GPane { GSeparator { Layout.fillWidth: true } - MoreViewMenuItem { + GMenuItem { Layout.fillWidth: true //: LABEL DESKTOP buttonText: qsTr("Show logs") diff --git a/resources/qml/Governikus/MoreView/+desktop/MoreViewGeneral.qml b/src/ui/qml/modules/MoreView/+desktop/internal/MoreViewGeneral.qml similarity index 52% rename from resources/qml/Governikus/MoreView/+desktop/MoreViewGeneral.qml rename to src/ui/qml/modules/MoreView/+desktop/internal/MoreViewGeneral.qml index 59e8b01fe..afe38f92f 100644 --- a/resources/qml/Governikus/MoreView/+desktop/MoreViewGeneral.qml +++ b/src/ui/qml/modules/MoreView/+desktop/internal/MoreViewGeneral.qml @@ -1,18 +1,16 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule +import Governikus.Type GPane { spacing: Constants.component_spacing - MoreViewMenuItem { + GMenuItem { Layout.fillWidth: true buttonIconSource: "qrc:///images/open_website.svg" //: LABEL DESKTOP @@ -28,7 +26,7 @@ GPane { GSeparator { Layout.fillWidth: true } - MoreViewMenuItem { + GMenuItem { Layout.fillWidth: true buttonIconSource: "qrc:///images/open_website.svg" //: LABEL DESKTOP @@ -44,46 +42,12 @@ GPane { GSeparator { Layout.fillWidth: true } - MoreViewMenuItem { - Layout.fillWidth: true - buttonIconSource: "qrc:///images/open_website.svg" - //: LABEL DESKTOP - buttonText: qsTr("Open website") - buttonTooltip: "https://www.ausweisapp.bund.de/%1/aa2/privacy".arg(SettingsModel.language) - iconSource: "qrc:/images/desktop/privacy_icon.svg" - - //: LABEL DESKTOP - title: qsTr("Privacy statement") - - onClicked: Qt.openUrlExternally(buttonTooltip) - } - GSeparator { - Layout.fillWidth: true - } - MoreViewMenuItem { - Layout.fillWidth: true - buttonIconSource: "qrc:///images/open_website.svg" - //: LABEL DESKTOP - buttonText: qsTr("Open website") - buttonTooltip: "https://www.ausweisapp.bund.de/%1/aa2/a11y".arg(SettingsModel.language) - iconSource: "qrc:/images/desktop/a11y_icon.svg" - - //: LABEL DESKTOP - title: qsTr("Accessibility statement") - - onClicked: Qt.openUrlExternally(buttonTooltip) - } - GSeparator { - Layout.fillWidth: true - } - MoreViewMenuItem { + GMenuItem { Layout.fillWidth: true buttonIconSource: "qrc:///images/open_website.svg" //: LABEL DESKTOP buttonText: qsTr("Open website") buttonTooltip: "https://www.ausweisapp.bund.de/%1/aa2/providerlist".arg(SettingsModel.language) - //: LABEL DESKTOP - description: qsTr("Do you want to see a list of service providers?") iconSource: "qrc:/images/identify.svg" //: LABEL DESKTOP diff --git a/resources/qml/Governikus/MoreView/+mobile/MoreView.qml b/src/ui/qml/modules/MoreView/+mobile/MoreView.qml similarity index 73% rename from resources/qml/Governikus/MoreView/+mobile/MoreView.qml rename to src/ui/qml/modules/MoreView/+mobile/MoreView.qml index 43d14fcd6..c677ac4ab 100644 --- a/resources/qml/Governikus/MoreView/+mobile/MoreView.qml +++ b/src/ui/qml/modules/MoreView/+mobile/MoreView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -10,15 +10,13 @@ import Governikus.TitleBar import Governikus.View import Governikus.FeedbackView import Governikus.InformationView -import Governikus.Type.ApplicationModel -import Governikus.Type.LogModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.SettingsView -import Governikus.Type.UiModule FlickableSectionPage { id: baseItem + enableTileStyle: false //: LABEL ANDROID IOS title: qsTr("Help") @@ -28,17 +26,19 @@ FlickableSectionPage { GOptionsContainer { //: LABEL ANDROID IOS - title: qsTr("Help & Feedback") + title: qsTr("General") width: parent.width - MenuItem { + GMenuItem { drawTopCorners: true - icon: "qrc:///images/open_website.svg" + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("FAQ - Frequently asked questions") width: parent.width onClicked: Qt.openUrlExternally("https://www.ausweisapp.bund.de/%1/aa2/faq".arg(SettingsModel.language)) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GSeparator { anchors.left: parent.left @@ -46,13 +46,15 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { - icon: "qrc:///images/open_website.svg" + GMenuItem { + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("Contact") width: parent.width onClicked: Qt.openUrlExternally("https://www.ausweisapp.bund.de/%1/aa2/support".arg(SettingsModel.language)) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GSeparator { anchors.left: parent.left @@ -60,13 +62,15 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { - icon: "qrc:///images/open_website.svg" + GMenuItem { + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("Privacy statement") width: parent.width onClicked: Qt.openUrlExternally("https://www.ausweisapp.bund.de/%1/aa2/privacy".arg(SettingsModel.language)) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GSeparator { anchors.left: parent.left @@ -74,13 +78,15 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { - icon: "qrc:///images/open_website.svg" + GMenuItem { + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("Accessibility statement") width: parent.width onClicked: Qt.openUrlExternally("https://www.ausweisapp.bund.de/%1/aa2/a11y".arg(SettingsModel.language)) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GSeparator { anchors.left: parent.left @@ -88,13 +94,15 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { - icon: "qrc:///images/open_website.svg" + GMenuItem { + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("List of Providers") width: parent.width onClicked: Qt.openUrlExternally("https://www.ausweisapp.bund.de/%1/aa2/providerlist".arg(SettingsModel.language)) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } GSeparator { anchors.left: parent.left @@ -102,14 +110,16 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { drawBottomCorners: true - icon: "qrc:///images/open_website.svg" + icon.source: "qrc:///images/open_website.svg" //: LABEL ANDROID IOS title: qsTr("Rate %1").arg(Qt.application.name) width: parent.width onClicked: Qt.openUrlExternally(ApplicationModel.storeUrl) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } } GOptionsContainer { @@ -117,18 +127,21 @@ FlickableSectionPage { title: qsTr("Logs") width: parent.width - MenuItem { + GMenuItem { drawTopCorners: true //: LABEL ANDROID IOS title: qsTr("Show Logs") width: parent.width onClicked: push(logPage) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) Component { id: logPage LogView { + enableTileStyle: baseItem.enableTileStyle } } } @@ -138,14 +151,16 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { drawBottomCorners: true - icon: "qrc:///images/material_mail.svg" + icon.source: "qrc:///images/email_icon.svg" //: LABEL ANDROID IOS title: qsTr("Send log to the support") width: parent.width onClicked: LogModel.mailLog() + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } } GOptionsContainer { @@ -153,18 +168,21 @@ FlickableSectionPage { title: qsTr("Information") width: parent.width - MenuItem { + GMenuItem { drawTopCorners: true //: LABEL ANDROID IOS title: qsTr("Version information") width: parent.width onClicked: push(versionInformation) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) Component { id: versionInformation VersionInformation { + enableTileStyle: baseItem.enableTileStyle } } } @@ -174,17 +192,20 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { //: LABEL ANDROID IOS title: qsTr("Terms of use and software license") width: parent.width onClicked: push(licenseInformation) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) Component { id: licenseInformation LicenseInformation { + enableTileStyle: baseItem.enableTileStyle } } } @@ -194,18 +215,21 @@ FlickableSectionPage { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { drawBottomCorners: true //: LABEL ANDROID IOS title: qsTr("Release notes") width: parent.width onClicked: push(releaseNotes) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) Component { id: releaseNotes ReleaseNotes { + enableTileStyle: baseItem.enableTileStyle } } } diff --git a/resources/qml/Governikus/Navigation/+mobile/Navigation.qml b/src/ui/qml/modules/Navigation/+mobile/Navigation.qml similarity index 85% rename from resources/qml/Governikus/Navigation/+mobile/Navigation.qml rename to src/ui/qml/modules/Navigation/+mobile/Navigation.qml index 66b56d331..ea72263be 100644 --- a/resources/qml/Governikus/Navigation/+mobile/Navigation.qml +++ b/src/ui/qml/modules/Navigation/+mobile/Navigation.qml @@ -1,18 +1,17 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule +import Governikus.Type RowLayout { id: navigation readonly property int activeModule: d.activeModule + readonly property real effectiveHeight: UiPluginModel.safeAreaMargins.bottom + (lockedAndHidden ? 0 : implicitHeight) readonly property bool lockedAndHidden: d.lockedAndHidden signal resetContentArea @@ -29,7 +28,7 @@ RowLayout { } enabled: !lockedAndHidden - height: lockedAndHidden ? 0 : (navigationView.height + plugin.safeAreaMargins.bottom) + height: lockedAndHidden ? 0 : effectiveHeight visible: height > 0 Behavior on height { diff --git a/resources/qml/Governikus/Navigation/+mobile/NavigationItem.qml b/src/ui/qml/modules/Navigation/+mobile/internal/NavigationItem.qml similarity index 77% rename from resources/qml/Governikus/Navigation/+mobile/NavigationItem.qml rename to src/ui/qml/modules/Navigation/+mobile/internal/NavigationItem.qml index aab0fd48f..9dcbef66a 100644 --- a/resources/qml/Governikus/Navigation/+mobile/NavigationItem.qml +++ b/src/ui/qml/modules/Navigation/+mobile/internal/NavigationItem.qml @@ -1,27 +1,29 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.View AbstractButton { id: root property bool flowHorizontally: true - readonly property color itemColor: selected ? Style.color.text_navigation : Style.color.text_navigation_unchecked - property bool selected: false property alias source: tabImage.source Accessible.name: text - Accessible.role: Accessible.Button + Accessible.role: checked ? Accessible.PageTab : Accessible.Button Layout.minimumWidth: tabImage.implicitWidth + leftPadding + rightPadding padding: Constants.text_spacing / 2 background: Rectangle { - color: selected ? Style.color.control : Style.color.transparent + id: pane + + border.color: colors.paneBorder + color: colors.paneBackground radius: Style.dimens.control_radius } contentItem: Item { @@ -39,8 +41,6 @@ AbstractButton { rowSpacing: Style.dimens.navigation_bar_text_padding rows: 2 - Accessible.onPressAction: root.clicked() - TintableIcon { id: tabImage @@ -48,7 +48,7 @@ AbstractButton { Layout.alignment: root.flowHorizontally ? Qt.AlignRight : Qt.AlignCenter Layout.maximumWidth: implicitWidth sourceSize.height: Style.dimens.navigation_bar_icon_size - tintColor: root.itemColor + tintColor: tabText.color } GText { id: tabText @@ -56,7 +56,7 @@ AbstractButton { Accessible.ignored: true Layout.alignment: root.flowHorizontally ? Qt.AlignLeft : Qt.AlignCenter Layout.preferredWidth: Math.min(Math.ceil(implicitWidth), root.contentItem.width) - color: root.itemColor + color: colors.textNormal elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter maximumLineCount: 1 @@ -65,4 +65,17 @@ AbstractButton { } } } + + HoverHandler { + id: hoverHandler + + } + StatefulColors { + id: colors + + hoveredCondition: hoverHandler.hovered + statefulControl: root + } + FocusFrame { + } } diff --git a/resources/qml/Governikus/Navigation/+mobile/NavigationView.qml b/src/ui/qml/modules/Navigation/+mobile/internal/NavigationView.qml similarity index 62% rename from resources/qml/Governikus/Navigation/+mobile/NavigationView.qml rename to src/ui/qml/modules/Navigation/+mobile/internal/NavigationView.qml index 2f9f74662..65f2d1a39 100644 --- a/resources/qml/Governikus/Navigation/+mobile/NavigationView.qml +++ b/src/ui/qml/modules/Navigation/+mobile/internal/NavigationView.qml @@ -1,33 +1,33 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick +import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.UiModule -import Governikus.Type.WorkflowModel +import Governikus.Type -GControl { +Control { id: root Layout.maximumWidth: Math.max(Layout.preferredWidth, Style.dimens.max_text_width) Layout.minimumWidth: navigationRow.Layout.minimumWidth + leftPadding + rightPadding Layout.preferredWidth: contentItem.Layout.preferredWidth + leftPadding + rightPadding - bottomInset: -plugin.safeAreaMargins.bottom - bottomPadding: Constants.is_layout_android ? Style.dimens.navigation_bar_padding : Style.dimens.navigation_bar_text_padding + bottomInset: -UiPluginModel.safeAreaMargins.bottom + bottomPadding: Style.dimens.navigation_bar_bottom_padding horizontalPadding: Style.dimens.navigation_bar_padding topPadding: Style.dimens.navigation_bar_padding background: RoundedRectangle { bottomLeftCorner: false bottomRightCorner: false - color: Style.color.pane + color: Style.color.pane.background.basic layer.enabled: GraphicsInfo.api !== GraphicsInfo.Software radius: Style.dimens.pane_radius layer.effect: GDropShadow { - verticalOffset: -3 + shadowVerticalOffset: -3 } } contentItem: RowLayout { @@ -44,13 +44,31 @@ GControl { delegate: NavigationItem { readonly property var mainViewSubViews: [UiModule.IDENTIFY, UiModule.SELF_AUTHENTICATION, UiModule.PINMANAGEMENT, UiModule.CHECK_ID_CARD, UiModule.SMART_EID] + //: ANDROID IOS LABEL Relative position of current navigation tab in navigation view. %1 is replaced with the current tab's index, %2 with the total count of tabs + readonly property string tabPositionA11y: qsTr("%1 of %2").arg(index + 1).arg(repeater.count) Accessible.ignored: root.Accessible.ignored + Accessible.name: { + //: ANDROID IOS LABEL + var a11yName = [text, qsTr("Tab"), tabPositionA11y]; + if (checked) { + if (Qt.platform.os === "ios") { + //: IOS Selected navigation tab. + a11yName.unshift(qsTr("Selection")); + //: IOS Name of a11y element of selected navigation tab. + a11yName.unshift(qsTr("Tab bar")); + } else { + //: ANDROID Currently selected navigation tab of navigation view. + a11yName.unshift(qsTr("Selected")); + } + } + return a11yName.join(". "); + } Layout.fillHeight: true Layout.fillWidth: true Layout.preferredWidth: repeater.maxItemWidth + checked: navigation.activeModule === module || (module === UiModule.DEFAULT && mainViewSubViews.includes(navigation.activeModule)) flowHorizontally: navigationRow.horizontalIcons - selected: navigation.activeModule === module || (module === UiModule.DEFAULT && mainViewSubViews.includes(navigation.activeModule)) source: image text: qsTr(desc) diff --git a/src/ui/qml/modules/PasswordInfoView/+desktop/PasswordInfoView.qml b/src/ui/qml/modules/PasswordInfoView/+desktop/PasswordInfoView.qml new file mode 100644 index 000000000..3dd2d7e53 --- /dev/null +++ b/src/ui/qml/modules/PasswordInfoView/+desktop/PasswordInfoView.qml @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Governikus.Animations +import Governikus.Global +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: root + + readonly property url buttonLink: infoContent.buttonLink + readonly property string buttonText: infoContent.buttonText + readonly property var contentList: infoContent.contentList + readonly property string hint: infoContent.hint + readonly property string hintButtonText: infoContent.hintButtonText + readonly property string hintTitle: infoContent.hintTitle + property PasswordInfoData infoContent: PasswordInfoData { + } + property alias rootEnabled: titleBarAction.rootEnabled + readonly property string title: infoContent.title + + signal abortCurrentWorkflow + signal close + + spacing: Constants.pane_spacing + + titleBarAction: TitleBarAction { + id: titleBarAction + + rootEnabled: ApplicationModel.currentWorkflow === ApplicationModel.Workflow.NONE + showSettings: false + text: root.title + } + + Keys.onEnterPressed: close() + Keys.onEscapePressed: close() + Keys.onReturnPressed: close() + + GRepeater { + id: repeater + + autoConsiderItems: false + model: root.contentList + + delegate: RowLayout { + Layout.alignment: Qt.AlignLeft + spacing: 2 * Constants.component_spacing + + AnimationLoader { + Layout.alignment: Qt.AlignTop + animated: false + type: blockHeaderAnimation + + Component.onCompleted: repeater.addConsideredItem(this) + Component.onDestruction: repeater.removeConsideredItem(this) + } + TintableIcon { + Layout.alignment: Qt.AlignTop + source: blockImage + sourceSize.width: Math.max(repeater.maxItemWidth, Style.dimens.header_icon_size) + tintColor: Style.color.image + visible: source != "" + } + ColumnLayout { + Layout.alignment: Qt.AlignTop + spacing: Constants.groupbox_spacing + + GText { + Layout.alignment: Qt.AlignLeft + activeFocusOnTab: true + horizontalAlignment: Text.AlignLeft + text: blockTitle + textStyle: Style.text.subline + visible: text !== "" + + FocusFrame { + } + } + Repeater { + model: paragraphList + + delegate: GText { + Layout.alignment: Qt.AlignLeft + activeFocusOnTab: true + horizontalAlignment: Text.AlignLeft + text: modelData + visible: text !== "" + + FocusFrame { + } + } + } + } + } + } + GButton { + Layout.alignment: Qt.AlignRight + Layout.topMargin: Constants.component_spacing + icon.source: "qrc:///images/open_website.svg" + text: root.buttonText + visible: text !== "" + + onClicked: Qt.openUrlExternally(root.buttonLink) + } + GSpacer { + Layout.fillHeight: true + } + Hint { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + buttonText: root.hintButtonText + buttonTooltip: PinResetInformationModel.pinResetUrl + text: root.hint + //: LABEL DESKTOP + title: root.hintTitle !== "" ? root.hintTitle : qsTr("Hint") + visible: text !== "" + + onClicked: { + abortCurrentWorkflow(); + Qt.openUrlExternally(PinResetInformationModel.pinResetUrl); + } + } +} diff --git a/resources/qml/Governikus/PasswordInfoView/+mobile/PasswordInfoView.qml b/src/ui/qml/modules/PasswordInfoView/+mobile/PasswordInfoView.qml similarity index 66% rename from resources/qml/Governikus/PasswordInfoView/+mobile/PasswordInfoView.qml rename to src/ui/qml/modules/PasswordInfoView/+mobile/PasswordInfoView.qml index 37c781978..ae41cc803 100644 --- a/resources/qml/Governikus/PasswordInfoView/+mobile/PasswordInfoView.qml +++ b/src/ui/qml/modules/PasswordInfoView/+mobile/PasswordInfoView.qml @@ -1,13 +1,14 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts +import Governikus.Animations import Governikus.Global import Governikus.View import Governikus.Style import Governikus.TitleBar -import Governikus.Type.PinResetInformationModel +import Governikus.Type FlickableSectionPage { id: root @@ -17,7 +18,8 @@ FlickableSectionPage { readonly property var contentList: infoContent.contentList readonly property string hint: infoContent.hint readonly property string hintButtonText: infoContent.hintButtonText - property var infoContent: PasswordInfoContent { + readonly property string hintTitle: infoContent.hintTitle + property PasswordInfoData infoContent: PasswordInfoData { } readonly property string infoContentTitle: infoContent.title @@ -38,7 +40,10 @@ FlickableSectionPage { Layout.margins: Constants.pane_padding spacing: Constants.component_spacing - Repeater { + GRepeater { + id: repeater + + autoConsiderItems: false model: root.contentList width: parent.width @@ -46,20 +51,14 @@ FlickableSectionPage { spacing: Constants.component_spacing width: parent.width - PasswordInfoImage { - anchors.horizontalCenter: parent.horizontalCenter - imageType: blockHeaderImageType - visible: blockHeaderImageType !== PasswordInfoImage.Type.NONE - width: parent.width * 0.3 - } Column { spacing: Constants.groupbox_spacing width: parent.width GText { - font.bold: true text: blockTitle - textStyle: headline ? Style.text.headline : Style.text.subline + textStyle: Style.text.subline + visible: text !== "" width: parent.width wrapMode: Text.WordWrap } @@ -69,10 +68,25 @@ FlickableSectionPage { delegate: GText { text: modelData + visible: text !== "" width: parent.width } } } + AnimationLoader { + anchors.horizontalCenter: parent.horizontalCenter + animated: false + type: blockHeaderAnimation + + Component.onCompleted: repeater.addConsideredItem(this) + Component.onDestruction: repeater.removeConsideredItem(this) + } + TintableIcon { + anchors.horizontalCenter: parent.horizontalCenter + source: blockImage + sourceSize.width: Math.max(repeater.maxItemWidth, Style.dimens.header_icon_size) + tintColor: Style.color.image + } } } GButton { @@ -83,6 +97,8 @@ FlickableSectionPage { visible: text !== "" onClicked: Qt.openUrlExternally(root.buttonLink) + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } Hint { @@ -91,11 +107,14 @@ FlickableSectionPage { Layout.topMargin: Constants.component_spacing buttonText: root.hintButtonText text: root.hint + //: LABEL ANDROID IOS + title: root.hintTitle !== "" ? root.hintTitle : qsTr("Hint") visible: text !== "" onClicked: { abortCurrentWorkflow(); Qt.openUrlExternally(PinResetInformationModel.pinResetUrl); } + onReceivedFocus: pItem => root.positionViewAtItem(pItem) } } diff --git a/src/ui/qml/modules/PasswordInfoView/PasswordInfoData.qml b/src/ui/qml/modules/PasswordInfoView/PasswordInfoData.qml new file mode 100644 index 000000000..64cf78123 --- /dev/null +++ b/src/ui/qml/modules/PasswordInfoView/PasswordInfoData.qml @@ -0,0 +1,477 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQml +import Governikus.Animations +import Governikus.Type + +QtObject { + enum Type { + PIN, + SMART_PIN, + CHOOSE_PIN, + CHOOSE_SMART_PIN, + TRANSPORT_PIN, + TRANSPORT_PIN_NOT_WORKING, + PUK, + CAN, + CAN_ALLOWED, + CHANGE_PIN, + SMART_BLOCKING_CODE, + NO_PIN, + EMPTY + } + + readonly property url buttonLink: infoContent.buttonLink + readonly property string buttonText: infoContent.buttonText + readonly property list content: [ + PasswordInfoContent { + id: empty + + linkText: "" + }, + PasswordInfoContent { + id: pinInfo + + hint: PinResetInformationModel.pinResetHint + hintButtonText: PinResetInformationModel.pinResetActionText + //: LABEL ALL_PLATFORMS + hintTitle: qsTr("I can't recall my PIN") + + //: LABEL ALL_PLATFORMS + linkText: qsTr("What is the card PIN?") + //: LABEL ALL_PLATFORMS + title: qsTr("What is the card PIN?") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_PIN + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("What is the card PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'what is the card pin?' + qsTr("The card PIN is a 6-digit PIN that you set yourself. You always need this %1PIN%2 if you want to use the %1eID function%2.").arg("").arg("")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Where can I find the card PIN?") + paragraphList: { + if (ApplicationModel.isSmartSupported) { + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' (%1 is replaced with the application name) + return [qsTr("You set the card PIN either directly when you picked up your ID card at the citizens' office (Bürgeramt) or later in %1 using the 5-digit Transport PIN. Only when you have set a 6-digit PIN of your own choice can you use the eID function and set up a Smart-eID.").arg(Qt.application.name)]; + } + return [ + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Intro + qsTr("The card PIN was %1either%2...").arg("").arg(""), + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 1/3 + " • %1".arg(qsTr("set by you when picking up the ID card %1at the citiziens' office%2").arg("").arg("")), + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 2/3 + " • %1".arg(qsTr("set %1in the %3 using%2 the 5-digit %1Transport PIN%2").arg("").arg("").arg(Qt.application.name)), + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the card PIN?' - Parapgraph 3/3 + " • %1".arg(qsTr("requested using the %1PIN Reset Service%2 - you may continue using the 6-digit card PIN from the letter or change it via \"Change PIN\" to a self chosen card PIN").arg("").arg(""))]; + } + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("I just have a 5-digit Transport PIN") + paragraphList: [ + //: INFO ALL_PLATFORMS Explanation if only the Transport PIN is at hand + qsTr("You need to change the %1 5-digit Transport PIN%2 to your personal card PIN. Use %1Change PIN > Transport PIN%2 from the startpage to do so.").arg("").arg("")] + } + ] + }, + PasswordInfoContent { + id: smartPinInfo + + //: LABEL ALL_PLATFORMS Hint text for PIN but it is unknown. + hint: qsTr("If you have forgotten your Smart-eID PIN, you can renew your Smart-eID and thereby set a new PIN.") + //: LABEL ALL_PLATFORMS + linkText: qsTr("What is the Smart-eID PIN?") + //: LABEL ALL_PLATFORMS + title: qsTr("PIN information") + + contentList: [ + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("What is the Smart-eID PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' + qsTr("The Smart-eID PIN is a 6-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID.")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Where can I find the Smart-eID PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the Smart-eID PIN?' + qsTr("You have set the Smart-eID PIN while setting up the Smart-eID.")] + } + ] + }, + PasswordInfoContent { + id: choosePinInfo + + //: LABEL ALL_PLATFORMS + linkText: qsTr("How do I choose a secure PIN?") + + //: LABEL ALL_PLATFORMS + title: qsTr("PIN information") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_NEW_PIN + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("How do I choose a secure PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 1/3 + qsTr("For your 6-digit PIN, choose a combination of numbers that cannot be guessed - i.e. neither \"123456\", nor your date of birth, nor any other numbers printed on your ID card."), + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 2/3 + qsTr("You can change your 6-digit PIN at any time and an unlimited number of times as long as you know your valid PIN."), + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure PIN?' paragraph 3/3 + qsTr("Keep your PIN secret and change it if another person becomes aware of it.")] + } + ] + }, + PasswordInfoContent { + id: chooseSmartPinInfo + + //: LABEL ALL_PLATFORMS + linkText: qsTr("What is the Smart-eID PIN?") + + //: LABEL ALL_PLATFORMS + title: qsTr("Set up Smart-eID") + + contentList: [ + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("What is the Smart-eID PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'what is the Smart-eID pin?' + qsTr("The Smart-eID PIN is a 6-digit PIN that you set yourself. You always need this PIN if you want to use your Smart-eID.")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("How do I choose a secure PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 1/3 + qsTr("For your 6-digit Smart-eID PIN, choose a combination of numbers that cannot be guessed - i.e. neither \"123456\", nor your date of birth, nor any other numbers printed on your ID card."), + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 2/3 + qsTr("You can change your 6-digit Smart-eID PIN at any time and an unlimited number of times as long as you know your valid Smart-eID PIN."), + //: INFO ALL_PLATFORMS Answer to the question 'How do I choose a secure (Smart-eID) PIN?' paragraph 3/3 + qsTr("Keep your PIN secret and change it if another person becomes aware of it.")] + } + ] + }, + PasswordInfoContent { + id: transportPinInfo + + hint: PinResetInformationModel.pinResetHintTransportPin + hintButtonText: PinResetInformationModel.pinResetActionText + hintTitle: qsTr("I can't recall my PIN") + + //: LABEL ALL_PLATFORMS + linkText: qsTr("What is the Transport PIN?") + //: LABEL ALL_PLATFORMS + title: qsTr("What is the Transport PIN?") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_TRANSPORT_PIN + //: LABEL ALL_PLATFORMS + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'What is the Transport PIN?' + qsTr("The Transport PIN is a %1one-time PIN%2 which is required for the initial %1setup of your ID card%2. Once you replace the %1Transport PIN with a card PIN%2, it is tied to your ID card and valid for all devices.").arg("").arg("")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Where do I find the Transport PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 1/2 + qsTr("The 5-digit Transport PIN is a %1one-time PIN%2, that you reveived per %1letter%2 when applying for the ID card.").arg("").arg(""), + //: INFO ALL_PLATFORMS Answer to the question 'Where do I find the Transport PIN?' paragraph 2/2 + qsTr("When setting up your ID card, you will %1replace%2 this 5-digit %1Transport PIN with%2 a 6-digit, %1self chosen card PIN%2.").arg("").arg("")] + } + ] + }, + PasswordInfoContent { + id: transportPinNotWorkingInfo + + hint: PinResetInformationModel.pinResetHintTransportPin + hintButtonText: PinResetInformationModel.pinResetActionText + hintTitle: qsTr("I can't recall my PIN") + + //: LABEL ALL_PLATFORMS + linkText: qsTr("My Transport PIN does not work") + //: LABEL ALL_PLATFORMS + title: qsTr("My Transport PIN does not work") + + contentList: [ + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + paragraphList: [ + //: INFO ALL_PLATFORMS Introduction why the Transport PIN might not work. + qsTr("If your Transport PIN from the PIN letter does work, this might be caused by the following reasons:"), + //: INFO ALL_PLATFORMS Information why the Transport PIN is void: a 6-digit PIN was already set + " • %1".arg(qsTr("You already set a 6-digit PIN either at the competent authority or using the %1.").arg(Qt.application.name)), + //: INFO ALL_PLATFORMS Information why the Transport PIN is void: the PIN Reset Service was used + " • %1".arg(qsTr("You applied for PIN Reset Letter (letter containing a 6-digit PIN and corresponding Activation Code)."))] + }, + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_TRANSPORT_PIN + paragraphList: [ + //: INFO ALL_PLATFORMS Information that the Transport PIN is void once a 6-digit PIN was set. + qsTr("Once you set a 6-digit PIN, the Transport PIN is no longer valid. You may then only use the 6-digit PIN to authenticate yourself.")] + } + ] + }, + PasswordInfoContent { + id: pukInfo + + hint: PinResetInformationModel.noPinAndNoPukHint + hintButtonText: PinResetInformationModel.pinResetActionText + hintTitle: qsTr("I can't recall my PUK") + + //: LABEL ALL_PLATFORMS + linkText: qsTr("Where do I find the PUK?") + //: LABEL ALL_PLATFORMS + title: qsTr("Where do I find the PUK?") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_PUK + //: LABEL ALL_PLATFORMS + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Where do I find the PUK?' + qsTr("The PUK is a %1 10-digit number%2 that you can find in the %1PIN letter%2 that was sent to you by mail after you %1applied for your ID card%2. You may find it to the %1right%2 of the 5-digit %1Transport PIN%2.").arg("").arg("")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Why is the PUK required?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Why is the PUK required?' + qsTr("The PUK is required if the %1card PIN has been entered incorrectly 3 times%2 in a row. As a result, the card PIN is blocked. By entering the PUK you will %1unblock the card PIN%2 and have %1 3 more attempts%2 to enter the correct PIN.").arg("").arg("")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("My PUK does not work") + paragraphList: [ + //: INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + qsTr("Make sure, that the letter at hand is the %1letter for your current ID card%2. The PIN letter is valid only for your current ID card. With a new ID card, you receive a new PIN letter with a new PUK.").arg("").arg(""), + //: INFO ALL_PLATFORMS Text block regaring "My PUK does not work" + qsTr("If you applied for a PIN Reset letter, make sure that you don't mix up the letters. The %1PIN letter you need contains the 5-digit Transport PIN and the PUK%2. The PIN Reset letter contains the 6-digit card PIN and the activation code.").arg("").arg("")] + } + ] + }, + PasswordInfoContent { + id: canInfo + + //: LABEL ALL_PLATFORMS + linkText: qsTr("Why is the CAN required?") + //: LABEL ALL_PLATFORMS + title: qsTr("Why is the CAN required?") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_CAN + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'When is the card access number (CAN) required?' + qsTr("The card access number (CAN) is required when the %1card PIN has been entered incorrectly 2 times%2.").arg("").arg("")] + }, + PasswordInfoContentBlock { + blockImage: "qrc:///images/can_info.svg" + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Where can I find the CAN?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Where can I find the CAN?' + qsTr("The CAN is a 6-digit number that can be found on the %1bottom right%2 of the %1front of the ID card%2.").arg("").arg("")] + }, + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Why do I have to enter the CAN before a 3rd attempt?") + paragraphList: [ + //: INFO ALL_PLATFORMS Answer to the question 'Why do I have to enter the CAN before a 3rd attempt?' + qsTr("A 3rd incorrect entry blocks your PIN and you can no longer use the eID function until it is unblocked. Requesting the CAN ensures that %1direct access to your ID card%2 is given.").arg("").arg("")] + } + ] + }, + PasswordInfoContent { + id: canAllowedInfo + + //: LABEL ALL_PLATFORMS + linkText: qsTr("Why is the CAN required?") + //: LABEL ALL_PLATFORMS + title: qsTr("Why is the CAN required?") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_CAN + + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Why is the CAN required?") + paragraphList: [ + //: INFO ALL_PLATFORMS Description text of CAN-allowed authentication + qsTr("The Card Access Number (CAN) allows to access the imprinted data of the ID card. The CAN is a 6-digit number that can be found on the front of the ID card. It is located at the bottom right next to the validity date (marked in picture).")] + } + ] + }, + PasswordInfoContent { + id: changePinInfo + + hint: PinResetInformationModel.pinResetHintTransportPin + hintButtonText: PinResetInformationModel.pinResetActionText + //: LABEL ALL_PLATFORMS + hintTitle: qsTr("I can't recall my PIN") + + //: LABEL ALL_PLATFORMS + linkText: qsTr("How do the PIN types differ?") + //: LABEL ALL_PLATFORMS + title: qsTr("How do the PIN types differ?") + + contentList: [ + PasswordInfoContentBlock { + paragraphList: [ + //: INFO ALL_PLATFORMS Description text explaining the PINs 1/7 + qsTr("Your ID card comes with a 5-digit %1Transport PIN%2 which you need to %1replace with%2 a 6-digit %1card PIN%2 that you choose yourself.").arg("").arg("")] + }, + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_TRANSPORT_PIN + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("5-digit Transport PIN") + paragraphList: [ + //: INFO ALL_PLATFORMS Description text explaining the PINs 2/7 + qsTr("The 5-digit Transport PIN is a %1one-time PIN%2 that was sent to you by %1mail%2 after you applied for your ID card.").arg("").arg(""), + //: INFO ALL_PLATFORMS Description text explaining the PINs 3/7 + qsTr("When you set up the eID function, you will %1replace%2 this 5-digit %1Transport PIN%2 with a 6-digit %1card PIN that you choose yourself%2.").arg("").arg("")] + }, + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_PIN + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("6-digit PIN") + paragraphList: ApplicationModel.isSmartSupported ? [ + + //: INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + qsTr("The 6-digit card PIN is a %1number that you choose yourself%2 when you set up the eID function for the first time. It %1replaces%2 your %1 5-digit Transport PIN%2.").arg("").arg(""), + //: INFO ALL_PLATFORMS Description text explaining the PINs 5/7 + qsTr("The Smart-eID PIN also has six digits. You also choose that PIN yourself while setting up the Smart-eID for the first time."), + //: INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + qsTr("With this 6-digit PIN you prove online that the ID card or Smart-eID belongs to you. No one can use the eID function without this PIN."), + //: INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + qsTr("You can change your card PIN and your Smart-eID PIN at any time in %1.").arg(Qt.application.name)] : [ + + //: INFO ALL_PLATFORMS Description text explaining the PINs 4/7 + qsTr("The 6-digit card PIN is a %1number that you choose yourself%2 when you set up the eID function for the first time. It %1replaces%2 your %1 5-digit Transport PIN%2.").arg("").arg(""), + //: INFO ALL_PLATFORMS Description text explaining the PINs 6/7 + qsTr("With this 6-digit PIN you prove online that the ID card belongs to you. %1No one can use the eID function without this PIN%2.").arg("").arg(""), + //: INFO ALL_PLATFORMS Description text explaining the PINs (%1 is replaced with the application name) 7/7 + qsTr("If you applied for a %1PIN Reset letter%2, a new card PIN was already set for you. You can change your card PIN at %1any time in %3%2.").arg("").arg("").arg(Qt.application.name)] + } + ] + }, + PasswordInfoContent { + id: smartBlockingCodeInfo + + //: LABEL ANDROID IOS + title: qsTr("Smart-eID blocking code") + + contentList: [ + PasswordInfoContentBlock { + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("Smart-eID blocking code") + paragraphList: [ + //: INFO ANDROID IOS Description text of Smart-eID PIN + qsTr("Just like the physical ID card, the Smart-eID stored on your Smartphone can be blocked. This might be required if you ever lose your device."), + //: INFO ANDROID IOS Description text of Smart-eID PIN + qsTr("To revoke an active Smart-eID, a blocking code is required. The blocking code will be displayed after successfully creating the Smart-eID. Furthermore, it is contained in the letter you will receive after creation.")] + } + ] + }, + PasswordInfoContent { + id: noPin + + hint: PinResetInformationModel.pinResetHintNoPin + hintButtonText: PinResetInformationModel.pinResetActionText + hintTitle: qsTr("Set a new PIN") + + //: LABEL ALL_PLATFORMS + title: qsTr("No PIN known") + + contentList: [ + PasswordInfoContentBlock { + blockHeaderAnimation: AnimationLoader.Type.ENTER_NO_PIN + + //: LABEL ALL_PLATFORMS + blockTitle: qsTr("You do not know your PIN?") + paragraphList: [ + //: INFO ALL_PLATFORMS + qsTr("You have not yet set a 6-digit card PIN and cannot find the PIN letter with the Transport PIN?"), + //: INFO ALL_PLATFORMS + qsTr("You set a card PIN when picking up your ID card or later by yourself, but you can no longer remember it?")] + } + ] + } + ] + readonly property var contentList: infoContent.contentList + property int contentType + readonly property string hint: infoContent.hint + readonly property string hintButtonText: infoContent.hintButtonText + readonly property string hintTitle: infoContent.hintTitle + readonly property PasswordInfoContent infoContent: { + switch (contentType) { + case PasswordInfoData.Type.PIN: + return pinInfo; + case PasswordInfoData.Type.SMART_PIN: + return smartPinInfo; + case PasswordInfoData.Type.CHOOSE_PIN: + return choosePinInfo; + case PasswordInfoData.Type.CHOOSE_SMART_PIN: + return chooseSmartPinInfo; + case PasswordInfoData.Type.TRANSPORT_PIN: + return transportPinInfo; + case PasswordInfoData.Type.TRANSPORT_PIN_NOT_WORKING: + return transportPinNotWorkingInfo; + case PasswordInfoData.Type.PUK: + return pukInfo; + case PasswordInfoData.Type.CAN: + return canInfo; + case PasswordInfoData.Type.CAN_ALLOWED: + return canAllowedInfo; + case PasswordInfoData.Type.CHANGE_PIN: + return changePinInfo; + case PasswordInfoData.Type.SMART_BLOCKING_CODE: + return smartBlockingCodeInfo; + case PasswordInfoData.Type.NO_PIN: + return noPin; + case PasswordInfoData.Type.EMPTY: + return empty; + default: + return pinInfo; + } + } + readonly property string linkText: infoContent.linkText + readonly property string title: infoContent.title + + function fromPasswordType(pPasswordType, pIsCanAllowedMode = false) { + switch (pPasswordType) { + case NumberModel.PasswordType.PIN: + return PasswordInfoData.Type.PIN; + case NumberModel.PasswordType.SMART_PIN: + return PasswordInfoData.Type.SMART_PIN; + case NumberModel.PasswordType.CAN: + return pIsCanAllowedMode ? PasswordInfoData.Type.CAN_ALLOWED : PasswordInfoData.Type.CAN; + case NumberModel.PasswordType.PUK: + return PasswordInfoData.Type.PUK; + case NumberModel.PasswordType.NEW_PIN: + return PasswordInfoData.Type.CHOOSE_PIN; + case NumberModel.PasswordType.NEW_SMART_PIN: + return PasswordInfoData.Type.CHOOSE_SMART_PIN; + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: + return PasswordInfoData.Type.EMPTY; + case NumberModel.PasswordType.TRANSPORT_PIN: + return PasswordInfoData.Type.TRANSPORT_PIN; + case NumberModel.PasswordType.SMART_BLOCKING_CODE: + return PasswordInfoData.Type.SMART_BLOCKING_CODE; + default: + return PasswordInfoData.Type.PIN; + } + } +} diff --git a/resources/qml/Governikus/PasswordInfoView/PasswordInfoContent.qml b/src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContent.qml similarity index 57% rename from resources/qml/Governikus/PasswordInfoView/PasswordInfoContent.qml rename to src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContent.qml index 223c0c522..26c282bb8 100644 --- a/resources/qml/Governikus/PasswordInfoView/PasswordInfoContent.qml +++ b/src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContent.qml @@ -1,29 +1,15 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick QtObject { - enum Type { - PIN, - SMART_PIN, - CHOOSE_PIN, - CHOOSE_SMART_PIN, - TRANSPORT_PIN, - PUK, - CAN, - CAN_ALLOWED, - CHANGE_PIN, - SMART_BLOCKING_CODE, - NO_PIN, - EMPTY - } - property url buttonLink: "" property string buttonText: "" property list contentList property string hint: "" property string hintButtonText: "" + property string hintTitle: "" //: LABEL ALL_PLATFORMS property string linkText: qsTr("More information") diff --git a/src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContentBlock.qml b/src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContentBlock.qml new file mode 100644 index 000000000..789b1bd2a --- /dev/null +++ b/src/ui/qml/modules/PasswordInfoView/internal/PasswordInfoContentBlock.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Animations + +QtObject { + property int blockHeaderAnimation: AnimationLoader.Type.NONE + property url blockImage + property string blockTitle + property var paragraphList +} diff --git a/resources/qml/Governikus/ProgressView/+desktop/ProgressView.qml b/src/ui/qml/modules/ProgressView/+desktop/ProgressView.qml similarity index 55% rename from resources/qml/Governikus/ProgressView/+desktop/ProgressView.qml rename to src/ui/qml/modules/ProgressView/+desktop/ProgressView.qml index e21fd9806..586708b99 100644 --- a/resources/qml/Governikus/ProgressView/+desktop/ProgressView.qml +++ b/src/ui/qml/modules/ProgressView/+desktop/ProgressView.qml @@ -1,44 +1,61 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick -import QtQuick.Controls -import QtQuick.Layouts +import Governikus.Animations import Governikus.Global import Governikus.Style +import Governikus.Type import Governikus.View SectionPage { id: baseItem + property alias icon: statusIcon.source property alias progressBarVisible: progressBar.visible property alias progressText: progressText.text - property int progressValue + property alias progressValue: progressBar.value property alias subText: subText.text property alias subTextColor: subText.color property alias text: text.text + property alias tintColor: statusIcon.tintColor - TintableAnimation { - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.top - anchors.verticalCenterOffset: baseItem.height / 4 - fillMode: Image.PreserveAspectFit - height: Style.dimens.header_icon_size - source: "qrc:///images/sandglass.webp" - tintColor: Style.color.control + HourglassAnimation { + visible: !statusIcon.visible + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: Constants.component_spacing + } + } + TintableIcon { + id: statusIcon + + sourceSize.height: Style.dimens.header_icon_size + visible: source.toString() !== "" + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: Constants.component_spacing + } } GText { id: text Accessible.name: text.text activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.verticalCenter horizontalAlignment: Text.AlignHCenter textStyle: Style.text.headline visible: text.text !== "" width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.verticalCenter + topMargin: Constants.component_spacing * 2 + } FocusFrame { } } @@ -47,14 +64,16 @@ SectionPage { Accessible.name: subText.text activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: text.bottom - anchors.topMargin: Constants.text_spacing horizontalAlignment: Text.AlignHCenter textStyle: Style.text.subline visible: subText.text !== "" width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) + anchors { + horizontalCenter: parent.horizontalCenter + top: text.bottom + topMargin: Constants.text_spacing + } FocusFrame { } } @@ -63,13 +82,15 @@ SectionPage { Accessible.name: progressText.text activeFocusOnTab: true - anchors.bottom: progressBar.top - anchors.bottomMargin: Constants.component_spacing - anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter visible: progressBar.visible width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) + anchors { + bottom: progressBar.top + bottomMargin: Constants.component_spacing + horizontalCenter: parent.horizontalCenter + } FocusFrame { } } @@ -77,13 +98,12 @@ SectionPage { id: progressBar activeFocusOnTab: true - value: progressValue visible: false anchors { bottom: parent.bottom left: parent.left - margins: plugin.scaleFactor * 80 + margins: UiPluginModel.scaleFactor * 80 right: parent.right } } diff --git a/resources/qml/Governikus/ProgressView/+mobile/ProgressView.qml b/src/ui/qml/modules/ProgressView/+mobile/ProgressView.qml similarity index 77% rename from resources/qml/Governikus/ProgressView/+mobile/ProgressView.qml rename to src/ui/qml/modules/ProgressView/+mobile/ProgressView.qml index 57fc1f3d7..5bea7e894 100644 --- a/resources/qml/Governikus/ProgressView/+mobile/ProgressView.qml +++ b/src/ui/qml/modules/ProgressView/+mobile/ProgressView.qml @@ -1,9 +1,9 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick -import QtQuick.Controls import QtQuick.Layouts +import Governikus.Animations import Governikus.Global import Governikus.Style import Governikus.View @@ -14,18 +14,22 @@ FlickableSectionPage { property alias icon: statusIcon.source property alias progressBarVisible: progressBar.visible property alias progressText: progressText.text - property int progressValue + property alias progressValue: progressBar.value property alias subText: subText.text property alias subTextColor: subText.color property alias text: text.text - AnimatedImage { + HourglassAnimation { + Layout.alignment: Qt.AlignHCenter + visible: !statusIcon.visible + } + TintableIcon { id: statusIcon Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: Style.dimens.header_icon_size - fillMode: Image.PreserveAspectFit - source: "qrc:///images/sandglass.webp" + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + visible: source.toString() !== "" } GText { id: text @@ -52,7 +56,6 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.topMargin: 2 * Constants.component_spacing - value: progressValue visible: false } GText { diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/LocalNetworkInfo.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/LocalNetworkInfo.qml similarity index 65% rename from resources/qml/Governikus/RemoteServiceView/+mobile/LocalNetworkInfo.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/LocalNetworkInfo.qml index 5b4faf64e..07b783098 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/LocalNetworkInfo.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/LocalNetworkInfo.qml @@ -1,27 +1,28 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick +import QtQuick.Layouts import QtQuick.Controls -import Governikus.Type.ApplicationModel +import Governikus.Type import Governikus.Global import Governikus.Style -Column { +ColumnLayout { spacing: Constants.text_spacing GText { + Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter //: INFO IOS Let user know to check the application settings for local network permission text: qsTr("Ensure that access to the local network is allowed in your settings.") - width: parent.width } MoreInformationLink { - anchors.horizontalCenter: parent.horizontalCenter + Layout.alignment: Qt.AlignHCenter iconVisible: false //: INFO IOS Link to application settings text: qsTr("Go to application settings") - onClicked: ApplicationModel.showSettings(ApplicationModel.SETTING_APP) + onClicked: ApplicationModel.showSettings(ApplicationModel.Settings.APP) } } diff --git a/resources/qml/Governikus/RemoteServiceView/RemoteServiceSettings.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceSettings.qml similarity index 57% rename from resources/qml/Governikus/RemoteServiceView/RemoteServiceSettings.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceSettings.qml index aa8110f20..ffa75a1ea 100644 --- a/resources/qml/Governikus/RemoteServiceView/RemoteServiceSettings.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceSettings.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -11,6 +11,9 @@ import Governikus.View FlickableSectionPage { id: rootPage + signal pairingFailed + signal pairingSuccessful + //: LABEL ANDROID IOS title: qsTr("Manage pairings") @@ -22,5 +25,10 @@ FlickableSectionPage { RemoteServiceViewRemote { Layout.fillWidth: true + title: rootPage.title + + onPairingFailed: rootPage.pairingFailed() + onPairingSuccessful: rootPage.pairingSuccessful() + onReceivedFocus: pItem => rootPage.positionViewAtItem(pItem) } } diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceView.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceView.qml similarity index 71% rename from resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceView.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceView.qml index 965dfefb6..2a88d306e 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceView.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/RemoteServiceView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,13 +8,12 @@ import Governikus.Global import Governikus.TitleBar import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.RemoteServiceModel +import Governikus.Type FlickableSectionPage { id: baseItem - hiddenNavbarPadding: true + enableTileStyle: false //: LABEL ANDROID IOS title: qsTr("Card reader") @@ -30,16 +29,9 @@ FlickableSectionPage { when: RemoteServiceModel.running && RemoteServiceModel.isPairing PropertyChanges { - target: knownDevicesContainer - visible: false - } - PropertyChanges { - target: pairingCode - visible: true - } - PropertyChanges { - target: paringCodeLink - visible: true + knownDevicesContainer.visible: false + pairingCode.visible: true + paringCodeLink.visible: true } }, State { @@ -47,12 +39,8 @@ FlickableSectionPage { when: !RemoteServiceModel.running || (RemoteServiceModel.running && RemoteServiceModel.connectedToPairedDevice) PropertyChanges { - target: wifiInfo - visible: false - } - PropertyChanges { - target: networkPermissionText - visible: false + networkPermissionText.visible: false + wifiInfo.visible: false } } ] @@ -61,10 +49,6 @@ FlickableSectionPage { function onFireIsRunningChanged() { setLockedAndHidden(RemoteServiceModel.running); } - function onFirePairingFailed() { - //: ERROR ANDROID IOS An error occurred while pairing the device. - ApplicationModel.showFeedback(qsTr("Pairing failed. Please start a new pairing process on your other device and enter the shown pairing code.")); - } target: RemoteServiceModel } @@ -80,13 +64,13 @@ FlickableSectionPage { //: LABEL ANDROID IOS RemoteServiceModel.canEnableNfc ? qsTr("NFC not active") : //: LABEL ANDROID IOS - !RemoteServiceModel.runnable ? qsTr("Remote service not available") : + !RemoteServiceModel.runnable ? qsTr("NFC is not available") : //: LABEL ANDROID IOS RemoteServiceModel.connectedToPairedDevice ? qsTr("Card access in progress") : //: LABEL ANDROID IOS RemoteServiceModel.isPairing ? qsTr("Waiting for pairing") : //: LABEL ANDROID IOS - RemoteServiceModel.running ? qsTr("Waiting for connection") : "" + RemoteServiceModel.running ? qsTr("Card reader ready") : "" ColumnLayout { spacing: Constants.component_spacing @@ -94,18 +78,17 @@ FlickableSectionPage { TintableIcon { Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: Style.dimens.medium_icon_size - fillMode: Image.PreserveAspectFit + Layout.topMargin: Constants.text_spacing source: "qrc:///images/phone_to_pc.svg" sourceSize.height: Style.dimens.medium_icon_size - tintColor: Style.color.control + tintColor: Style.color.image } GText { id: infoText readonly property string currentPin: RemoteServiceModel.psk //: INFO ANDROID IOS - readonly property string enterCodeString: qsTr("Enter the pairing code %1 in the %2 on your other device.") + readonly property string enterCodeString: qsTr("Enter the pairing code \"%1\" in the %2 on your other device.") Accessible.name: text Layout.alignment: Qt.AlignHCenter @@ -113,59 +96,47 @@ FlickableSectionPage { horizontalAlignment: Text.AlignHCenter //: INFO ANDROID IOS text: qsTr("You can use this Smartphone as a card reader for the %1 on other devices e.g. a laptop.\n\nTo do this you first have to pair that device with this smartphone.").arg(Qt.application.name) - textStyle: RemoteServiceModel.runnable ? Style.text.normal : Style.text.normal_warning states: [ State { when: !RemoteServiceModel.runnable && RemoteServiceModel.errorMessage !== "" PropertyChanges { - target: infoText - text: RemoteServiceModel.errorMessage + infoText.text: RemoteServiceModel.errorMessage } }, State { when: RemoteServiceModel.running && RemoteServiceModel.connectedToPairedDevice PropertyChanges { - target: infoText - text: RemoteServiceModel.connectionInfo + infoText.text: RemoteServiceModel.connectionInfo } }, State { when: RemoteServiceModel.isPairing PropertyChanges { - Accessible.name: enterCodeString.arg(currentPin.split("").join(" ")).arg(Qt.application.name) - target: infoText - text: enterCodeString.arg(currentPin).arg(Qt.application.name) + infoText.Accessible.name: infoText.enterCodeString.arg(infoText.currentPin.split("").join(" ")).arg(Qt.application.name) + infoText.text: infoText.enterCodeString.arg(infoText.currentPin).arg(Qt.application.name) } }, State { when: !RemoteServiceModel.running && knownDeviceList.count > 0 PropertyChanges { - target: infoText //: INFO ANDROID IOS - text: qsTr("Allow a connection with paired devices to use this Smartphone as a card reader or pair another device.") + infoText.text: qsTr("Allow a connection with paired devices to use this Smartphone as a card reader or pair another device.") } }, State { when: RemoteServiceModel.running && knownDeviceList.count > 0 PropertyChanges { - target: infoText + infoText.text: "%1\n\n%2" //: INFO ANDROID IOS - text: qsTr("Paired devices may use this Smartphone as a card reader now.") - } - }, - State { - when: RemoteServiceModel.running - - PropertyChanges { - target: infoText + .arg(qsTr("Paired devices may use this Smartphone as a card reader now.")) //: INFO ANDROID IOS - text: qsTr("Waiting for connection from a paired device...") + .arg(qsTr("To do this, start a process on a paired device.")) } } ] @@ -173,7 +144,7 @@ FlickableSectionPage { GText { id: pairingCode - readonly property string currentPin: RemoteServiceModel.psk.toString() + readonly property string currentPin: RemoteServiceModel.psk Accessible.ignored: true Layout.alignment: Qt.AlignHCenter @@ -229,26 +200,27 @@ FlickableSectionPage { model: RemoteServiceModel.allDevices delegate: DevicesListDelegate { + Layout.fillWidth: true highlightTitle: isLastAddedDevice linkQualityVisible: false title: remoteDeviceName } } - GButton { + GLink { //: LABEL ANDROID IOS Accessible.name: qsTr("Start pairing of a new device") Layout.alignment: Qt.AlignLeft Layout.topMargin: knownDevices.spacing - background: null icon.source: "qrc:///images/material_add.svg" padding: 0 //: LABEL ANDROID IOS text: qsTr("Pair new device") - textStyle: Style.text.link tintIcon: true visible: !RemoteServiceModel.isPairing && !RemoteServiceModel.running onClicked: RemoteServiceModel.setRunning(!RemoteServiceModel.running, !RemoteServiceModel.isPairing) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } } } @@ -265,7 +237,6 @@ FlickableSectionPage { id: networkPermissionText Layout.bottomMargin: Constants.text_spacing - Layout.fillWidth: true Layout.topMargin: Constants.component_spacing visible: RemoteServiceModel.requiresLocalNetworkPermission } @@ -298,60 +269,67 @@ FlickableSectionPage { when: !ApplicationModel.wifiEnabled PropertyChanges { - target: pairConnectButton //: LABEL ANDROID IOS - text: qsTr("Enable WiFi") + pairConnectButton.text: qsTr("Enable WiFi") - onClicked: ApplicationModel.enableWifi() + pairConnectButton.onClicked: ApplicationModel.enableWifi() } }, State { when: RemoteServiceModel.canEnableNfc PropertyChanges { - target: pairConnectButton //: LABEL ANDROID IOS - text: qsTr("Enable NFC") + pairConnectButton.text: qsTr("Enable NFC") - onClicked: ApplicationModel.showSettings(ApplicationModel.SETTING_NFC) + pairConnectButton.onClicked: ApplicationModel.showSettings(ApplicationModel.Settings.NFC) } }, State { when: RemoteServiceModel.runnable && knownDeviceList.count > 0 && !RemoteServiceModel.isPairing && !RemoteServiceModel.running PropertyChanges { - target: pairConnectButton //: LABEL ANDROID IOS - text: qsTr("Allow connection") + pairConnectButton.text: qsTr("Activate card reader") - onClicked: RemoteServiceModel.setRunning(true) + pairConnectButton.onClicked: RemoteServiceModel.setRunning(true) } }, State { when: RemoteServiceModel.runnable && knownDeviceList.count < 1 && !RemoteServiceModel.isPairing PropertyChanges { - target: pairConnectButton //: LABEL ANDROID IOS - text: qsTr("Pair device") + pairConnectButton.text: qsTr("Pair device") - onClicked: RemoteServiceModel.setRunning(true, true) + pairConnectButton.onClicked: RemoteServiceModel.setRunning(true, true) } }, State { when: RemoteServiceModel.isPairing PropertyChanges { - target: pairConnectButton //: LABEL ANDROID IOS - text: qsTr("Cancel pairing") - visible: true + pairConnectButton.text: qsTr("Cancel pairing") + pairConnectButton.visible: true + + pairConnectButton.onClicked: RemoteServiceModel.setRunning(false, false) + } + }, + State { + when: RemoteServiceModel.running + + PropertyChanges { + //: LABEL ANDROID IOS + pairConnectButton.text: qsTr("Stop card reader") - onClicked: RemoteServiceModel.setRunning(false, false) + pairConnectButton.onClicked: RemoteServiceModel.setRunning(false, false) } } ] onClicked: RemoteServiceModel.setRunning(true, !RemoteServiceModel.isPairing) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } } diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/DevicesListDelegate.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/DevicesListDelegate.qml similarity index 85% rename from resources/qml/Governikus/RemoteServiceView/+mobile/DevicesListDelegate.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/internal/DevicesListDelegate.qml index c80fa867b..bb032abca 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/DevicesListDelegate.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/DevicesListDelegate.qml @@ -1,11 +1,12 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.View MouseArea { id: root @@ -19,11 +20,16 @@ MouseArea { Accessible.name: qsTr("Device %1. %2.").arg(title).arg(description) Accessible.role: Accessible.ListItem + activeFocusOnTab: true implicitHeight: content.implicitHeight implicitWidth: content.implicitWidth Accessible.onPressAction: clicked(null) + Keys.onSpacePressed: clicked(null) + FocusFrame { + marginFactor: 3 + } RowLayout { id: content @@ -40,6 +46,7 @@ MouseArea { Accessible.ignored: true elide: Text.ElideRight maximumLineCount: 1 + textFormat: Text.PlainText textStyle: Style.text.subline } GText { diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/PairingCodeInfoView.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingCodeInfoView.qml similarity index 78% rename from resources/qml/Governikus/RemoteServiceView/+mobile/PairingCodeInfoView.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingCodeInfoView.qml index 06578fbce..cbf5f0955 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/PairingCodeInfoView.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingCodeInfoView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,14 +8,14 @@ import Governikus.Global import Governikus.TitleBar import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel +import Governikus.Type FlickableSectionPage { + readonly property string currentPin: RemoteServiceModel.psk property alias text: descriptionContainer.title signal navActionClicked - hiddenNavbarPadding: true spacing: Constants.component_spacing //: LABEL ANDROID IOS @@ -42,19 +42,20 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter Layout.maximumWidth: parent.width Layout.preferredHeight: Style.dimens.medium_icon_size - fillMode: Image.PreserveAspectFit source: "qrc:///images/phone_to_pc.svg" sourceSize.height: Style.dimens.medium_icon_size - tintColor: Style.color.control + tintColor: Style.color.image } Repeater { model: [ - //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 3 + //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4 qsTr("Open %1 on your %2other device%3.").arg(Qt.application.name).arg("").arg(""), - //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 3. %1 and %2 are surrounding tags for bold font. + //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 and %2 are surrounding tags for bold font. qsTr("On that device go to %1Settings%2 and then %1Smartphone as card reader%2 resp. %1Manage pairings%2.").arg("").arg(""), - //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 3 - qsTr("Choose this smartphone in the list to pair it.")] + //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4 + qsTr("Choose this smartphone in the list to pair it."), + //: LABEL ANDROID IOS Provide pairing code. Step 4 of 4 + qsTr("Enter the pairing code \"%1\".").arg(currentPin)] GText { Accessible.name: ApplicationModel.stripHtmlTags(text) diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/PairingProcessInfo.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingProcessInfo.qml similarity index 86% rename from resources/qml/Governikus/RemoteServiceView/+mobile/PairingProcessInfo.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingProcessInfo.qml index ef2f177e4..4b1eff66c 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/PairingProcessInfo.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/PairingProcessInfo.qml @@ -1,17 +1,17 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type ColumnLayout { Repeater { model: [ //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4. %1 is a placeholder-tag for the app name. - qsTr("Ensure that the %1 on your Smartphone as card reader has at least version %2.").arg(Qt.application.name).arg("1.26.5"), + qsTr("Ensure that the %1 on your Smartphone as card reader has at least version %2.").arg(Qt.application.name).arg("2.1.0"), //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 is a placeholder-tag for the app name. qsTr("Open %1 on your smartphone as card reader.").arg(Qt.application.name), //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4. %1 and %2 are surrounding tags for bold font. diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceViewRemote.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceViewRemote.qml similarity index 74% rename from resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceViewRemote.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceViewRemote.qml index f3494155d..985e42b24 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceViewRemote.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceViewRemote.qml @@ -1,27 +1,37 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.EnterPasswordView import Governikus.Global import Governikus.PasswordInfoView +import Governikus.ProgressView import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.RemoteServiceModel +import Governikus.Type Item { id: baseItem + property string title + + signal pairingFailed + signal pairingSuccessful + signal receivedFocus(var pItem) + implicitHeight: mainColumn.implicitHeight QtObject { id: d property bool oldLockedAndHiddenStatus + + function close(pSignal) { + setLockedAndHidden(oldLockedAndHiddenStatus); + pop(); + pSignal(); + } } Column { id: mainColumn @@ -121,7 +131,7 @@ Item { GListView { id: searchDeviceList - height: childrenRect.height + height: contentHeight model: RemoteServiceModel.availableDevicesInPairingMode spacing: Constants.component_spacing visible: ApplicationModel.wifiEnabled && count > 0 @@ -146,7 +156,6 @@ Item { GText { //: INFO ANDROID IOS Wifi is not enabled and no new devices can be paired. text: qsTr("Please connect your WiFi to use another smartphone as card reader (SaC).") - textStyle: Style.text.normal_warning visible: !ApplicationModel.wifiEnabled width: parent.width } @@ -158,9 +167,10 @@ Item { visible: !ApplicationModel.wifiEnabled onClicked: ApplicationModel.enableWifi() + onFocusChanged: if (focus) + baseItem.receivedFocus(this) } LocalNetworkInfo { - topPadding: Constants.component_spacing visible: RemoteServiceModel.requiresLocalNetworkPermission && !RemoteServiceModel.remoteReaderVisible width: parent.width } @@ -178,22 +188,72 @@ Item { id: enterPinView EnterPasswordView { - function close() { - setLockedAndHidden(d.oldLockedAndHiddenStatus); - pop(); - } - - passwordType: PasswordType.REMOTE_PIN + passwordType: NumberModel.PasswordType.REMOTE_PIN //: LABEL ANDROID IOS title: qsTr("Pairing code") navigationAction: NavigationAction { action: NavigationAction.Action.Cancel - onClicked: close() + onClicked: d.close(pairingFailed) + } + + onPasswordEntered: replace(pairingProgressView) + } + } + Component { + id: pairingProgressView + + ProgressView { + //: LABEL ANDROID IOS + text: qsTr("Pairing the device ...") + title: baseItem.title + + Connections { + function onFirePairingFailed(pDeviceName, pErrorMessage) { + replace(pairingFailedView, { + "deviceName": pDeviceName, + "errorMessage": pErrorMessage + }); + } + function onFirePairingSuccess(pDeviceName) { + replace(pairingSuccessView, { + "deviceName": pDeviceName + }); + } + + target: RemoteServiceModel + } + } + } + Component { + id: pairingFailedView + + PairingFailedView { + title: baseItem.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Back + + onClicked: d.close(pairingFailed) + } + + onContinueClicked: d.close(pairingFailed) + } + } + Component { + id: pairingSuccessView + + PairingSuccessView { + title: baseItem.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Back + + onClicked: d.close(pairingSuccessful) } - onPasswordEntered: close() + onContinueClicked: d.close(pairingSuccessful) } } } diff --git a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceWifiInfo.qml b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceWifiInfo.qml similarity index 64% rename from resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceWifiInfo.qml rename to src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceWifiInfo.qml index 1add943ea..01f4293ce 100644 --- a/resources/qml/Governikus/RemoteServiceView/+mobile/RemoteServiceWifiInfo.qml +++ b/src/ui/qml/modules/RemoteServiceView/+mobile/internal/RemoteServiceWifiInfo.qml @@ -1,3 +1,7 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + import QtQuick import QtQuick.Layouts import Governikus.Global @@ -8,16 +12,16 @@ RowLayout { TintableIcon { source: "qrc:/images/info.svg" - sourceSize.width: Style.dimens.medium_icon_size + sourceSize.width: Style.dimens.icon_size tintColor: infoText.color } GText { id: infoText - color: Style.color.text_subline + color: Style.color.textSubline.basic //: INFO ANDROID IOS The remote service is active. Hint that both devices need to be connected to the same network. - text: qsTr("Both devices have to be connected to the same WiFi.") + text: qsTr("Both devices have to be on the same network (e.g. WiFi).") } GSpacer { Layout.fillWidth: true diff --git a/resources/qml/Governikus/RemoteServiceView/LinkQuality.qml b/src/ui/qml/modules/RemoteServiceView/LinkQuality.qml similarity index 78% rename from resources/qml/Governikus/RemoteServiceView/LinkQuality.qml rename to src/ui/qml/modules/RemoteServiceView/LinkQuality.qml index b99e10c02..10f5aabe3 100644 --- a/resources/qml/Governikus/RemoteServiceView/LinkQuality.qml +++ b/src/ui/qml/modules/RemoteServiceView/LinkQuality.qml @@ -1,8 +1,9 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style +import Governikus.Type Image { id: img @@ -15,6 +16,9 @@ Image { if (inactive) { return "qrc:///images/icon_remote_inactive_%1.svg".arg(Style.currentTheme.name); } + if (!SettingsModel.useAnimations && percent >= 20) { + return "qrc:///images/icon_remote_100_%1.svg".arg(Style.currentTheme.name); + } if (percent >= 80) { return "qrc:///images/icon_remote_100_%1.svg".arg(Style.currentTheme.name); } diff --git a/src/ui/qml/modules/RemoteServiceView/PairingFailedView.qml b/src/ui/qml/modules/RemoteServiceView/PairingFailedView.qml new file mode 100644 index 000000000..709053576 --- /dev/null +++ b/src/ui/qml/modules/RemoteServiceView/PairingFailedView.qml @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +import Governikus.Style +import Governikus.ResultView + +ResultView { + id: root + + required property string deviceName + required property string errorMessage + + icon: "qrc:///images/workflow_error_sak_connection_%1.svg".arg(Style.currentTheme.name) + + //: ERROR ALL_PLATFORMS An error occurred while pairing the device. + text: qsTr("Pairing to \"%1\" failed:").arg(deviceName) + "
%1".arg(errorMessage) +} diff --git a/src/ui/qml/modules/RemoteServiceView/PairingSuccessView.qml b/src/ui/qml/modules/RemoteServiceView/PairingSuccessView.qml new file mode 100644 index 000000000..e68b9ab10 --- /dev/null +++ b/src/ui/qml/modules/RemoteServiceView/PairingSuccessView.qml @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +import Governikus.ResultView + +ResultView { + id: root + + required property string deviceName + + icon: "qrc:///images/phone_to_pc.svg" + + //: INFO ALL_PLATFORMS The pairing with the SaC server was successful. + text: qsTr("Pairing with \"%1\" successful, it will be listed under \"Paired devices\".").arg(deviceName) + "
" + qsTr("The device may now be used as a card reader.") +} diff --git a/resources/qml/Governikus/RemoteServiceView/RemoteServiceController.qml b/src/ui/qml/modules/RemoteServiceView/internal/RemoteServiceController.qml similarity index 87% rename from resources/qml/Governikus/RemoteServiceView/RemoteServiceController.qml rename to src/ui/qml/modules/RemoteServiceView/internal/RemoteServiceController.qml index d30fbbd52..2700646da 100644 --- a/resources/qml/Governikus/RemoteServiceView/RemoteServiceController.qml +++ b/src/ui/qml/modules/RemoteServiceView/internal/RemoteServiceController.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -10,19 +10,14 @@ import Governikus.Style import Governikus.TitleBar import Governikus.View import Governikus.Workflow -import Governikus.Type.ChatModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.ReaderPlugIn -import Governikus.Type.RemoteServiceModel -import Governikus.Type.SettingsModel +import Governikus.Type Controller { id: controller readonly property bool editRightsShown: stackView.currentItem instanceof EditRights readonly property bool enterPasswordShown: stackView.currentItem instanceof EnterPasswordView - readonly property bool isSmartWorkflow: RemoteServiceModel.readerPlugInType === ReaderPlugIn.SMART + readonly property bool isSmartWorkflow: RemoteServiceModel.readerPluginType === ReaderManagerPluginType.SMART readonly property bool workflowShown: stackView.currentItem instanceof GeneralWorkflow function processStateChange(pState) { @@ -64,9 +59,8 @@ Controller { function requestInput(pState) { if (RemoteServiceModel.isBasicReader && RemoteServiceModel.pinPadModeOn()) { push(enterPinView, { - "passwordType": NumberModel.passwordType, - "inputError": NumberModel.inputError - }); + "passwordType": NumberModel.passwordType + }); } else { RemoteServiceModel.continueWorkflow(); } @@ -126,7 +120,7 @@ Controller { id: generalWorkflow GeneralWorkflow { - smartEidUsed: RemoteServiceModel.readerPlugInType === ReaderPlugIn.SMART + smartEidUsed: RemoteServiceModel.readerPluginType === ReaderManagerPluginType.SMART workflowModel: RemoteServiceModel //: LABEL ANDROID IOS workflowTitle: qsTr("Remote service") @@ -185,18 +179,19 @@ Controller { } onPasswordEntered: pPasswordType => { switch (pPasswordType) { - case PasswordType.NEW_PIN: - case PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: controller.processStateChange(RemoteServiceModel.currentState); break; - case PasswordType.NEW_PIN_CONFIRMATION: - case PasswordType.NEW_SMART_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: if (NumberModel.commitNewPin()) { popAll(); RemoteServiceModel.startScanExplicitly(); RemoteServiceModel.continueWorkflow(); } else { - controller.processStateChange(RemoteServiceModel.currentState); + popAll(); + RemoteServiceModel.passwordsDiffer(); } break; default: diff --git a/src/ui/qml/modules/ResultView/+desktop/ResultView.qml b/src/ui/qml/modules/ResultView/+desktop/ResultView.qml new file mode 100644 index 000000000..7d4ef9eec --- /dev/null +++ b/src/ui/qml/modules/ResultView/+desktop/ResultView.qml @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQml +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Governikus.Global +import Governikus.TitleBar +import Governikus.Style +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + property alias buttonIcon: button.icon.source + property alias buttonText: button.text + property alias header: resultHeader.text + property alias hintButtonText: hintItem.buttonText + property alias hintText: hintItem.text + property alias hintTitle: hintItem.title + property alias icon: headerIcon.source + property alias mailButtonVisible: mailButton.visible + property string popupText + property string popupTitle + property alias showOkButton: button.visible + property alias subheader: subheader.text + property alias text: resultText.text + property alias textColor: resultText.color + + signal emailButtonPressed + signal hintClicked + + function confirm() { + button.clicked(); + } + + spacing: Constants.pane_spacing + + Keys.onEnterPressed: button.clicked() + Keys.onEscapePressed: button.clicked() + Keys.onReturnPressed: button.clicked() + + GText { + id: resultHeader + + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + textStyle: Style.text.headline + visible: text !== "" + + FocusFrame { + } + } + TintableIcon { + id: headerIcon + + Layout.alignment: Qt.AlignHCenter + sourceSize.height: Style.dimens.header_icon_size + tintEnabled: false + visible: source.toString() !== "" + } + GSpacer { + Layout.fillHeight: true + } + GText { + id: subheader + + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + textStyle: Style.text.subline + visible: text !== "" + + Accessible.onIgnoredChanged: baseItem.visibleChanged() + + FocusFrame { + } + } + GText { + id: resultText + + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + visible: text !== "" + + Accessible.onIgnoredChanged: baseItem.visibleChanged() + + FocusFrame { + } + } + RowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + spacing: Constants.component_spacing + visible: popupTitle !== "" || popupText !== "" + + GButton { + id: mailButton + + icon.source: "qrc:///images/email_icon.svg" + //: LABEL DESKTOP + text: qsTr("Send email") + tintIcon: true + visible: false + + onClicked: baseItem.emailButtonPressed() + } + GButton { + icon.source: "qrc:/images/desktop/save_icon.svg" + //: LABEL DESKTOP + text: qsTr("Save log") + tintIcon: true + + onClicked: { + LogModel.setLogFile(0); + let filenameSuggestion = LogModel.createLogFileName(LogModel.getCurrentLogFileDate()); + fileDialog.selectFile(filenameSuggestion); + } + + GFileDialog { + id: fileDialog + + defaultSuffix: "log" + //: LABEL DESKTOP + nameFilters: qsTr("Logfiles (*.log)") + + //: LABEL DESKTOP + title: qsTr("Save log") + + onAccepted: LogModel.saveCurrentLogFile(file) + } + } + GButton { + property QtObject popup: null + + function destroyPopup() { + if (popup) { + popup.close(); + popup.destroy(); + popup = null; + } + } + + icon.source: "qrc:/images/info.svg" + //: LABEL DESKTOP + text: qsTr("See details") + tintIcon: true + visible: popupTitle !== "" || popupText !== "" + + onClicked: { + destroyPopup(); + popup = detailedResultPopup.createObject(baseItem, { + "text": popupText, + "title": popupTitle + }); + popup.open(); + } + onVisibleChanged: destroyPopup() + } + } + GSpacer { + Layout.fillHeight: true + } + Hint { + id: hintItem + + Layout.fillWidth: true + //: LABEL DESKTOP + title: qsTr("Hint") + visible: text !== "" + + onClicked: baseItem.hintClicked() + } + GButton { + id: button + + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: height + Layout.preferredWidth: width + activeFocusOnTab: true + text: qsTr("OK") + tintIcon: true + + onClicked: baseItem.nextView(UiModule.DEFAULT) + } + Component { + id: detailedResultPopup + + ConfirmationPopup { + style: ConfirmationPopup.PopupStyle.OkButton + } + } +} diff --git a/resources/qml/Governikus/ResultView/+mobile/ResultErrorView.qml b/src/ui/qml/modules/ResultView/+mobile/ResultErrorView.qml similarity index 72% rename from resources/qml/Governikus/ResultView/+mobile/ResultErrorView.qml rename to src/ui/qml/modules/ResultView/+mobile/ResultErrorView.qml index 1c6430d6f..86f5b4082 100644 --- a/resources/qml/Governikus/ResultView/+mobile/ResultErrorView.qml +++ b/src/ui/qml/modules/ResultView/+mobile/ResultErrorView.qml @@ -1,13 +1,14 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.TitleBar ResultView { - id: baseItem + id: root property string errorCode property alias errorDescription: textErrorDescription.text @@ -17,6 +18,11 @@ ResultView { signal mailClicked + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + enabled: false + } + onCancelClicked: continueClicked() onVisibleChanged: errorDetailsShown = false @@ -24,8 +30,10 @@ ResultView { Layout.fillWidth: true Layout.leftMargin: -Constants.pane_padding * 2 Layout.rightMargin: -Constants.pane_padding * 2 + arrowToLeft: true horizontalMargin: Constants.pane_padding * 2 - title: qsTr("Details") + //: LABEL ANDROID IOS + title: qsTr("Show Details") visible: hasErrorDetails GText { @@ -42,10 +50,12 @@ ResultView { id: mailButton Layout.alignment: Qt.AlignHCenter - icon.source: "qrc:///images/material_mail.svg" + icon.source: "qrc:///images/email_icon.svg" tintIcon: true visible: text !== "" onClicked: mailClicked() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/resources/qml/Governikus/ResultView/+mobile/ResultView.qml b/src/ui/qml/modules/ResultView/+mobile/ResultView.qml similarity index 71% rename from resources/qml/Governikus/ResultView/+mobile/ResultView.qml rename to src/ui/qml/modules/ResultView/+mobile/ResultView.qml index 3c54b3fa8..0e1d7775d 100644 --- a/resources/qml/Governikus/ResultView/+mobile/ResultView.qml +++ b/src/ui/qml/modules/ResultView/+mobile/ResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -17,7 +17,9 @@ FlickableSectionPage { property alias header: paneTitle.text property alias hintButtonText: hintItem.buttonText property alias hintText: hintItem.text + property alias hintTitle: hintItem.title property alias icon: customIcon.source + property alias subheader: subheader.text property alias text: resultText.text property alias textFormat: resultText.textFormat @@ -25,12 +27,23 @@ FlickableSectionPage { signal continueClicked signal hintClicked + function confirm() { + buttonContinue.clicked(); + } + + spacing: Constants.component_spacing + navigationAction: NavigationAction { action: NavigationAction.Action.Cancel onClicked: cancelClicked() } + PaneTitle { + id: paneTitle + + Layout.alignment: Qt.AlignHCenter + } TintableIcon { id: customIcon @@ -42,19 +55,18 @@ FlickableSectionPage { ColumnLayout { id: layout - Layout.margins: Constants.pane_padding + Layout.maximumWidth: Number.POSITIVE_INFINITY spacing: Constants.pane_spacing - PaneTitle { - id: paneTitle + GText { + id: subheader + textStyle: Style.text.subline + visible: text !== "" } GText { id: resultText - Layout.alignment: Qt.AlignCenter | Qt.AlignTop - Layout.maximumWidth: Style.dimens.max_text_width - Layout.topMargin: Constants.component_spacing visible: text !== "" } } @@ -64,19 +76,18 @@ FlickableSectionPage { Hint { id: hintItem - Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true - Layout.maximumWidth: Style.dimens.max_text_width - Layout.topMargin: Constants.component_spacing + //: LABEL ANDROID IOS + title: qsTr("Hint") visible: text !== "" onClicked: hintClicked() + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) } GButton { id: buttonContinue Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Constants.component_spacing //: LABEL ANDROID IOS text: qsTr("OK") @@ -84,5 +95,7 @@ FlickableSectionPage { visible: text !== "" onClicked: continueClicked() + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) } } diff --git a/src/ui/qml/modules/ResultView/InputErrorView.qml b/src/ui/qml/modules/ResultView/InputErrorView.qml new file mode 100644 index 000000000..0349771e1 --- /dev/null +++ b/src/ui/qml/modules/ResultView/InputErrorView.qml @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import QtQuick.Layouts +import Governikus.Animations +import Governikus.Global +import Governikus.PasswordInfoView +import Governikus.View +import Governikus.Style +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + required property string inputError + property bool isTransportPin: false + required property int passwordType + required property int returnCode + property alias titleVisible: title.visible + + signal continueClicked + signal passwordInfoRequested + + spacing: Constants.component_spacing + + PasswordInfoData { + id: infoData + + contentType: { + if (!isTransportPin) { + return fromPasswordType(passwordType); + } + switch (returnCode) { + case CardReturnCode.INVALID_CAN: + case CardReturnCode.INVALID_PUK: + return fromPasswordType(passwordType); + default: + return PasswordInfoData.Type.TRANSPORT_PIN_NOT_WORKING; + } + } + } + AnimationLoader { + id: animation + + Layout.alignment: Qt.AlignHCenter + Layout.bottomMargin: Constants.component_spacing + animated: false + symbol: EnterPasswordAnimation.Symbol.ERROR + type: { + switch (returnCode) { + case CardReturnCode.INVALID_PIN: + case CardReturnCode.INVALID_PIN_2: + case CardReturnCode.INVALID_PIN_3: + return isTransportPin ? AnimationLoader.Type.ENTER_TRANSPORT_PIN : AnimationLoader.Type.ENTER_PIN; + case CardReturnCode.INVALID_CAN: + return AnimationLoader.Type.ENTER_CAN; + case CardReturnCode.INVALID_PUK: + return AnimationLoader.Type.ENTER_PUK; + } + switch (passwordType) { + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: + return AnimationLoader.Type.ENTER_NEW_PIN; + } + return AnimationLoader.Type.NONE; + } + } + GText { + id: title + + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + text: { + switch (returnCode) { + case CardReturnCode.INVALID_CAN: + //: LABEL ALL_PLATFORMS + return qsTr("Wrong CAN"); + case CardReturnCode.INVALID_PUK: + //: LABEL ALL_PLATFORMS + return qsTr("Wrong PUK"); + case CardReturnCode.INVALID_PIN: + case CardReturnCode.INVALID_PIN_2: + case CardReturnCode.INVALID_PIN_3: + return isTransportPin ? + //: LABEL ALL_PLATFORMS + qsTr("Wrong Transport PIN") : smartEidUsed ? + //: LABEL ALL_PLATFORMS + qsTr("Wrong Smart-eID PIN") : + //: LABEL ALL_PLATFORMS + qsTr("Wrong ID card PIN"); + } + switch (passwordType) { + case NumberModel.PasswordType.NEW_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_PIN: + //: LABEL ALL_PLATFORMS + return qsTr("Wrong new ID card PIN confirmation"); + case NumberModel.PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: + //: LABEL ALL_PLATFORMS + return qsTr("Wrong new Smart-eID PIN confirmation"); + } + return ""; + } + textStyle: Style.text.headline + + FocusFrame { + } + } + GText { + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + text: inputError + + FocusFrame { + } + } + MoreInformationLink { + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + text: infoData.linkText + visible: text !== "" && (returnCode === CardReturnCode.INVALID_PUK || infoData.contentType === PasswordInfoData.Type.TRANSPORT_PIN_NOT_WORKING) + + onClicked: passwordInfoRequested() + + FocusFrame { + } + } + TintableIcon { + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: Constants.component_spacing + source: "qrc:///images/can_info.svg" + sourceSize.width: animation.width + tintColor: Style.color.image + tintEnabled: false + visible: !isTransportPin && (returnCode === CardReturnCode.INVALID_PIN_2 || returnCode === CardReturnCode.INVALID_CAN) + } + GSpacer { + Layout.fillHeight: true + } + GButton { + Layout.alignment: Qt.AlignHCenter + icon.source: "qrc:///images/material_arrow_right.svg" + layoutDirection: Qt.RightToLeft + + //: LABEL ALL_PLATFORMS + text: qsTr("Continue") + tintIcon: true + + onClicked: continueClicked() + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } +} diff --git a/src/ui/qml/modules/ResultView/InputSuccessView.qml b/src/ui/qml/modules/ResultView/InputSuccessView.qml new file mode 100644 index 000000000..30a04476b --- /dev/null +++ b/src/ui/qml/modules/ResultView/InputSuccessView.qml @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +import QtQuick +import QtQuick.Layouts +import Governikus.Animations +import Governikus.Global +import Governikus.View +import Governikus.Style +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + property bool isTransportPin: false + required property int passwordType + + signal continueClicked + + spacing: Constants.component_spacing + + AnimationLoader { + id: animation + + Layout.alignment: Qt.AlignHCenter + Layout.bottomMargin: Constants.component_spacing + animated: false + symbol: EnterPasswordAnimation.Symbol.CHECK + type: { + switch (passwordType) { + case NumberModel.PasswordType.CAN: + return AnimationLoader.Type.ENTER_CAN; + case NumberModel.PasswordType.PUK: + return AnimationLoader.Type.ENTER_PUK; + default: + return AnimationLoader.Type.NONE; + } + } + } + GText { + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + text: { + switch (passwordType) { + case NumberModel.PasswordType.CAN: + //: INFO ALL_PLATFORMS + return qsTr("CAN is correct"); + case NumberModel.PasswordType.PUK: + //: INFO ALL_PLATFORMS + return qsTr("PUK is correct"); + default: + return ""; + } + } + textStyle: Style.text.headline + + FocusFrame { + } + } + GText { + Layout.alignment: Qt.AlignHCenter + activeFocusOnTab: true + horizontalAlignment: Text.AlignHCenter + text: { + switch (passwordType) { + case NumberModel.PasswordType.CAN: + //: INFO ALL_PLATFORMS + return isTransportPin ? "%1

%2".arg(qsTr("Please enter your 5-digit Transport PIN. This is your last attempt.")).arg(qsTr("If you enter a wrong Transport PIN again, the PIN will be blocked. This block may only be removed using the PUK.")) : + //: INFO ALL_PLATFORMS + "%1

%2".arg(qsTr("Please enter your 6-digit ID card PIN. This is your last attempt.")).arg(qsTr("If you enter a wrong ID Card PIN again, the PIN will be blocked. This block may only be removed using the PUK.")); + case NumberModel.PasswordType.PUK: + //: INFO ALL_PLATFORMS + return isTransportPin ? qsTr("You now have 3 more attempts to enter your correct Transport PIN.") : + //: INFO ALL_PLATFORMS + qsTr("You now have 3 more attempts to enter your correct ID card PIN."); + default: + return ""; + } + } + + FocusFrame { + } + } + GSpacer { + Layout.fillHeight: true + } + GButton { + id: buttonContinue + + Layout.alignment: Qt.AlignHCenter + icon.source: "qrc:///images/material_arrow_right.svg" + layoutDirection: Qt.RightToLeft + + //: LABEL ALL_PLATFORMS + text: qsTr("Continue") + tintIcon: true + visible: text !== "" + + onClicked: continueClicked() + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } +} diff --git a/resources/qml/Governikus/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml b/src/ui/qml/modules/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml similarity index 85% rename from resources/qml/Governikus/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml rename to src/ui/qml/modules/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml index 2e7bf0db9..04fc52150 100644 --- a/resources/qml/Governikus/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml +++ b/src/ui/qml/modules/SelfAuthenticationView/+desktop/SelfAuthenticationView.qml @@ -1,13 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.SettingsModel import Governikus.TitleBar -import Governikus.Type.SelfAuthModel +import Governikus.Type import Governikus.View SectionPage { @@ -16,8 +15,8 @@ SectionPage { text: qsTr("Identify") } - Keys.onEnterPressed: startWorkflowButton.onClicked() - Keys.onReturnPressed: startWorkflowButton.onClicked() + Keys.onEnterPressed: startWorkflowButton.clicked() + Keys.onReturnPressed: startWorkflowButton.clicked() Column { anchors.centerIn: parent @@ -59,7 +58,7 @@ SectionPage { GPane { id: textPane - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic drawShadow: false anchors { @@ -86,7 +85,7 @@ SectionPage { id: startWorkflowButton Layout.alignment: Qt.AlignHCenter - buttonColor: SettingsModel.useSelfauthenticationTestUri ? Constants.red : Style.color.control + buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.error : Style.color.control.background.basic icon.source: "qrc:///images/identify.svg" //: LABEL DESKTOP text: qsTr("See my personal data") diff --git a/src/ui/qml/modules/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml b/src/ui/qml/modules/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml new file mode 100644 index 000000000..e2d28abde --- /dev/null +++ b/src/ui/qml/modules/SelfAuthenticationView/+mobile/SelfAuthenticationView.qml @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.AuthView +import Governikus.Global +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.Type + +FlickableSectionPage { + id: root + + property bool autoInsertCard: false + property bool hideTechnologySwitch: false + property var initialPlugin + + signal back + signal workflowFinished(int pModuleToShow) + + //: LABEL ANDROID IOS + title: qsTr("Identify") + + navigationAction: NavigationAction { + action: NavigationAction.Action.Back + + onClicked: root.back() + } + + FadeInAnimation { + target: root + } + Component { + id: authView + + AuthView { + property bool backRequested: false + + autoInsertCard: root.autoInsertCard + hideTechnologySwitch: root.hideTechnologySwitch + initialPlugin: root.initialPlugin + + Component.onCompleted: SelfAuthModel.startWorkflow(false) + onRequestBack: backRequested = true + onShowChangePinView: root.workflowFinished(UiModule.PINMANAGEMENT) + onWorkflowFinished: root.workflowFinished(backRequested ? UiModule.SELF_AUTHENTICATION : UiModule.DEFAULT) + } + } + ColumnLayout { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + spacing: Constants.component_spacing + + TintableIcon { + Layout.alignment: Qt.AlignHCenter + source: "qrc:///images/mobile/mydata.svg" + sourceSize.height: Style.dimens.header_icon_size + tintColor: Style.color.image + + PkiSwitch { + anchors.fill: parent + //: LABEL ANDROID IOS + functionName: qsTr("Self-authentication") + } + } + GText { + Layout.alignment: Qt.AlignHCenter + //: LABEL ANDROID IOS + text: qsTr("View the data stored on your ID card") + textStyle: Style.text.subline + wrapMode: Text.WordWrap + } + PrivacyStatement { + activeFocusOnTab: true + + FocusFrame { + } + } + } + GSpacer { + Layout.fillHeight: true + Layout.minimumHeight: Constants.component_spacing + } + Hint { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Hint") + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: Constants.groupbox_spacing + + Image { + fillMode: Image.PreserveAspectFit + source: "qrc:///images/siteWithLogo_%1.svg".arg(Style.currentTheme.name) + sourceSize.width: Math.min(Style.dimens.header_icon_size, (parent.width - parent.spacing) / 3) + } + GText { + //: LABEL ANDROID IOS A11y description of eID logo displayed next to the logo itself + Accessible.name: qsTr("You can use your ID card anywhere you find the logo of the electronic identification function.") + Layout.minimumWidth: 80 + + //: LABEL ANDROID IOS + text: qsTr("You can use your ID card anywhere you see this logo.") + } + } + } + GSpacer { + Layout.fillHeight: true + Layout.minimumHeight: Constants.component_spacing + } + GButton { + Layout.alignment: Qt.AlignHCenter + buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.error : Style.color.control.background.basic + icon.source: "qrc:///images/identify.svg" + //: LABEL ANDROID IOS + text: qsTr("See my personal data") + tintIcon: true + + onClicked: push(authView) + onFocusChanged: if (focus) + root.positionViewAtItem(this) + } +} diff --git a/resources/qml/Governikus/SettingsView/+desktop/CardReaderView.qml b/src/ui/qml/modules/SettingsView/+desktop/CardReaderView.qml similarity index 80% rename from resources/qml/Governikus/SettingsView/+desktop/CardReaderView.qml rename to src/ui/qml/modules/SettingsView/+desktop/CardReaderView.qml index 7c3ed5abf..319b9cd82 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/CardReaderView.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/CardReaderView.qml @@ -1,14 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.ReaderModel -import Governikus.Type.ReaderScanEnabler -import Governikus.Type.ReaderPlugIn +import Governikus.Type import Governikus.View Column { @@ -19,7 +16,7 @@ Column { ReaderScanEnabler { id: readerScanEnabler - plugInType: ReaderPlugIn.PCSC + pluginType: ReaderManagerPluginType.PCSC } GPane { //: LABEL DESKTOP @@ -27,6 +24,8 @@ Column { width: parent.width Column { + Accessible.name: qsTr("List of connected card readers.") + Accessible.role: Accessible.List Layout.fillWidth: true spacing: Constants.component_spacing visible: readerRepeater.count > 0 @@ -42,19 +41,24 @@ Column { } } RowLayout { - spacing: Constants.component_spacing + spacing: Constants.groupbox_spacing visible: !readerScanEnabler.scanRunning width: parent.width TintableIcon { source: "qrc:///images/status_warning.svg" sourceSize.height: Style.dimens.large_icon_size - tintColor: Style.color.text_warning + tintColor: Style.color.warning } GText { + activeFocusOnTab: true text: qsTr("The connection to your system's smartcard service could not be established. You can try to resolve this issue and restart the scan.") + + FocusFrame { + } } GButton { + Layout.minimumWidth: implicitWidth text: qsTr("Restart smartcard scan") onClicked: readerScanEnabler.restartScan() @@ -79,20 +83,20 @@ Column { id: hintAndDateText Layout.topMargin: Constants.component_spacing - spacing: Constants.component_spacing + spacing: Constants.groupbox_spacing width: parent.width TintableIcon { source: "qrc:/images/info.svg" sourceSize.height: Style.dimens.large_icon_size - tintColor: Style.color.control + tintColor: hintText.color } GText { id: hintText Layout.alignment: Qt.AlignVCenter activeFocusOnTab: true - color: Style.color.control + color: Style.color.textSubline.basic text: qsTr("After connecting a new card reader it may take a few seconds to recognize the driver. It may be necessary to restart your system after installing the driver. Only connected card readers are shown here. %1").arg(ReaderModel.lastUpdatedInformation) verticalAlignment: Text.AlignBottom diff --git a/resources/qml/Governikus/SettingsView/+desktop/DarkModeButtons.qml b/src/ui/qml/modules/SettingsView/+desktop/DarkModeButtons.qml similarity index 83% rename from resources/qml/Governikus/SettingsView/+desktop/DarkModeButtons.qml rename to src/ui/qml/modules/SettingsView/+desktop/DarkModeButtons.qml index 868d5a7c9..5d9d36c11 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/DarkModeButtons.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/DarkModeButtons.qml @@ -1,11 +1,10 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global -import Governikus.Type.SettingsModel -import Governikus.Type.ModeOption +import Governikus.Type ColumnLayout { id: root @@ -23,17 +22,17 @@ ColumnLayout { root.buttonClicked(); } - spacing: Constants.component_spacing + spacing: 0 Component.onCompleted: { - if (!plugin.osDarkModeSupported) + if (!UiPluginModel.osDarkModeSupported) system.visible = false; } GRadioButton { id: system - readonly property var mode: ModeOption.AUTO + readonly property var mode: SettingsModel.ModeOption.AUTO //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to system mode") @@ -49,7 +48,7 @@ ColumnLayout { GRadioButton { id: dark - readonly property var mode: ModeOption.ON + readonly property var mode: SettingsModel.ModeOption.ON //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to dark mode") @@ -65,7 +64,7 @@ ColumnLayout { GRadioButton { id: light - readonly property var mode: ModeOption.OFF + readonly property var mode: SettingsModel.ModeOption.OFF //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to light mode") diff --git a/resources/qml/Governikus/SettingsView/+desktop/LanguageButtons.qml b/src/ui/qml/modules/SettingsView/+desktop/LanguageButtons.qml similarity index 90% rename from resources/qml/Governikus/SettingsView/+desktop/LanguageButtons.qml rename to src/ui/qml/modules/SettingsView/+desktop/LanguageButtons.qml index aee2e9c75..7c1fdd865 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/LanguageButtons.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/LanguageButtons.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts diff --git a/resources/qml/Governikus/SettingsView/+desktop/RemoteReaderView.qml b/src/ui/qml/modules/SettingsView/+desktop/RemoteReaderView.qml similarity index 84% rename from resources/qml/Governikus/SettingsView/+desktop/RemoteReaderView.qml rename to src/ui/qml/modules/SettingsView/+desktop/RemoteReaderView.qml index f7b591d4d..537d98316 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/RemoteReaderView.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/RemoteReaderView.qml @@ -1,16 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.NumberModel -import Governikus.Type.RemoteServiceModel -import Governikus.Type.ReaderScanEnabler -import Governikus.Type.ReaderPlugIn +import Governikus.Type import Governikus.View Item { @@ -23,7 +19,7 @@ Item { implicitWidth: column.implicitWidth ReaderScanEnabler { - plugInType: ReaderPlugIn.REMOTE_IFD + pluginType: ReaderManagerPluginType.REMOTE_IFD } Column { id: column @@ -77,16 +73,13 @@ Item { title: qsTr("Add pairing") width: parent.width - GListView { + Repeater { id: availableDevices - Layout.fillWidth: true - implicitHeight: contentHeight model: RemoteServiceModel.availableDevicesInPairingMode delegate: RemoteReaderDelegate { - height: implicitHeight + Constants.pane_padding - width: availableDevices.width + Layout.fillWidth: true onPairDevice: pDeviceId => root.pairDevice(pDeviceId) } @@ -99,7 +92,7 @@ Item { Repeater { model: [ //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 1 of 4. %1 is a placeholder-tag for the app name. - qsTr("Ensure that the %1 on your Smartphone as card reader has at least version %2.").arg(Qt.application.name).arg("1.26.5"), + qsTr("Ensure that the %1 on your Smartphone as card reader has at least version %2.").arg(Qt.application.name).arg("2.1.0"), //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 2 of 4. %1 is a placeholder-tag for the app name. qsTr("Open the %1 on your Smartphone as card reader.").arg(Qt.application.name), //: LABEL ANDROID IOS Assistance text for pairing new devices. Step 3 of 4. %1 and %2 are surrounding tags for bold font @@ -141,13 +134,15 @@ Item { TintableIcon { source: "qrc:/images/info.svg" sourceSize.height: Style.dimens.large_icon_size - tintColor: Style.color.control + tintColor: hintText.color } GText { + id: hintText + Layout.alignment: Qt.AlignVCenter activeFocusOnTab: true - color: Style.color.control - text: qsTr("Both devices have to be connected to the same WiFi.") + color: Style.color.textSubline.basic + text: qsTr("Both devices have to be on the same network (e.g. WiFi).") verticalAlignment: Text.AlignBottom wrapMode: Text.WordWrap diff --git a/resources/qml/Governikus/SettingsView/+desktop/SettingsView.qml b/src/ui/qml/modules/SettingsView/+desktop/SettingsView.qml similarity index 79% rename from resources/qml/Governikus/SettingsView/+desktop/SettingsView.qml rename to src/ui/qml/modules/SettingsView/+desktop/SettingsView.qml index 08b8dbff4..7415b77e7 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/SettingsView.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/SettingsView.qml @@ -1,15 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQml.Models import Governikus.Global import Governikus.View import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule -import Governikus.Type.RemoteServiceModel +import Governikus.Type import Governikus.UpdateView SectionPage { @@ -67,15 +64,13 @@ SectionPage { qsTr("USB card reader"), //: LABEL DESKTOP qsTr("Security and privacy")]; - if (plugin.debugBuild) { - model.push( - //: LABEL DESKTOP - qsTr("Debug options")); + if (UiPluginModel.debugBuild) { + //: LABEL DESKTOP + model.push(qsTr("Debug options")); } if (SettingsModel.developerOptions) { - model.push( - //: LABEL DESKTOP - qsTr("Developer options")); + //: LABEL DESKTOP + model.push(qsTr("Developer options")); } return model; } @@ -84,13 +79,6 @@ SectionPage { contentObjectModel: ObjectModel { Component { GeneralSettings { - Connections { - function onFireUseSystemFontChanged() { - sectionPage.nextView(UiModule.DEFAULT); - } - - target: SettingsModel - } } } Component { @@ -115,7 +103,7 @@ SectionPage { } Component.onCompleted: { - if (plugin.debugBuild) { + if (UiPluginModel.debugBuild) { contentObjectModel.append(debugSettings); } if (SettingsModel.developerOptions) { @@ -148,6 +136,7 @@ SectionPage { rootEnabled: titleBarAction.rootEnabled visible: d.view === SettingsView.SubView.ConnectSacView - onCloseView: d.view = SettingsView.SubView.None + onPairingFailed: d.view = SettingsView.SubView.None + onPairingSuccessful: d.view = SettingsView.SubView.None } } diff --git a/resources/qml/Governikus/SettingsView/+desktop/TabbedReaderView.qml b/src/ui/qml/modules/SettingsView/+desktop/TabbedReaderView.qml similarity index 77% rename from resources/qml/Governikus/SettingsView/+desktop/TabbedReaderView.qml rename to src/ui/qml/modules/SettingsView/+desktop/TabbedReaderView.qml index 16d088124..e15c458c8 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/TabbedReaderView.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/TabbedReaderView.qml @@ -1,13 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQml.Models import Governikus.Global +import Governikus.ResultView import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.NumberModel -import Governikus.Type.RemoteServiceModel +import Governikus.Type import Governikus.View SectionPage { @@ -15,10 +14,11 @@ SectionPage { enum SubView { None, - ConnectSacView + ConnectSacView, + PcscReaderFoundView } - readonly property int availableReader: ApplicationModel.availableReader + readonly property int availableReader: ApplicationModel.availablePcscReader readonly property int currentView: d.view property int lastReaderCount: 0 property alias paneAnchors: tabbedPane.anchors @@ -35,6 +35,8 @@ SectionPage { text: qsTr("Card Readers") customSubAction: NavigationAction { + type: NavigationAction.Action.Back + onClicked: closeView() } @@ -44,7 +46,8 @@ SectionPage { Component.onCompleted: lastReaderCount = availableReader onAvailableReaderChanged: { if (visible && availableReader > lastReaderCount) { - root.closeView(); + d.view = TabbedReaderView.SubView.PcscReaderFoundView; + updateTitleBarActions(); } lastReaderCount = availableReader; } @@ -56,6 +59,13 @@ SectionPage { property int precedingView property int view } + ResultView { + icon: "qrc:///images/desktop/workflow_idcard_usb.svg" + text: qsTr("Found new USB card reader that is suitable for the ID card. The workflow may now be continued.") + visible: d.view === TabbedReaderView.SubView.PcscReaderFoundView + + onNextView: root.closeView() + } TabbedPane { id: tabbedPane @@ -93,27 +103,16 @@ SectionPage { top: parent.top } } - NavigationButton { - buttonType: NavigationButton.Type.Back - visible: tabbedPane.visible - - onClicked: root.closeView() - - anchors { - bottom: parent.bottom - left: parent.left - margins: Constants.pane_padding - } - } ConnectSacView { id: connectSacView rootEnabled: root.rootEnabled visible: d.view === TabbedReaderView.SubView.ConnectSacView - onCloseView: { + onPairingFailed: { d.view = d.precedingView; updateTitleBarActions(); } + onPairingSuccessful: root.closeView() } } diff --git a/resources/qml/Governikus/SettingsView/+desktop/CardReaderDelegate.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/CardReaderDelegate.qml similarity index 61% rename from resources/qml/Governikus/SettingsView/+desktop/CardReaderDelegate.qml rename to src/ui/qml/modules/SettingsView/+desktop/internal/CardReaderDelegate.qml index db204976d..3294c4ab1 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/CardReaderDelegate.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/CardReaderDelegate.qml @@ -1,22 +1,27 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style +import Governikus.Type import Governikus.View +import Governikus.Type RoundedRectangle { - property int iconHeight: plugin.scaleFactor * 175 + property int iconHeight: UiPluginModel.scaleFactor * 175 - Accessible.name: readerName + ". " + readerHTMLDescription - Accessible.role: Accessible.Button + //: INFO DESKTOP Text read by screen reader if the text contains a web link to a card reader driver which may be opened. + Accessible.name: readerName + ". " + ApplicationModel.stripHtmlTags(readerHTMLDescription) + ". " + (textDescription.hasLink ? qsTr("Press space to open link.") : "") + Accessible.role: textDescription.hasLink ? Accessible.Button : Accessible.ListItem activeFocusOnTab: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic implicitHeight: rowLayout.implicitHeight implicitWidth: rowLayout.implicitWidth + Keys.onSpacePressed: textDescription.tryActivateLink() + FocusFrame { } RowLayout { @@ -39,36 +44,24 @@ RoundedRectangle { name: "OK" PropertyChanges { - source: "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) - target: statusIcon - } - PropertyChanges { - target: statusIcon - tintColor: Style.color.success + statusIcon.source: "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) + statusIcon.tintColor: Style.color.success } }, State { name: "WARNING" PropertyChanges { - source: "qrc:///images/status_warning.svg" - target: statusIcon - } - PropertyChanges { - target: statusIcon - tintColor: Style.color.fail + statusIcon.source: "qrc:///images/status_warning.svg" + statusIcon.tintColor: Style.color.fail } }, State { name: "ERROR" PropertyChanges { - source: "qrc:///images/status_error_%1.svg".arg(Style.currentTheme.name) - target: statusIcon - } - PropertyChanges { - target: statusIcon - tintColor: Style.color.text_warning + statusIcon.source: "qrc:///images/status_error_%1.svg".arg(Style.currentTheme.name) + statusIcon.tintColor: Style.color.warning } } ] @@ -78,8 +71,8 @@ RoundedRectangle { Layout.preferredHeight: iconHeight + 2 * Constants.pane_padding Layout.preferredWidth: iconHeight + Constants.pane_padding bottomRightCorner: false - color: Style.color.pane_sublevel - gradientColor: Style.color.pane + color: Style.color.paneSublevel.background.basic + gradientColor: Style.color.pane.background.basic topRightCorner: false Image { @@ -106,6 +99,7 @@ RoundedRectangle { spacing: Constants.text_spacing GText { + Accessible.ignored: true Layout.alignment: Qt.AlignLeft clip: true text: readerName @@ -114,9 +108,8 @@ RoundedRectangle { GText { id: textDescription - Accessible.description: qsTr("Press space to open the link in your browser") + Accessible.ignored: true Layout.alignment: Qt.AlignLeft - activeFocusOnTab: true text: readerHTMLDescription FocusFrame { diff --git a/resources/qml/Governikus/SettingsView/+desktop/ConnectSacView.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/ConnectSacView.qml similarity index 60% rename from resources/qml/Governikus/SettingsView/+desktop/ConnectSacView.qml rename to src/ui/qml/modules/SettingsView/+desktop/internal/ConnectSacView.qml index 2268fee01..fb4cbe6ae 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/ConnectSacView.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/ConnectSacView.qml @@ -1,17 +1,15 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.EnterPasswordView import Governikus.PasswordInfoView import Governikus.ProgressView -import Governikus.ResultView +import Governikus.RemoteServiceView import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.PasswordType -import Governikus.Type.RemoteServiceModel +import Governikus.Type import Governikus.View SectionPage { @@ -21,12 +19,14 @@ SectionPage { None, EnterPassword, WaitForPairing, - PairingFailed + PairingFailed, + PairingSuccess } property alias rootEnabled: mainTitleBarAction.rootEnabled - signal closeView + signal pairingFailed + signal pairingSuccessful titleBarAction: TitleBarAction { id: mainTitleBarAction @@ -36,9 +36,10 @@ SectionPage { text: qsTr("Pairing") customSubAction: NavigationAction { + type: d.view === ConnectSacView.SubView.PairingSuccess || d.view === ConnectSacView.SubView.PairingFailed ? NavigationAction.Action.Back : NavigationAction.Action.Cancel visible: true - onClicked: root.closeView() + onClicked: d.view === ConnectSacView.SubView.PairingSuccess ? root.pairingSuccessful() : root.pairingFailed() } } @@ -57,7 +58,7 @@ SectionPage { property int view } EnterPasswordView { - passwordType: PasswordType.REMOTE_PIN + passwordType: NumberModel.PasswordType.REMOTE_PIN visible: d.view === ConnectSacView.SubView.EnterPassword onPasswordEntered: d.view = ConnectSacView.SubView.WaitForPairing @@ -74,26 +75,30 @@ SectionPage { pairingFailedView.errorMessage = pErrorMessage; d.view = ConnectSacView.SubView.PairingFailed; } - function onFirePairingSuccess() { - root.closeView(); + function onFirePairingSuccess(pDeviceName) { + pairingSuccessView.deviceName = pDeviceName; + d.view = ConnectSacView.SubView.PairingSuccess; } enabled: visible target: RemoteServiceModel } } - ResultView { + PairingFailedView { id: pairingFailedView - property string deviceName - property string errorMessage + deviceName: "" + errorMessage: "" + visible: d.view === ConnectSacView.SubView.PairingFailed - icon: "qrc:///images/desktop/workflow_error_sak_connection_%1.svg".arg(Style.currentTheme.name) + onNextView: root.pairingFailed() + } + PairingSuccessView { + id: pairingSuccessView - //: ERROR DESKTOP An error occurred while pairing the device. - text: qsTr("Pairing to \"%1\" failed:").arg(deviceName) + "
\"%2\"".arg(errorMessage) - visible: d.view === ConnectSacView.SubView.PairingFailed + deviceName: "" + visible: d.view === ConnectSacView.SubView.PairingSuccess - onNextView: root.closeView() + onNextView: root.pairingSuccessful() } } diff --git a/src/ui/qml/modules/SettingsView/+desktop/internal/DebugSettings.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/DebugSettings.qml new file mode 100644 index 000000000..e2aa5fec5 --- /dev/null +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/DebugSettings.qml @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick.Layouts +import Governikus.Global +import Governikus.View +import Governikus.Style +import Governikus.Type + +ColumnLayout { + spacing: Constants.component_spacing + + GPane { + Layout.fillWidth: true + contentPadding: 0 + spacing: Constants.component_spacing + + //: LABEL DESKTOP + title: qsTr("Create dummy entries") + + RowLayout { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + Layout.topMargin: Constants.pane_padding + + GButton { + //: LABEL DESKTOP + text: qsTr("Logfile") + + onClicked: { + LogModel.saveDummyLogFile(); + ApplicationModel.showFeedback("Created new logfile."); + } + } + } + ColumnLayout { + spacing: 0 + + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.showBetaTesting + //: LABEL DESKTOP + text: qsTr("Show beta testing image") + + onCheckedChanged: SettingsModel.showBetaTesting = checked + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.enableCanAllowed + //: LABEL DESKTOP + text: qsTr("Support CAN allowed mode") + + onCheckedChanged: SettingsModel.enableCanAllowed = checked + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.skipRightsOnCanAllowed + enabled: SettingsModel.enableCanAllowed + //: LABEL DESKTOP + text: qsTr("Skip rights page in CAN allowed mode") + + onCheckedChanged: SettingsModel.skipRightsOnCanAllowed = checked + } + } + GButton { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + //: LABEL DESKTOP + text: qsTr("Reset hideable dialogs") + + onClicked: { + SettingsModel.resetHideableDialogs(); + } + } + GText { + Layout.bottomMargin: Constants.pane_padding + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + activeFocusOnTab: true + //: LABEL DESKTOP + text: qsTr("Show Transport PIN reminder, store feedback and close reminder dialogs.") + + FocusFrame { + } + } + } +} diff --git a/resources/qml/Governikus/SettingsView/+desktop/DeveloperSettings.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/DeveloperSettings.qml similarity index 81% rename from resources/qml/Governikus/SettingsView/+desktop/DeveloperSettings.qml rename to src/ui/qml/modules/SettingsView/+desktop/internal/DeveloperSettings.qml index e797698cf..1a50d1b70 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/DeveloperSettings.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/DeveloperSettings.qml @@ -1,51 +1,54 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import QtQuick.Layouts import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.LogModel -import Governikus.Type.SettingsModel +import Governikus.Type ColumnLayout { spacing: Constants.component_spacing GPane { Layout.fillWidth: true - spacing: Constants.component_spacing + contentPadding: 0 + spacing: 0 //: LABEL DESKTOP title: qsTr("Developer options") - LabeledSwitch { + GSwitch { + Layout.fillWidth: true checked: SettingsModel.useSelfauthenticationTestUri //: LABEL DESKTOP description: qsTr("Allow test sample card usage") //: LABEL DESKTOP - title: qsTr("Testmode for the self-authentication") + text: qsTr("Testmode for the self-authentication") onCheckedChanged: SettingsModel.useSelfauthenticationTestUri = checked } - LabeledSwitch { + GSwitch { + Layout.fillWidth: true checked: SettingsModel.enableSimulator //: LABEL DESKTOP description: qsTr("The internal card simulator allows to run an authentication in the test PKI without any ID card or card reader. Note that no other card reader can be used while the simulator is activated.") //: LABEL DESKTOP - title: qsTr("Internal card simulator") + text: qsTr("Internal card simulator") onCheckedChanged: SettingsModel.enableSimulator = checked } - LabeledSwitch { + GSwitch { + Layout.fillWidth: true checked: SettingsModel.developerMode //: LABEL DESKTOP - description: qsTr("The developer mode deactivates some security checks and the authentication process will continue even if some errors occur. Skipped errors will be shown as notifications. The developer mode is only usable with the test PKI.").arg(Qt.application.name) + description: qsTr("The developer mode deactivates some security checks and the authentication process will continue even if some errors occur. Skipped errors will be shown as notifications. The developer mode is only usable with the test PKI.") + drawBottomCorners: true //: LABEL DESKTOP - title: qsTr("Developer mode") + text: qsTr("Developer mode") onCheckedChanged: SettingsModel.developerMode = checked } diff --git a/src/ui/qml/modules/SettingsView/+desktop/internal/GeneralSettings.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/GeneralSettings.qml new file mode 100644 index 000000000..4bf67d289 --- /dev/null +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/GeneralSettings.qml @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View +import Governikus.Type + +ColumnLayout { + spacing: Constants.component_spacing + + GPane { + Layout.fillWidth: true + spacing: Constants.component_spacing + //: LABEL DESKTOP + title: qsTr("Change language") + + LanguageButtons { + columns: 4 + } + } + GPane { + Layout.fillWidth: true + contentPadding: 0 + spacing: 0 + //: LABEL DESKTOP + title: qsTr("Appearance") + + DarkModeButtons { + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.useSystemFont + + //: LABEL DESKTOP + description: qsTr("Toggling will restart the %1").arg(Qt.application.name) + drawBottomCorners: true + //: LABEL DESKTOP + text: qsTr("Use the system font") + + onCheckedChanged: { + if (checked !== SettingsModel.useSystemFont) { + SettingsModel.useSystemFont = checked; + UiPluginModel.doRefresh(); + } + } + } + } + GPane { + Layout.fillWidth: true + contentPadding: 0 + spacing: 0 + //: LABEL DESKTOP + title: qsTr("Accessibility") + + GSwitch { + Layout.fillWidth: true + checked: !SettingsModel.useAnimations + //: LABEL DESKTOP + text: qsTr("Use images instead of animations") + + onCheckedChanged: SettingsModel.useAnimations = !checked + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.visualPrivacy + //: LABEL DESKTOP + text: qsTr("Hide key animations when entering PIN") + + onCheckedChanged: SettingsModel.visualPrivacy = checked + } + GSwitch { + Layout.fillWidth: true + checked: !SettingsModel.autoRedirectAfterAuthentication + //: LABEL DESKTOP + description: qsTr("After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds.") + drawBottomCorners: true + //: LABEL DESKTOP + text: qsTr("Manual redirection back to the provider") + + onCheckedChanged: SettingsModel.autoRedirectAfterAuthentication = !checked + } + } + GPane { + Layout.fillWidth: true + contentPadding: 0 + spacing: 0 + //: LABEL DESKTOP + title: qsTr("Behavior") + + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.autoStartApp + enabled: !SettingsModel.autoStartSetByAdmin && SettingsModel.autoStartAvailable + text: Qt.platform.os === "osx" ? + //: LABEL MACOS Text for auto-start option + qsTr("Auto-start %1 after boot and add to menu bar").arg(Qt.application.name) : + //: LABEL WINDOWS Text for auto-start option + qsTr("Auto-start %1 after boot and add a tray icon").arg(Qt.application.name) + + onCheckedChanged: SettingsModel.autoStartApp = checked + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.autoCloseWindowAfterAuthentication + + //: LABEL DESKTOP + text: qsTr("Close %1 after authentication").arg(Qt.application.name) + + onCheckedChanged: SettingsModel.autoCloseWindowAfterAuthentication = checked + } + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.showInAppNotifications + + //: LABEL DESKTOP Only visible when the user activates the developer mode in the settings. + description: SettingsModel.developerMode ? qsTr("Using the developer mode forces the notifications to be enabled.") : "" + drawBottomCorners: true + enabled: !SettingsModel.developerMode + + //: LABEL DESKTOP + text: qsTr("Show notifications inside of %1").arg(Qt.application.name) + + onCheckedChanged: SettingsModel.showInAppNotifications = checked + } + } + GPane { + Layout.fillWidth: true + contentPadding: 0 + spacing: Constants.component_spacing + //: LABEL DESKTOP + title: qsTr("Network") + visible: SettingsModel.customProxyAttributesPresent + + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.useCustomProxy + drawBottomCorners: true + + //: LABEL DESKTOP + text: qsTr("Use the proxy (%1) specified during the installation.").arg(SettingsModel.customProxyUrl) + + onCheckedChanged: SettingsModel.useCustomProxy = checked + } + } +} diff --git a/resources/qml/Governikus/SettingsView/+desktop/RemoteReaderDelegate.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/RemoteReaderDelegate.qml similarity index 72% rename from resources/qml/Governikus/SettingsView/+desktop/RemoteReaderDelegate.qml rename to src/ui/qml/modules/SettingsView/+desktop/internal/RemoteReaderDelegate.qml index 8c3c9f3cf..abb3e0bfa 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/RemoteReaderDelegate.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/RemoteReaderDelegate.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,6 +8,7 @@ import Governikus.Global import Governikus.Style import Governikus.RemoteServiceView import Governikus.View +import Governikus.Type RoundedRectangle { id: root @@ -18,19 +19,22 @@ RoundedRectangle { signal unpairDevice(string pDeviceId) Accessible.name: { - let msg = qsTr("Smartphone named \"%1\"").arg(remoteDeviceName) + subtext.text; - if (isPaired) { + //: INFO DESKTOP Name and status of remote device. %1 is replaced with the name, %2 with the status + let msg = qsTr("Smartphone named \"%1\". %2. ").arg(remoteDeviceName).arg(subtext.text); + if (isPaired && !isPairing) { + //: INFO DESKTOP Text for activation action if the device is paired. return msg + qsTr("Press space to unpair the smartphone \"%1\".").arg(remoteDeviceName); } + //: INFO DESKTOP Text for activation action if the device is unpaired. return msg + qsTr("Press space to pair the smartphone \"%1\".").arg(remoteDeviceName); } Accessible.role: Accessible.Button activeFocusOnTab: true - color: Style.color.pane_sublevel + color: Style.color.paneSublevel.background.basic implicitHeight: rowLayout.implicitHeight + 2 * rowLayout.anchors.margins implicitWidth: rowLayout.implicitWidth + 2 * rowLayout.anchors.margins - Keys.onSpacePressed: isPaired ? unpairDevice(deviceId) : pairDevice(deviceId) + Keys.onSpacePressed: (isPaired && !isPairing && ApplicationModel.isScreenReaderRunning()) ? unpairDevice(deviceId) : pairDevice(deviceId) FocusFrame { } @@ -48,6 +52,7 @@ RoundedRectangle { elide: Text.ElideRight maximumLineCount: 1 text: remoteDeviceName + textFormat: Text.PlainText textStyle: Style.text.headline width: parent.width } @@ -71,12 +76,14 @@ RoundedRectangle { TintableIcon { id: removeIcon - fillMode: Image.PreserveAspectFit + activeFocusOnTab: !ApplicationModel.isScreenReaderRunning() source: "qrc:///images/trash_icon.svg" sourceSize.height: iconHeight - tintColor: Style.color.control + tintColor: Style.color.image visible: isPaired && !isPairing + Keys.onSpacePressed: unpairDevice(deviceId) + MouseArea { id: trashMouse @@ -89,6 +96,8 @@ RoundedRectangle { onClicked: unpairDevice(deviceId) } + FocusFrame { + } } GSpacer { height: removeIcon.height diff --git a/resources/qml/Governikus/SettingsView/+desktop/SecurityAndPrivacySettings.qml b/src/ui/qml/modules/SettingsView/+desktop/internal/SecurityAndPrivacySettings.qml similarity index 73% rename from resources/qml/Governikus/SettingsView/+desktop/SecurityAndPrivacySettings.qml rename to src/ui/qml/modules/SettingsView/+desktop/internal/SecurityAndPrivacySettings.qml index 681b72df2..dbc6a4c94 100644 --- a/resources/qml/Governikus/SettingsView/+desktop/SecurityAndPrivacySettings.qml +++ b/src/ui/qml/modules/SettingsView/+desktop/internal/SecurityAndPrivacySettings.qml @@ -1,13 +1,12 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.View ColumnLayout { @@ -15,52 +14,50 @@ ColumnLayout { GPane { Layout.fillWidth: true - spacing: Constants.component_spacing + contentPadding: 0 + spacing: 0 //: LABEL DESKTOP - title: qsTr("Onscreen keypad") - - LabeledSwitch { - checked: SettingsModel.useScreenKeyboard + title: qsTr("Numeric keypad") - //: LABEL DESKTOP - title: qsTr("Use on screen keypad for PIN entry") - - onCheckedChanged: SettingsModel.useScreenKeyboard = checked - } - LabeledSwitch { + GSwitch { + Layout.fillWidth: true checked: SettingsModel.shuffleScreenKeyboard - enabled: SettingsModel.useScreenKeyboard + //: LABEL DESKTOP + description: qsTr("Makes it difficult for outsiders to detect PIN entry") //: LABEL DESKTOP - title: qsTr("Shuffle digits of on screen keypad") + text: qsTr("Shuffle keys") onCheckedChanged: SettingsModel.shuffleScreenKeyboard = checked } - LabeledSwitch { - checked: !SettingsModel.visualPrivacy + GSwitch { + Layout.fillWidth: true + checked: SettingsModel.visualPrivacy //: LABEL DESKTOP - description: qsTr("Visually highlight key presses on screen keypad") - enabled: SettingsModel.useScreenKeyboard + description: qsTr("Makes it difficult for outsiders to detect PIN entry") + drawBottomCorners: true //: LABEL DESKTOP - title: qsTr("Button animation") + text: qsTr("Hide key animations") - onCheckedChanged: SettingsModel.visualPrivacy = !checked + onCheckedChanged: SettingsModel.visualPrivacy = checked } } GPane { Layout.fillWidth: true + contentPadding: 0 spacing: Constants.component_spacing //: LABEL DESKTOP title: qsTr("Software updates") visible: SettingsModel.autoUpdateAvailable - LabeledSwitch { + GSwitch { + Layout.fillWidth: true checked: SettingsModel.autoUpdateCheck enabled: !SettingsModel.autoUpdateCheckSetByAdmin //: LABEL DESKTOP - title: qsTr("Check at program start") + text: qsTr("Check for updates at program start") onCheckedChanged: SettingsModel.autoUpdateCheck = checked } @@ -68,7 +65,9 @@ ColumnLayout { readonly property bool updateAvailable: SettingsModel.appUpdateData.updateAvailable readonly property bool updateValid: SettingsModel.appUpdateData.valid - Layout.fillWidth: true + Layout.bottomMargin: Constants.pane_padding + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding spacing: Constants.component_spacing GButton { @@ -82,7 +81,7 @@ ColumnLayout { } GText { activeFocusOnTab: true - color: (parent.updateAvailable || !parent.updateValid) ? Style.color.text_warning : Style.color.control + color: (parent.updateAvailable || !parent.updateValid) ? Style.color.textNormal.basic : Style.color.textSubline.basic text: { if (parent.updateAvailable && parent.updateValid) { //: LABEL DESKTOP An update is available, the new version is supplied to the user. @@ -98,7 +97,6 @@ ColumnLayout { return qsTr("No update information available, please check for update manually."); } } - textStyle: Style.text.normal FocusFrame { } diff --git a/resources/qml/Governikus/SettingsView/+mobile/DarkModeButtons.qml b/src/ui/qml/modules/SettingsView/+mobile/DarkModeButtons.qml similarity index 75% rename from resources/qml/Governikus/SettingsView/+mobile/DarkModeButtons.qml rename to src/ui/qml/modules/SettingsView/+mobile/DarkModeButtons.qml index 4fdeb6d6c..e94ef2ee0 100644 --- a/resources/qml/Governikus/SettingsView/+mobile/DarkModeButtons.qml +++ b/src/ui/qml/modules/SettingsView/+mobile/DarkModeButtons.qml @@ -1,11 +1,10 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global -import Governikus.Type.SettingsModel -import Governikus.Type.ModeOption +import Governikus.Type ColumnLayout { id: root @@ -15,6 +14,7 @@ ColumnLayout { readonly property string selectedText: checkedButton.title signal buttonClicked + signal receivedFocus(var pItem) function onAppearanceButtonClicked(mode) { if (SettingsModel.userDarkMode === mode) @@ -23,17 +23,17 @@ ColumnLayout { root.buttonClicked(); } - spacing: Constants.groupbox_spacing + spacing: 0 Component.onCompleted: { - if (!plugin.osDarkModeSupported) + if (!UiPluginModel.osDarkModeSupported) system.visible = false; } GCollapsibleSubButton { id: system - readonly property var mode: ModeOption.AUTO + readonly property var mode: SettingsModel.ModeOption.AUTO //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to system mode") @@ -44,11 +44,13 @@ ColumnLayout { title: qsTr("System") onClicked: root.onAppearanceButtonClicked(mode) + onFocusChanged: if (focus) + root.receivedFocus(this) } GCollapsibleSubButton { id: dark - readonly property var mode: ModeOption.ON + readonly property var mode: SettingsModel.ModeOption.ON //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to dark mode") @@ -59,11 +61,13 @@ ColumnLayout { title: qsTr("Dark") onClicked: root.onAppearanceButtonClicked(mode) + onFocusChanged: if (focus) + root.receivedFocus(this) } GCollapsibleSubButton { id: light - readonly property var mode: ModeOption.OFF + readonly property var mode: SettingsModel.ModeOption.OFF //: LABEL ALL_PLATFORMS Accessible.description: qsTr("Set the app appearance to light mode") @@ -74,5 +78,7 @@ ColumnLayout { title: qsTr("Light") onClicked: root.onAppearanceButtonClicked(mode) + onFocusChanged: if (focus) + root.receivedFocus(this) } } diff --git a/src/ui/qml/modules/SettingsView/+mobile/SettingsView.qml b/src/ui/qml/modules/SettingsView/+mobile/SettingsView.qml new file mode 100644 index 000000000..8db507626 --- /dev/null +++ b/src/ui/qml/modules/SettingsView/+mobile/SettingsView.qml @@ -0,0 +1,516 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import Governikus.Global +import Governikus.Style +import Governikus.TitleBar +import Governikus.View +import Governikus.RemoteServiceView +import Governikus.SmartView +import Governikus.Type + +FlickableSectionPage { + id: baseItem + + function platformId(pName) { + return "mobile," + pName.replace(" ", "").toLowerCase(); + } + + enableTileStyle: false + spacing: Constants.component_spacing + //: LABEL ANDROID IOS + title: qsTr("Settings") + + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("General") + + GCollapsible { + id: languageCollapsible + + contentBottomMargin: 0 + contentHorizontalMargin: 0 + contentSpacing: 0 + contentTopMargin: 0 + drawTopCorners: true + selectionIcon: "qrc:///images/location_flag_%1.svg".arg(SettingsModel.language) + selectionTitle: { + switch (SettingsModel.language) { + case "de": + return "Deutsch"; + case "ru": + return "Русский"; + case "uk": + return "Українська"; + default: + return "English"; + } + } + //: LABEL ANDROID IOS + title: qsTr("Change language") + width: parent.width + + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) + + GRepeater { + id: repeater + + delegate: GCollapsibleSubButton { + Accessible.description: model.a11yDescription + Accessible.name: model.a11yName + Layout.fillWidth: true + image: model.image + title: model.text + + onClicked: { + SettingsModel.language = model.language; + languageCollapsible.expanded = false; + } + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + model: LanguageButtonData { + } + } + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GCollapsible { + id: appearanceCollapsible + + contentBottomMargin: 0 + contentHorizontalMargin: 0 + contentSpacing: 0 + contentTopMargin: 0 + selectionIcon: modeButtons.selectedIconPath + selectionTitle: modeButtons.selectedText + tintIcon: true + //: LABEL ANDROID IOS + title: qsTr("Appearance") + width: parent.width + + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) + + DarkModeButtons { + id: modeButtons + + width: parent.width + + onButtonClicked: appearanceCollapsible.expanded = false + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) + } + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + //: LABEL ANDROID IOS + description: qsTr("Toggling will restart the %1").arg(Qt.application.name) + drawBottomCorners: true + //: LABEL ANDROID IOS + text: qsTr("Use system font") + width: parent.width + + Component.onCompleted: { + checked = SettingsModel.useSystemFont; + } + onCheckedChanged: { + if (checked !== SettingsModel.useSystemFont) { + SettingsModel.useSystemFont = checked; + UiPluginModel.doRefresh(); + } + } + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Accessibility") + + GSwitch { + checked: !SettingsModel.useAnimations + drawTopCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Use images instead of animations") + width: parent.width + + onCheckedChanged: SettingsModel.useAnimations = !checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.visualPrivacy + //: LABEL ANDROID IOS + text: qsTr("Hide key animations when entering PIN") + width: parent.width + + onCheckedChanged: SettingsModel.visualPrivacy = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: !SettingsModel.autoRedirectAfterAuthentication + //: LABEL ANDROID IOS + description: qsTr("After identification, you will only be redirected back to the provider after confirmation. Otherwise, you will be redirected automatically after a few seconds.") + drawBottomCorners: true + //: LABEL ANDROID IOS + text: qsTr("Manual redirection back to the provider") + width: parent.width + + onCheckedChanged: SettingsModel.autoRedirectAfterAuthentication = !checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Smartphone as card reader") + + GCollapsible { + alwaysReserveSelectionTitleHeight: true + contentBottomMargin: 0 + contentTopMargin: 0 + drawTopCorners: true + selectionTitle: expanded ? "" : SettingsModel.deviceName + //: LABEL ANDROID IOS + title: qsTr("Device name") + width: parent.width + + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) + + GTextField { + function saveInput() { + focus = false; + SettingsModel.deviceName = text; + } + + Layout.fillWidth: true + Layout.margins: Constants.component_spacing + maximumLength: Constants.maximumDeviceNameLength + text: SettingsModel.deviceName + + onAccepted: saveInput() + onFocusChanged: focus ? baseItem.positionViewAtItem(this) : saveInput() + } + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.pinPadMode + + //: LABEL ANDROID IOS + text: qsTr("Enter PIN on this device") + width: parent.width + + onCheckedChanged: SettingsModel.pinPadMode = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.showAccessRights + enabled: SettingsModel.pinPadMode + + //: LABEL ANDROID IOS + text: qsTr("Show requested rights on this device as well") + width: parent.width + + onCheckedChanged: SettingsModel.showAccessRights = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GMenuItem { + //: LABEL ANDROID IOS + description: qsTr("Add and remove devices") + drawBottomCorners: true + + //: LABEL ANDROID IOS + title: qsTr("Manage pairings") + width: parent.width + + onClicked: push(remoteServiceSettings) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + + Component { + id: remoteServiceSettings + + RemoteServiceSettings { + enableTileStyle: baseItem.enableTileStyle + + Component.onCompleted: RemoteServiceModel.detectRemoteDevices = true + Component.onDestruction: RemoteServiceModel.detectRemoteDevices = false + } + } + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Numeric keypad") + + GSwitch { + checked: SettingsModel.shuffleScreenKeyboard + //: LABEL ANDROID IOS + description: qsTr("Makes it difficult for outsiders to detect PIN entry") + drawTopCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Shuffle keys") + width: parent.width + + onCheckedChanged: SettingsModel.shuffleScreenKeyboard = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.visualPrivacy + //: LABEL ANDROID IOS + description: qsTr("Makes it difficult for outsiders to detect PIN entry") + drawBottomCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Hide key animations") + width: parent.width + + onCheckedChanged: SettingsModel.visualPrivacy = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Smart-eID") + visible: ApplicationModel.isSmartSupported + + GMenuItem { + //: LABEL ANDROID IOS + description: qsTr("Reset Smart-eID data on your device") + //: LABEL ANDROID IOS + title: qsTr("Reset Smart-eID") + width: parent.width + + onClicked: push(smartDeleteView) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + + Component { + id: smartDeleteView + + SmartResetView { + } + } + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("On-site reading") + visible: SettingsModel.advancedSettings + + GSwitch { + checked: SettingsModel.enableCanAllowed + drawTopCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Support CAN allowed mode for on-site reading") + width: parent.width + + onCheckedChanged: SettingsModel.enableCanAllowed = checked + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.skipRightsOnCanAllowed + drawBottomCorners: true + enabled: SettingsModel.enableCanAllowed + + //: LABEL ANDROID IOS + text: qsTr("Skip rights page") + width: parent.width + + onCheckedChanged: SettingsModel.skipRightsOnCanAllowed = checked + } + } + GOptionsContainer { + Layout.fillWidth: true + //: LABEL ANDROID IOS + title: qsTr("Developer options") + visible: SettingsModel.advancedSettings + + GSwitch { + id: testUriSwitch + + checked: SettingsModel.useSelfauthenticationTestUri + //: LABEL ANDROID IOS + description: qsTr("Allow test sample card usage") + drawTopCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Testmode for the self-authentication") + width: parent.width + + onCheckedChanged: SettingsModel.useSelfauthenticationTestUri = checked + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GSwitch { + checked: SettingsModel.enableSimulator + //: LABEL ANDROID IOS + description: qsTr("Simulate a test sample card in authentications") + drawBottomCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Internal card simulator") + width: parent.width + + onCheckedChanged: SettingsModel.enableSimulator = checked + } + } + GOptionsContainer { + Layout.fillWidth: true + + //: LABEL ANDROID IOS + title: qsTr("Debug options") + visible: UiPluginModel.debugBuild + + GSwitch { + checked: SettingsModel.developerMode + //: LABEL ANDROID IOS + description: qsTr("Use a more tolerant mode") + drawTopCorners: true + + //: LABEL ANDROID IOS + text: qsTr("Developer mode") + width: parent.width + + onCheckedChanged: SettingsModel.developerMode = checked + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GSeparator { + anchors.left: parent.left + anchors.leftMargin: Constants.component_spacing + anchors.right: parent.right + anchors.rightMargin: Constants.component_spacing + } + GMenuItem { + //: LABEL ANDROID IOS + description: qsTr("Show Transport PIN reminder, store feedback and close reminder dialogs.") + drawBottomCorners: true + icon.source: "qrc:///images/material_refresh.svg" + //: LABEL ANDROID IOS + title: qsTr("Reset hideable dialogs") + width: parent.width + + onClicked: { + SettingsModel.resetHideableDialogs(); + } + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + GOptionsContainer { + Layout.fillWidth: true + + //: LABEL ANDROID IOS + title: qsTr("Create dummy entries") + visible: UiPluginModel.debugBuild + + ColumnLayout { + spacing: Constants.component_spacing + width: parent.width + + GButton { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + Layout.topMargin: Constants.pane_padding + + //: LABEL ALL_PLATFORMS + text: qsTr("New Logfile") + + onClicked: { + LogModel.saveDummyLogFile(); + ApplicationModel.showFeedback("Created new logfile."); + } + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GButton { + Layout.bottomMargin: Constants.pane_padding + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Constants.pane_padding + + //: LABEL ALL_PLATFORMS + text: qsTr("15 days old Logfile") + + onClicked: { + let date = new Date(); + date.setDate(new Date().getDate() - 15); + LogModel.saveDummyLogFile(date); + ApplicationModel.showFeedback("Created old logfile."); + } + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + } +} diff --git a/resources/qml/Governikus/SettingsView/LanguageButtonData.qml b/src/ui/qml/modules/SettingsView/internal/LanguageButtonData.qml similarity index 94% rename from resources/qml/Governikus/SettingsView/LanguageButtonData.qml rename to src/ui/qml/modules/SettingsView/internal/LanguageButtonData.qml index 2ac1ddc39..18ff838ea 100644 --- a/resources/qml/Governikus/SettingsView/LanguageButtonData.qml +++ b/src/ui/qml/modules/SettingsView/internal/LanguageButtonData.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/SetupAssistantView/+desktop/SetupAutostartView.qml b/src/ui/qml/modules/SetupAssistantView/+desktop/SetupAutostartView.qml similarity index 92% rename from resources/qml/Governikus/SetupAssistantView/+desktop/SetupAutostartView.qml rename to src/ui/qml/modules/SetupAssistantView/+desktop/SetupAutostartView.qml index e9f2d6b65..cac3f3d22 100644 --- a/resources/qml/Governikus/SetupAssistantView/+desktop/SetupAutostartView.qml +++ b/src/ui/qml/modules/SetupAssistantView/+desktop/SetupAutostartView.qml @@ -1,12 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.TitleBar import Governikus.View -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule +import Governikus.Type DecisionView { mainIconSource: "qrc:///images/desktop/autostart.svg" diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartDeleteView.qml b/src/ui/qml/modules/SmartView/+mobile/SmartDeleteView.qml similarity index 74% rename from resources/qml/Governikus/SmartView/+mobile/SmartDeleteView.qml rename to src/ui/qml/modules/SmartView/+mobile/SmartDeleteView.qml index c52367524..71aa8f750 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartDeleteView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/SmartDeleteView.qml @@ -1,9 +1,8 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQml -import Governikus.Type.SmartModel -import Governikus.Type.UiModule +import Governikus.Type SmartDeleteBaseView { id: root @@ -27,26 +26,26 @@ SmartDeleteBaseView { onDeleteConfirmed: { setLockedAndHidden(); pushProgressView({ - "title": root.title, - //: LABEL ANDROID IOS - "text": qsTr("Deleting Smart-eID") - }); + "title": root.title, + //: LABEL ANDROID IOS + "text": qsTr("Deleting Smart-eID") + }); SmartModel.deletePersonalization(); } Connections { function onFireDeletePersonalizationDone(pSuccess) { pushResultView({ - "success": pSuccess, - "title": root.title, - "text": pSuccess ? + "success": pSuccess, + "title": root.title, + "text": (pSuccess ? //: LABEL ANDROID IOS qsTr("You have successfuly deleted your Smart-eID.") : //: LABEL ANDROID IOS - qsTr("The Smart-eID could not be successfully deleted from your device."), - //: LABEL ANDROID IOS - "buttonText": qsTr("Back to start page") - }); + qsTr("The Smart-eID could not be successfully deleted from your device.")), + //: LABEL ANDROID IOS + "buttonText": qsTr("Back to start page") + }); } target: SmartModel diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartResetView.qml b/src/ui/qml/modules/SmartView/+mobile/SmartResetView.qml similarity index 73% rename from resources/qml/Governikus/SmartView/+mobile/SmartResetView.qml rename to src/ui/qml/modules/SmartView/+mobile/SmartResetView.qml index becbfd929..d769bee13 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartResetView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/SmartResetView.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import Governikus.AuthView -import Governikus.Type.ConnectivityManager -import Governikus.Type.SmartModel +import Governikus.Type SmartDeleteBaseView { id: root @@ -28,13 +27,13 @@ SmartDeleteBaseView { onDeleteConfirmed: { setLockedAndHidden(); pushProgressView({ - "title": root.title, - //: LABEL ANDROID IOS - "text": qsTr("Resetting Smart-eID"), - "progressBarVisible": true, - //: LABEL ANDROID IOS - "progressText": qsTr("Resetting Smart-eID") - }); + "title": root.title, + //: LABEL ANDROID IOS + "text": qsTr("Resetting Smart-eID"), + "progressBarVisible": true, + //: LABEL ANDROID IOS + "progressText": qsTr("Resetting Smart-eID") + }); if (connectivityManager.checkConnectivity()) { SmartModel.deleteSmart(); } else { @@ -55,11 +54,11 @@ SmartDeleteBaseView { Connections { function onFireDeleteSmartDone() { pushResultView({ - "success": SmartModel.errorString === "", - "title": root.title, - //: LABEL ANDROID IOS - "text": SmartModel.errorString === "" ? qsTr("You have successfully reset your Smart-eID.") : SmartModel.errorString - }); + "success": SmartModel.errorString === "", + "title": root.title, + //: LABEL ANDROID IOS + "text": SmartModel.errorString === "" ? qsTr("You have successfully reset your Smart-eID.") : SmartModel.errorString + }); } target: SmartModel diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartView.qml b/src/ui/qml/modules/SmartView/+mobile/SmartView.qml similarity index 87% rename from resources/qml/Governikus/SmartView/+mobile/SmartView.qml rename to src/ui/qml/modules/SmartView/+mobile/SmartView.qml index a42531439..911841e07 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/SmartView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.AuthView @@ -9,11 +9,7 @@ import Governikus.SelfAuthenticationView import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.ChangePinModel -import Governikus.Type.ConnectivityManager -import Governikus.Type.ReaderPlugIn -import Governikus.Type.SmartModel -import Governikus.Type.UiModule +import Governikus.Type FlickableSectionPage { id: root @@ -61,7 +57,7 @@ FlickableSectionPage { autoInsertCard: true hidePinTypeSelection: true hideTechnologySwitch: true - initialPlugIn: ReaderPlugIn.SMART + initialPlugin: ReaderManagerPluginType.SMART Component.onCompleted: ChangePinModel.startWorkflow(false, false) onWorkflowFinished: popAll() @@ -73,9 +69,10 @@ FlickableSectionPage { SelfAuthenticationView { autoInsertCard: true hideTechnologySwitch: true - initialPlugIn: ReaderPlugIn.SMART + initialPlugin: ReaderManagerPluginType.SMART onBack: pop() + onWorkflowFinished: _ => popAll() } } Component { @@ -97,7 +94,7 @@ FlickableSectionPage { id: checkSmartResultView CheckSmartResultView { - result: SmartModel.smartState + result: SmartModel.state onCancelClicked: { setLockedAndHidden(false); @@ -125,6 +122,7 @@ FlickableSectionPage { onChangePin: push(changePinView) onDeletePersonalization: push(deletePersonalizationStartview) + onReceivedFocus: pItem => root.positionViewAtItem(pItem) onShowCheckResult: { setLockedAndHidden(); push(checkSmartResultView); diff --git a/resources/qml/Governikus/SmartView/+mobile/CheckSmartResultView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/CheckSmartResultView.qml similarity index 87% rename from resources/qml/Governikus/SmartView/+mobile/CheckSmartResultView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/CheckSmartResultView.qml index c3828237c..3f6f90a80 100644 --- a/resources/qml/Governikus/SmartView/+mobile/CheckSmartResultView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/CheckSmartResultView.qml @@ -1,11 +1,11 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.CheckResultView import Governikus.ResultView import Governikus.Style -import Governikus.Type.SmartModel +import Governikus.Type CheckResultSuggestionView { id: root @@ -22,14 +22,14 @@ CheckResultSuggestionView { return updateCheckError; } switch (result) { - case SmartModel.SMART_UPDATING_STATUS: + case SmartModel.State.UPDATING_STATUS: return smartUpdatingData; - case SmartModel.SMART_UNAVAILABLE: + case SmartModel.State.UNAVAILABLE: return smartUnvailableData; - case SmartModel.SMART_UNUSABLE: + case SmartModel.State.UNUSABLE: return smartUnusableData; - case SmartModel.SMART_NO_PROVISIONING: - case SmartModel.SMART_NO_PERSONALIZATION: + case SmartModel.State.NO_PROVISIONING: + case SmartModel.State.NO_PERSONALIZATION: return smartNotSetupData; default: return empty; @@ -57,7 +57,7 @@ CheckResultSuggestionView { SuggestionData { id: smartUpdatingData - icon: "qrc:///images/sandglass.svg" + icon: "qrc:///animations/hourglass.svg" //: LABEL ANDROID IOS text: qsTr("Please wait a moment.") @@ -94,7 +94,7 @@ CheckResultSuggestionView { //: LABEL ANDROID IOS qsTr("The setup has not been completed.") + "
  • " + //: LABEL ANDROID IOS - qsTr("The Smart-eID PIN has been entered incorrectly three times.") + "
  • " + + qsTr("The Smart-eID PIN has been entered incorrectly 3 times.") + "
  • " + //: LABEL ANDROID IOS qsTr("The %1 has been uninstalled temporarily.").arg(Qt.application.name) + "
  • " + "
    " + //: LABEL ANDROID IOS diff --git a/resources/qml/Governikus/SmartView/+mobile/PersonalizationController.qml b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationController.qml similarity index 79% rename from resources/qml/Governikus/SmartView/+mobile/PersonalizationController.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationController.qml index b32e741d3..3b57d492e 100644 --- a/resources/qml/Governikus/SmartView/+mobile/PersonalizationController.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationController.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.AuthView @@ -11,15 +11,7 @@ import Governikus.PasswordInfoView import Governikus.View import Governikus.WhiteListClient import Governikus.Workflow -import Governikus.Type.ConnectivityManager -import Governikus.Type.ChatModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.PersonalizationModel -import Governikus.Type.ReaderPlugIn -import Governikus.Type.SettingsModel -import Governikus.Type.SurveyModel -import Governikus.Type.UiModule +import Governikus.Type Controller { id: controller @@ -44,6 +36,14 @@ Controller { property bool workflowProgressVisible: false property int workflowState: PersonalizationController.WorkflowStates.Initial + function displayInputError() { + push(inputErrorView, { + "returnCode": PersonalizationModel.lastReturnCode, + "inputError": NumberModel.inputError, + "passwordType": NumberModel.passwordType + }); + NumberModel.resetInputError(); + } function done() { PersonalizationModel.continueWorkflow(); popAll(); @@ -94,6 +94,31 @@ Controller { } break; case "StateEnterPacePassword": + if (PersonalizationModel.lastReturnCode === CardReturnCode.OK_CAN) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.CAN + }); + return; + } else if (PersonalizationModel.lastReturnCode === CardReturnCode.OK_PUK) { + push(inputSuccessView, { + "passwordType": NumberModel.PasswordType.PUK + }); + return; + } + if (NumberModel.inputError !== "") { + displayInputError(); + return; + } + if (NumberModel.initialInputError !== "") { + push(inputErrorView, { + "returnCode": NumberModel.passwordType === NumberModel.PasswordType.CAN ? CardReturnCode.INVALID_CAN : CardReturnCode.INVALID_PUK, + "inputError": NumberModel.initialInputError, + "passwordType": NumberModel.passwordType, + "titleVisible": false + }); + NumberModel.setInitialInputErrorShown(); + return; + } setWorkflowStateAndRequestInput(PersonalizationController.WorkflowStates.Pin); break; case "StateEstablishPaceChannel": @@ -123,6 +148,12 @@ Controller { PersonalizationModel.continueWorkflow(); break; case "StateEnterNewPacePin": + if (NumberModel.inputError !== "") { + displayInputError(); + NumberModel.newPin = ""; + NumberModel.newPinConfirmation = ""; + return; + } setWorkflowStateAndRequestInput(PersonalizationController.WorkflowStates.SmartPinNew); if (PersonalizationModel.applet) { PersonalizationModel.continueWorkflow(); @@ -156,6 +187,9 @@ Controller { PersonalizationModel.continueWorkflow(); } } + function rerunCurrentState() { + processStateChange(PersonalizationModel.currentState); + } function setWorkflowStateAndContinue(pState) { controller.workflowState = pState; PersonalizationModel.continueWorkflow(); @@ -164,9 +198,8 @@ Controller { controller.workflowState = pState; if (PersonalizationModel.isBasicReader) { replace(enterPinView, { - "passwordType": NumberModel.passwordType, - "inputError": NumberModel.inputError - }); + "passwordType": NumberModel.passwordType + }); } else { replace(smartProgress); PersonalizationModel.continueWorkflow(); @@ -193,7 +226,7 @@ Controller { onNetworkInterfaceActiveChanged: { if (PersonalizationModel.currentState === "StateCheckStatus") - processStateChange(PersonalizationModel.currentState); + rerunCurrentState(); } } Component { @@ -221,7 +254,7 @@ Controller { PasswordInfoData { id: transportPinReminderInfoData - contentType: PasswordInfoContent.Type.CHANGE_PIN + contentType: PasswordInfoData.Type.CHANGE_PIN } Component { id: transportPinReminderInfoView @@ -247,7 +280,7 @@ Controller { id: cardPositionView CardPositionView { - smartEidUsed: PersonalizationModel.readerPlugInType === ReaderPlugIn.SMART + smartEidUsed: PersonalizationModel.readerPluginType === ReaderManagerPluginType.SMART title: smartEidTitle onCancelClicked: PersonalizationModel.cancelWorkflow() @@ -333,10 +366,10 @@ Controller { onPasswordEntered: pPasswordType => { switch (pPasswordType) { - case PasswordType.NEW_SMART_PIN: + case NumberModel.PasswordType.NEW_SMART_PIN: setWorkflowStateAndRequestInput(PersonalizationController.WorkflowStates.SmartPinNew); break; - case PasswordType.NEW_SMART_PIN_CONFIRMATION: + case NumberModel.PasswordType.NEW_SMART_PIN_CONFIRMATION: if (NumberModel.commitNewPin()) { replace(smartProgress); if (PersonalizationModel.applet) { @@ -401,4 +434,49 @@ Controller { } } } + Component { + id: inputErrorView + + InputErrorView { + smartEidUsed: controller.smartEidUsed + title: controller.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + PersonalizationModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + controller.rerunCurrentState(); + } + onPasswordInfoRequested: push(passwordInfoView) + } + } + Component { + id: inputSuccessView + + InputSuccessView { + smartEidUsed: controller.smartEidUsed + title: controller.title + + navigationAction: NavigationAction { + action: NavigationAction.Action.Cancel + + onClicked: { + pop(); + PersonalizationModel.cancelWorkflow(); + } + } + + onContinueClicked: { + pop(); + setWorkflowStateAndRequestInput(PersonalizationController.WorkflowStates.Pin); + } + } + } } diff --git a/resources/qml/Governikus/SmartView/+mobile/PersonalizationLegalInformationView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationLegalInformationView.qml similarity index 82% rename from resources/qml/Governikus/SmartView/+mobile/PersonalizationLegalInformationView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationLegalInformationView.qml index 0e1d29f2b..adae31e44 100644 --- a/resources/qml/Governikus/SmartView/+mobile/PersonalizationLegalInformationView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationLegalInformationView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Style @@ -14,11 +14,11 @@ ResultView { smartEidUsed: true text: "" + "
    • " + //: LABEL ANDROID IOS - qsTr("Do not give your smartphone to third parties unattended, especially if it is already unlocked.") + "
    • " + + qsTr("Do not give your smartphone to 3rd parties unattended, especially if it is already unlocked.") + "
    • " + //: LABEL ANDROID IOS qsTr("Do not keep a note of the Smart-eID PIN in or on your smartphone.") + "
    • " + //: LABEL ANDROID IOS - qsTr("Do not give your Smart-eID PIN to third parties.") + "
    • " + + qsTr("Do not give your Smart-eID PIN to 3rd parties.") + "
    • " + //: LABEL ANDROID IOS qsTr("Update the operating system of your smartphone regularly.") + "
    • " + //: LABEL ANDROID IOS diff --git a/resources/qml/Governikus/SmartView/+mobile/PersonalizationProgressView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationProgressView.qml similarity index 94% rename from resources/qml/Governikus/SmartView/+mobile/PersonalizationProgressView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationProgressView.qml index b4688c1c6..4cd935d45 100644 --- a/resources/qml/Governikus/SmartView/+mobile/PersonalizationProgressView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationProgressView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -7,8 +7,7 @@ import Governikus.ProgressView import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.AuthModel -import Governikus.Type.PersonalizationModel +import Governikus.Type ProgressView { id: root diff --git a/resources/qml/Governikus/SmartView/+mobile/PersonalizationResultView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationResultView.qml similarity index 87% rename from resources/qml/Governikus/SmartView/+mobile/PersonalizationResultView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationResultView.qml index 8a64671b8..020ba5e58 100644 --- a/resources/qml/Governikus/SmartView/+mobile/PersonalizationResultView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/PersonalizationResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -8,21 +8,22 @@ import Governikus.PasswordInfoView import Governikus.ResultView import Governikus.Style import Governikus.TitleBar -import Governikus.Type.PasswordType -import Governikus.Type.PersonalizationModel +import Governikus.Type ResultErrorView { id: root buttonText: PersonalizationModel.error ? //: LABEL ANDROID IOS - qsTr("OK") : + qsTr("Back to start page") : //: LABEL ANDROID IOS qsTr("Continue") errorCode: PersonalizationModel.error ? PersonalizationModel.statusCodeString : "" errorDescription: PersonalizationModel.error ? PersonalizationModel.errorText : "" - header: PersonalizationModel.error ? PersonalizationModel.errorHeader : "" + //: LABEL ANDROID IOS + header: qsTr("Personalization failed") icon: PersonalizationModel.error ? "qrc:///images/status_error_%1.svg".arg(Style.currentTheme.name) : "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) + subheader: PersonalizationModel.error ? PersonalizationModel.errorHeader : "" //: INFO ANDROID IOS Success message that the Smart-eID was created. text: PersonalizationModel.error ? PersonalizationModel.resultString : qsTr("You have successfully set up your Smart-eID.") @@ -40,7 +41,6 @@ ResultErrorView { } GText { Layout.alignment: Qt.AlignHCenter - font.bold: true horizontalAlignment: Text.AlignHCenter text: PersonalizationModel.blockingCode textStyle: Style.text.headline @@ -55,7 +55,6 @@ ResultErrorView { font.bold: true //: INFO ANDROID IOS Placeholder (error) text if the Smart-eID setup finished successfully but for some reason no blocking code was retrieved text: qsTr("The Smart-eID setup finished successfully but no blocking code was retrieved. For security reasons, you should delete your Smart-eID and restart the setup.") - textStyle: Style.text.normal_warning visible: PersonalizationModel.blockingCode === "" } MoreInformationLink { @@ -76,14 +75,13 @@ ResultErrorView { return ""; } } - textStyle: Style.text.normal_warning visible: text !== "" } } PasswordInfoData { id: infoData - contentType: PasswordInfoContent.Type.SMART_BLOCKING_CODE + contentType: PasswordInfoData.Type.SMART_BLOCKING_CODE } Component { id: passwordInfoView diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartCardView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartCardView.qml similarity index 57% rename from resources/qml/Governikus/SmartView/+mobile/SmartCardView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartCardView.qml index b0f342ed7..d95442477 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartCardView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartCardView.qml @@ -1,16 +1,17 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick +import Governikus.Animations import Governikus.Global import Governikus.Style -import Governikus.Type.SmartModel +import Governikus.Type Item { id: root readonly property real padding: Constants.groupbox_spacing - readonly property int smartState: SmartModel.smartState + readonly property int smartState: SmartModel.state implicitHeight: cardIcon.implicitHeight + 2 * padding implicitWidth: cardIcon.implicitWidth + 2 * padding @@ -23,14 +24,13 @@ Item { desaturate: true source: "qrc:///images/mobile/generic_id_card.svg" sourceSize.height: Style.dimens.header_icon_size - 2 * root.padding - tintEnabled: root.smartState !== SmartModel.SMART_READY + tintEnabled: root.smartState !== SmartModel.State.READY } - TintableAnimation { + HourglassAnimation { anchors.bottom: parent.bottom anchors.right: parent.right - height: Style.dimens.medium_icon_size - source: "qrc:///images/sandglass.webp" - tintColor: Style.color.control - visible: root.smartState === SmartModel.SMART_UPDATING_STATUS + sourceSize.height: Style.dimens.medium_icon_size + tintColor: Style.color.image + visible: root.smartState === SmartModel.State.UPDATING_STATUS } } diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartDeleteBaseView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartDeleteBaseView.qml similarity index 86% rename from resources/qml/Governikus/SmartView/+mobile/SmartDeleteBaseView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartDeleteBaseView.qml index f5da16696..c4e494dea 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartDeleteBaseView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartDeleteBaseView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -10,10 +10,7 @@ import Governikus.ResultView import Governikus.Style import Governikus.View import Governikus.TitleBar -import Governikus.Type.LogModel -import Governikus.Type.SmartModel -import Governikus.Type.UiModule -import Governikus.Type.WorkflowModel +import Governikus.Type FlickableSectionPage { id: root @@ -71,14 +68,14 @@ FlickableSectionPage { onCancelClicked: root.close() onContinueClicked: root.close() - onMailClicked: LogModel.mailLog("support@ausweisapp.de", WorkflowModel.getEmailHeader(), WorkflowModel.getEmailBody()) + onMailClicked: LogModel.mailLog("support@ausweisapp.de", PersonalizationModel.getEmailHeader(), PersonalizationModel.getEmailBody()) } } TintableIcon { Layout.alignment: Qt.AlignHCenter source: "qrc:///images/identify.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image } GPane { Layout.alignment: Qt.AlignHCenter @@ -103,13 +100,15 @@ FlickableSectionPage { id: deleteButton Layout.alignment: Qt.AlignHCenter - buttonColor: Style.color.text_warning + buttonColor: Style.color.warning icon.source: "qrc:///images/identify.svg" //: LABEL ANDROID IOS text: qsTr("Reset Smart-eID") onClicked: deleteConfirmation.open() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } ConfirmationPopup { id: deleteConfirmation diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartMainView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartMainView.qml similarity index 80% rename from resources/qml/Governikus/SmartView/+mobile/SmartMainView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartMainView.qml index 7cd74d0c3..924f70529 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartMainView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartMainView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,18 +7,17 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.SmartModel -import Governikus.Type.PersonalizationModel -import Governikus.Type.UiModule +import Governikus.Type ColumnLayout { id: root - readonly property bool showCheck: smartState !== SmartModel.SMART_UPDATING_STATUS && smartState !== SmartModel.SMART_READY - readonly property int smartState: SmartModel.smartState + readonly property bool showCheck: smartState !== SmartModel.State.UPDATING_STATUS && smartState !== SmartModel.State.READY + readonly property int smartState: SmartModel.state signal changePin signal deletePersonalization + signal receivedFocus(var pItem) signal showCheckResult signal startSelfAuth signal updateSmart @@ -35,10 +34,10 @@ ColumnLayout { horizontalAlignment: Text.AlignHCenter text: { switch (root.smartState) { - case SmartModel.SMART_UPDATING_STATUS: + case SmartModel.State.UPDATING_STATUS: //: LABEL ANDROID IOS return qsTr("Updating Smart-eID status..."); - case SmartModel.SMART_READY: + case SmartModel.State.READY: //: LABEL ANDROID IOS return qsTr("Smart-eID ready for use"); default: @@ -55,10 +54,10 @@ ColumnLayout { horizontalAlignment: Text.AlignHCenter text: { switch (root.smartState) { - case SmartModel.SMART_UPDATING_STATUS: + case SmartModel.State.UPDATING_STATUS: //: LABEL ANDROID IOS return qsTr("Please wait a moment."); - case SmartModel.SMART_READY: + case SmartModel.State.READY: //: LABEL ANDROID IOS return qsTr("Your Smart-eID is set up and ready for use. You can now perform online identifications without your ID card if supported by the provider."); default: @@ -70,7 +69,7 @@ ColumnLayout { } SmartSettingsView { Layout.topMargin: Constants.component_spacing - visible: root.smartState === SmartModel.SMART_READY + visible: root.smartState === SmartModel.State.READY onChangePin: root.changePin() onDeletePersonalization: root.deletePersonalization() @@ -108,5 +107,7 @@ ColumnLayout { visible: root.showCheck onClicked: root.showCheckResult() + onFocusChanged: if (focus) + root.receivedFocus(this) } } diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartSettingsView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartSettingsView.qml similarity index 79% rename from resources/qml/Governikus/SmartView/+mobile/SmartSettingsView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartSettingsView.qml index 627a64629..e04646635 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartSettingsView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartSettingsView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,13 +7,12 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.SmartModel -import Governikus.Type.PersonalizationModel +import Governikus.Type ColumnLayout { id: contentLayout - readonly property int smartState: SmartModel.smartState + readonly property int smartState: SmartModel.state signal changePin signal deletePersonalization @@ -27,13 +26,13 @@ ColumnLayout { //: LABEL ANDROID IOS title: qsTr("Smart-eID") - MenuItem { + GMenuItem { //: LABEL ANDROID IOS description: qsTr("Show Smart-eID data") //: LABEL ANDROID IOS title: qsTr("Try Smart-eID") - visible: smartState === SmartModel.SMART_READY + visible: smartState === SmartModel.State.READY width: parent.width onClicked: startSelfAuth() @@ -44,13 +43,13 @@ ColumnLayout { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { //: LABEL ANDROID IOS description: qsTr("Change the chosen Smart-eID PIN") //: LABEL ANDROID IOS title: qsTr("Change Smart-eID PIN") - visible: smartState === SmartModel.SMART_READY + visible: smartState === SmartModel.State.READY width: parent.width onClicked: changePin() @@ -61,13 +60,13 @@ ColumnLayout { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { //: LABEL ANDROID IOS description: qsTr("Renew your Smart-eID with current data") //: LABEL ANDROID IOS title: qsTr("Renew Smart-eID") - visible: smartState === SmartModel.SMART_READY + visible: smartState === SmartModel.State.READY width: parent.width onClicked: updateSmart() @@ -78,13 +77,13 @@ ColumnLayout { anchors.right: parent.right anchors.rightMargin: Constants.component_spacing } - MenuItem { + GMenuItem { //: LABEL ANDROID IOS description: qsTr("Delete Smart-eID data from your device") //: LABEL ANDROID IOS title: qsTr("Delete Smart-eID") - visible: smartState === SmartModel.SMART_READY + visible: smartState === SmartModel.State.READY width: parent.width onClicked: deletePersonalization() diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartSetupStartView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartSetupStartView.qml similarity index 78% rename from resources/qml/Governikus/SmartView/+mobile/SmartSetupStartView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartSetupStartView.qml index a05160d14..60bb7e303 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartSetupStartView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartSetupStartView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,8 +7,7 @@ import Governikus.Global import Governikus.Style import Governikus.View import Governikus.TitleBar -import Governikus.Type.PersonalizationModel -import Governikus.Type.SettingsModel +import Governikus.Type FlickableSectionPage { id: root @@ -29,7 +28,7 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter source: "qrc:///images/identify.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image PkiSwitch { anchors.fill: parent @@ -43,7 +42,7 @@ FlickableSectionPage { GText { //: LABEL ANDROID IOS - text: qsTr("You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your six-digit ID card PIN and an internet connection.") + text: qsTr("You are about to set up a Smart-eID on your device. In order to proceed, you need you ID card, your 6-digit ID card PIN and an internet connection.") width: parent.width } PrivacyStatement { @@ -56,12 +55,14 @@ FlickableSectionPage { } GButton { Layout.alignment: Qt.AlignHCenter - buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.text_warning : Style.color.control + buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.error : Style.color.control.background.basic icon.source: "qrc:///images/identify.svg" //: LABEL ANDROID IOS text: qsTr("Set up Smart-eID") onClicked: PersonalizationModel.startWorkflow() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/resources/qml/Governikus/SmartView/+mobile/SmartUpdateStartView.qml b/src/ui/qml/modules/SmartView/+mobile/internal/SmartUpdateStartView.qml similarity index 82% rename from resources/qml/Governikus/SmartView/+mobile/SmartUpdateStartView.qml rename to src/ui/qml/modules/SmartView/+mobile/internal/SmartUpdateStartView.qml index 4e1e1593a..06949c6c4 100644 --- a/resources/qml/Governikus/SmartView/+mobile/SmartUpdateStartView.qml +++ b/src/ui/qml/modules/SmartView/+mobile/internal/SmartUpdateStartView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,8 +7,7 @@ import Governikus.Global import Governikus.Style import Governikus.View import Governikus.TitleBar -import Governikus.Type.PersonalizationModel -import Governikus.Type.SettingsModel +import Governikus.Type FlickableSectionPage { id: root @@ -29,7 +28,7 @@ FlickableSectionPage { Layout.alignment: Qt.AlignHCenter source: "qrc:///images/identify.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image PkiSwitch { anchors.fill: parent @@ -44,7 +43,7 @@ FlickableSectionPage { GText { //: LABEL ANDROID IOS - text: qsTr("You are about to renew your Smart-eID. In order to proceed, you need your ID card, your six-digit ID card PIN and an internet connection.") + text: qsTr("You are about to renew your Smart-eID. In order to proceed, you need your ID card, your 6-digit ID card PIN and an internet connection.") width: parent.width } GText { @@ -64,12 +63,14 @@ FlickableSectionPage { } GButton { Layout.alignment: Qt.AlignHCenter - buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.text_warning : Style.color.control + buttonColor: SettingsModel.useSelfauthenticationTestUri ? Style.color.error : Style.color.control.background.basic icon.source: "qrc:///images/identify.svg" //: LABEL ANDROID IOS text: qsTr("Renew Smart-eID") onClicked: PersonalizationModel.startWorkflow() + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } diff --git a/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsContrast.qml b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsContrast.qml new file mode 100644 index 000000000..7c6a025a0 --- /dev/null +++ b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsContrast.qml @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Type + +Colors { + readonly property var disabledPalette: SystemPalette { + colorGroup: SystemPalette.Disabled + } + readonly property var palette: SystemPalette { + colorGroup: SystemPalette.Active + } + + background: palette.base + border: control.background.basic + fail: "#ff0000" + focus_indicator: textNormal.basic + image: "#ff0000" + progressbar_text: textNormal.basic + success: "#00ff00" + warning: "#ff0000" + + control: DefaultControlColors { + content.basic: palette.buttonText + content.checked: textNormal.basic + } + controlCheckbox: DefaultControlColors { + background.pressed: textNormal.basic + content.basic: textNormal.basic + } + controlOptional: DefaultControlColors { + content.basic: palette.buttonText + content.checked: textNormal.basic + } + controlRadiobutton: DefaultControlColors { + background.pressed: textNormal.basic + content.basic: textNormal.basic + } + controlScrollbar: DefaultControlColors { + background.basic: textNormal.basic + background.hovered: palette.highlight + border.hovered: palette.highlight + border.pressed: palette.highlight + content.basic: palette.buttonText + content.checked: textNormal.basic + } + controlSwitch: DefaultControlColors { + background.pressed: textNormal.basic + content.basic: textNormal.basic + } + linkBasic: DefaultLinkColors { + } + linkNavigation: DefaultLinkColors { + } + linkTitle: DefaultLinkColors { + } + pane: DefaultPaneColors { + } + paneSublevel: DefaultPaneColors { + background.hovered: textNormal.basic + background.pressed: palette.highlight + border.basic: "#576164" + } + textHeadline: DefaultTextColors { + } + textNormal: DefaultTextColors { + checked: palette.highlightedText + } + textSubline: DefaultTextColors { + } + textTitle: DefaultTextColors { + } + + component DefaultControlColors: ControlComponents { + background: ComponentColors { + basic: palette.button + checked: palette.button + disabled: disabledPalette.button + hovered: textNormal.basic + pressed: palette.highlight + } + border: ComponentColors { + basic: textNormal.basic + checked: textNormal.basic + disabled: textNormal.disabled + hovered: palette.base + pressed: palette.highlightedText + } + content: ComponentColors { + basic: textNormal.basic + checked: palette.buttonText + disabled: textNormal.disabled + hovered: palette.base + pressed: palette.highlightedText + } + } + component DefaultLinkColors: ComponentColors { + basic: palette.text + checked: basic + disabled: disabledPalette.text + hovered: palette.highlight + pressed: palette.highlight + } + component DefaultPaneColors: CoreComponents { + background: ComponentColors { + basic: palette.base + checked: palette.highlight + disabled: disabledPalette.base + hovered: palette.highlight + pressed: palette.highlight + } + border: ComponentColors { + basic: textNormal.basic + checked: basic + disabled: disabledPalette.text + hovered: textNormal.basic + pressed: textNormal.basic + } + } + component DefaultTextColors: ComponentColors { + basic: palette.text + checked: basic + disabled: disabledPalette.text + hovered: basic + pressed: basic + } +} diff --git a/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsDark.qml b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsDark.qml new file mode 100644 index 000000000..6e6bcb7c9 --- /dev/null +++ b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsDark.qml @@ -0,0 +1,6 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +ColorsDark { +} diff --git a/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsLight.qml b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsLight.qml new file mode 100644 index 000000000..2cb6e8380 --- /dev/null +++ b/src/ui/qml/modules/Style/+desktop/internal/PlatformColorsLight.qml @@ -0,0 +1,6 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +ColorsLight { +} diff --git a/src/ui/qml/modules/Style/+desktop/internal/PlatformDimensions.qml b/src/ui/qml/modules/Style/+desktop/internal/PlatformDimensions.qml new file mode 100644 index 000000000..2d3dcc297 --- /dev/null +++ b/src/ui/qml/modules/Style/+desktop/internal/PlatformDimensions.qml @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQml +import Governikus.Type + +QtObject { + readonly property real border_width: Math.max(Math.floor(UiPluginModel.scaleFactor * 2), 1) + readonly property real control_radius: UiPluginModel.scaleFactor * 26 + readonly property real header_icon_size: UiPluginModel.scaleFactor * 200 + readonly property real huge_icon_size: UiPluginModel.scaleFactor * 125 + readonly property real icon_size: UiPluginModel.scaleFactor * 48 + readonly property bool isLongLanguage: SettingsModel.language === "uk" || SettingsModel.language === "ru" + readonly property real large_icon_size: UiPluginModel.scaleFactor * 72 + readonly property real lineHeight: UiPluginModel.scaleFactor * 40 + readonly property real lineHeight_button: UiPluginModel.scaleFactor * 27 + readonly property real lineHeight_headline: UiPluginModel.scaleFactor * 47 + readonly property real lineHeight_navigation: UiPluginModel.scaleFactor * 63 + readonly property real lineHeight_subline: UiPluginModel.scaleFactor * 42 + readonly property real lineHeight_tile: UiPluginModel.scaleFactor * 63 + readonly property real lineHeight_title: UiPluginModel.scaleFactor * 70 + readonly property real max_text_width: UiPluginModel.scaleFactor * (isLongLanguage ? 1250 : 1000) + readonly property real medium_icon_size: UiPluginModel.scaleFactor * 64 + readonly property real min_button_width: UiPluginModel.scaleFactor * 220 + readonly property real pane_radius: UiPluginModel.scaleFactor * 34 + readonly property real popup_border: Math.max(UiPluginModel.scaleFactor * 2, 1) + readonly property real progress_bar_border: separator_size_large + readonly property real progress_bar_height: UiPluginModel.scaleFactor * 60 + readonly property real scrollbar_padding_horizontal: UiPluginModel.scaleFactor * 5 + readonly property real scrollbar_padding_vertical: UiPluginModel.scaleFactor * 0 + readonly property real scrollbar_width: UiPluginModel.scaleFactor * 10 + readonly property real separator_size: Math.max(Math.floor(UiPluginModel.scaleFactor * 2), 1) + readonly property real separator_size_large: Math.max(UiPluginModel.scaleFactor * 4, 1) + readonly property real small_icon_size: UiPluginModel.scaleFactor * 32 + readonly property real status_icon_medium: UiPluginModel.scaleFactor * 200 + readonly property real status_icon_small: UiPluginModel.scaleFactor * 100 + readonly property real switch_width: UiPluginModel.scaleFactor * 97 + readonly property real text: UiPluginModel.scaleFactor * 27 + readonly property real textHeadline: UiPluginModel.scaleFactor * 40 + readonly property real textSubline: UiPluginModel.scaleFactor * 30 + readonly property real textTitle: UiPluginModel.scaleFactor * 60 + readonly property real text_navigation: UiPluginModel.scaleFactor * 50 + readonly property real text_tile: UiPluginModel.scaleFactor * 50 + readonly property real titlebar_padding: UiPluginModel.scaleFactor * 20 + readonly property real titlepane_radius: UiPluginModel.scaleFactor * 50 +} diff --git a/src/ui/qml/modules/Style/+mobile/+android/internal/BrandDimensions.qml b/src/ui/qml/modules/Style/+mobile/+android/internal/BrandDimensions.qml new file mode 100644 index 000000000..3934d1b5b --- /dev/null +++ b/src/ui/qml/modules/Style/+mobile/+android/internal/BrandDimensions.qml @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global +import Governikus.Type + +QtObject { + readonly property int navigation_bar_bottom_padding: 10 + readonly property real text: 15 * UiPluginModel.fontScaleFactor + readonly property real textHeadline: 26 * UiPluginModel.fontScaleFactor + readonly property real textSubline: 18 * UiPluginModel.fontScaleFactor + readonly property real textTitle: 30 * UiPluginModel.fontScaleFactor + readonly property real text_navigation: 12 * UiPluginModel.fontScaleFactor + readonly property real text_tile: 30 * UiPluginModel.fontScaleFactor +} diff --git a/src/ui/qml/modules/Style/+mobile/+ios/internal/BrandDimensions.qml b/src/ui/qml/modules/Style/+mobile/+ios/internal/BrandDimensions.qml new file mode 100644 index 000000000..0b7692919 --- /dev/null +++ b/src/ui/qml/modules/Style/+mobile/+ios/internal/BrandDimensions.qml @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Window +import Governikus.Global +import Governikus.Type + +QtObject { + readonly property int navigation_bar_bottom_padding: 1 + // If this font size changes, it has to be changed in UiPluginModel, too. + readonly property real text: scaleText(15) * UiPluginModel.fontScaleFactor + readonly property real textHeadline: scaleText(26) * UiPluginModel.fontScaleFactor + readonly property real textSubline: scaleText(18) * UiPluginModel.fontScaleFactor + readonly property real textTitle: scaleText(30) * UiPluginModel.fontScaleFactor + readonly property real text_navigation: scaleText(12) * UiPluginModel.fontScaleFactor + readonly property real text_tile: scaleText(30) * UiPluginModel.fontScaleFactor + + // Scale the text on small devices like the iPhone SE + function scaleText(value) { + let w = Screen.width; + if (w > 415) { + return value; + } + return value * w / 415; + } +} diff --git a/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsContrast.qml b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsContrast.qml new file mode 100644 index 000000000..678a20a88 --- /dev/null +++ b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsContrast.qml @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +ColorsLight { +} diff --git a/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsDark.qml b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsDark.qml new file mode 100644 index 000000000..955da5460 --- /dev/null +++ b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsDark.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import Governikus.Type + +ColorsDark { + pane.background.pressed: UiPluginModel.isChromeOS ? lighter(pane.background.basic, 0.10) : pane.background.hovered + paneSublevel.background.pressed: UiPluginModel.isChromeOS ? lighter(paneSublevel.background.basic, 0.10) : paneSublevel.background.hovered +} diff --git a/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsLight.qml b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsLight.qml new file mode 100644 index 000000000..a056d2fec --- /dev/null +++ b/src/ui/qml/modules/Style/+mobile/internal/PlatformColorsLight.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import Governikus.Type + +ColorsLight { + pane.background.pressed: UiPluginModel.isChromeOS ? darker(pane.background.basic, 0.10) : pane.background.hovered + paneSublevel.background.pressed: UiPluginModel.isChromeOS ? darker(paneSublevel.background.basic, 0.10) : paneSublevel.background.hovered +} diff --git a/resources/qml/Governikus/Style/+mobile/PlatformDimensions.qml b/src/ui/qml/modules/Style/+mobile/internal/PlatformDimensions.qml similarity index 62% rename from resources/qml/Governikus/Style/+mobile/PlatformDimensions.qml rename to src/ui/qml/modules/Style/+mobile/internal/PlatformDimensions.qml index 0939d63c7..5ebe28338 100644 --- a/resources/qml/Governikus/Style/+mobile/PlatformDimensions.qml +++ b/src/ui/qml/modules/Style/+mobile/internal/PlatformDimensions.qml @@ -1,9 +1,9 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import Governikus.Global -import Governikus.Type.SettingsModel +import Governikus.Type BrandDimensions { readonly property int border_width: 1 @@ -12,20 +12,20 @@ BrandDimensions { readonly property int icon_size: 48 readonly property bool isLongLanguage: SettingsModel.language === "uk" || SettingsModel.language === "ru" readonly property int large_icon_size: 96 - readonly property int lineHeight: 21 - readonly property int lineHeight_button: 15 - readonly property int lineHeight_headline: 34 - readonly property int lineHeight_navigation: 12 - readonly property int lineHeight_subline: 25 - readonly property int lineHeight_title: 36 - readonly property int list_item_height: 64 + readonly property int lineHeight: 21 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_button: 15 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_headline: 34 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_navigation: 12 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_subline: 25 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_tile: 36 * UiPluginModel.fontScaleFactor + readonly property int lineHeight_title: 36 * UiPluginModel.fontScaleFactor readonly property int max_text_width: isLongLanguage ? 800 : 700 readonly property int medium_icon_size: 64 - readonly property int min_button_width: 80 + readonly property int min_button_width: 104 readonly property int navigation_bar_icon_size: 20 readonly property int navigation_bar_min_height: 49 readonly property int navigation_bar_padding: 10 - readonly property int navigation_bar_text_padding: 1 + readonly property int navigation_bar_text_padding: 5 readonly property int pageindicator_size: 8 readonly property int pane_radius: 22 readonly property int popup_border: 0 @@ -37,6 +37,7 @@ BrandDimensions { readonly property int scrollbar_width: 5 readonly property int separator_size: 1 readonly property int small_icon_size: 24 + readonly property int status_icon_small: large_icon_size readonly property int switch_width: 58 readonly property int titlebar_padding: 20 readonly property real workflow_progress_indicator_size: 1.5 * header_icon_size diff --git a/src/ui/qml/modules/Style/ComponentColors.qml b/src/ui/qml/modules/Style/ComponentColors.qml new file mode 100644 index 000000000..fa59f5dd3 --- /dev/null +++ b/src/ui/qml/modules/Style/ComponentColors.qml @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +QtObject { + required property color basic + required property color checked + required property color disabled + required property color hovered + required property color pressed +} diff --git a/src/ui/qml/modules/Style/ControlComponents.qml b/src/ui/qml/modules/Style/ControlComponents.qml new file mode 100644 index 000000000..f5634058f --- /dev/null +++ b/src/ui/qml/modules/Style/ControlComponents.qml @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +CoreComponents { + required property ComponentColors content +} diff --git a/src/ui/qml/modules/Style/CoreComponents.qml b/src/ui/qml/modules/Style/CoreComponents.qml new file mode 100644 index 000000000..109d98c8c --- /dev/null +++ b/src/ui/qml/modules/Style/CoreComponents.qml @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQml + +QtObject { + required property ComponentColors background + required property ComponentColors border +} diff --git a/resources/qml/Governikus/Style/Style.qml b/src/ui/qml/modules/Style/Style.qml similarity index 65% rename from resources/qml/Governikus/Style/Style.qml rename to src/ui/qml/modules/Style/Style.qml index 523fc2973..775ddb9b4 100644 --- a/resources/qml/Governikus/Style/Style.qml +++ b/src/ui/qml/modules/Style/Style.qml @@ -1,25 +1,24 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ pragma Singleton import QtQuick -import Governikus.Type.SettingsModel -import Governikus.Type.ModeOption +import Governikus.Type Item { id: style readonly property var color: currentTheme.color - readonly property var currentTheme: plugin.highContrastEnabled ? highContrastTheme : useDarkMode ? darkTheme : defaultTheme + readonly property var currentTheme: UiPluginModel.highContrastEnabled ? highContrastTheme : useDarkMode ? darkTheme : defaultTheme readonly property var dimens: currentTheme.dimens property bool software_renderer: false readonly property var text: currentTheme.text - readonly property bool useDarkMode: (plugin.osDarkModeEnabled && SettingsModel.userDarkMode === ModeOption.AUTO) || SettingsModel.userDarkMode === ModeOption.ON + readonly property bool useDarkMode: (UiPluginModel.osDarkModeEnabled && SettingsModel.userDarkMode === SettingsModel.ModeOption.AUTO) || SettingsModel.userDarkMode === SettingsModel.ModeOption.ON QtObject { id: darkTheme - readonly property var color: DarkModeColors { + readonly property var color: PlatformColorsDark { software_renderer: style.software_renderer } readonly property alias dimens: dimensions @@ -30,7 +29,7 @@ Item { QtObject { id: highContrastTheme - readonly property var color: HighContrastColors { + readonly property var color: PlatformColorsContrast { software_renderer: style.software_renderer } readonly property alias dimens: dimensions @@ -41,7 +40,7 @@ Item { QtObject { id: defaultTheme - readonly property var color: Colors { + readonly property var color: PlatformColorsLight { software_renderer: style.software_renderer } readonly property alias dimens: dimensions diff --git a/src/ui/qml/modules/Style/TextStyle.qml b/src/ui/qml/modules/Style/TextStyle.qml new file mode 100644 index 000000000..e241424d1 --- /dev/null +++ b/src/ui/qml/modules/Style/TextStyle.qml @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +QtObject { + property int fontWeight: Font.Normal + property real lineHeight: Style.dimens.lineHeight + property color textColor: Style.color.textNormal.basic + property real textSize: Style.dimens.text +} diff --git a/src/ui/qml/modules/Style/internal/Colors.qml b/src/ui/qml/modules/Style/internal/Colors.qml new file mode 100644 index 000000000..5540e67bd --- /dev/null +++ b/src/ui/qml/modules/Style/internal/Colors.qml @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +QtObject { + required property color background + required property color border + readonly property color card_eid: "#0077b6" + readonly property color card_smart: "#327509" + required property ControlComponents control + required property ControlComponents controlCheckbox + required property ControlComponents controlOptional + required property ControlComponents controlRadiobutton + required property ControlComponents controlScrollbar + required property ControlComponents controlSwitch + readonly property color error: "#eb0000" + required property color fail + required property color focus_indicator + required property color image + required property ComponentColors linkBasic + required property ComponentColors linkNavigation + required property ComponentColors linkTitle + required property CoreComponents pane + required property CoreComponents paneSublevel + required property color progressbar_text + property bool software_renderer: false + required property color success + required property ComponentColors textHeadline + required property ComponentColors textNormal + required property ComponentColors textSubline + required property ComponentColors textTitle + readonly property color transparent: "transparent" + required property color warning + + function darker(pColor, pPercent) { + return Qt.hsva(pColor.hsvHue, pColor.hsvSaturation, pColor.hsvValue - pPercent, pColor.a); + } + function lighter(pColor, pPercent) { + return Qt.hsva(pColor.hsvHue, pColor.hsvSaturation, pColor.hsvValue + pPercent, pColor.a); + } +} diff --git a/src/ui/qml/modules/Style/internal/ColorsDark.qml b/src/ui/qml/modules/Style/internal/ColorsDark.qml new file mode 100644 index 000000000..e829c6324 --- /dev/null +++ b/src/ui/qml/modules/Style/internal/ColorsDark.qml @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +Colors { + background: "#232323" + border: "#ffffff" + fail: "#ff9b29" + focus_indicator: "#0098eb" + image: "#0098eb" + progressbar_text: textNormal.basic + success: "#5fcb01" + warning: "#ff9b29" + + control: DefaultControlColors { + background.basic: "#0098eb" + background.checked: "#232323" + border.basic: "#0098eb" + border.checked: "#ffffff" + content.basic: "#232323" + content.checked: "#ffffff" + } + controlCheckbox: DefaultControlColors { + background.checked: transparent + background.pressed: "#80cdec" + border.pressed: "#80cdec" + content.basic: "#ffffff" + content.checked: "#0098eb" + content.pressed: "#ffffff" + } + controlOptional: DefaultControlColors { + background.basic: transparent + background.pressed: "#0098eb" + border.basic: "#0098eb" + border.pressed: "#0098eb" + content.basic: "#0098eb" + content.pressed: "#ffffff" + } + controlRadiobutton: DefaultControlColors { + background.pressed: "#0098eb" + content.basic: "#ffffff" + } + controlScrollbar: DefaultControlColors { + background.basic: "#0098eb" + background.checked: "#232323" + background.pressed: "#80cdec" + border.basic: "#0098eb" + border.checked: "#ffffff" + border.pressed: "#80cdec" + content.basic: "#232323" + content.checked: "#ffffff" + content.pressed: "#ffffff" + } + controlSwitch: DefaultControlColors { + background.pressed: "#80cdec" + border.pressed: "#80cdec" + content.basic: "#ffffff" + content.pressed: "#ffffff" + } + linkBasic: DefaultLinkColors { + } + linkNavigation: DefaultLinkColors { + } + linkTitle: DefaultLinkColors { + basic: "#ffffff" + hovered: "#80cdec" + pressed: "#0098eb" + } + pane: DefaultPaneColors { + } + paneSublevel: DefaultPaneColors { + background.basic: pane.background.hovered + border.basic: "#576164" + } + textHeadline: DefaultTextColors { + } + textNormal: DefaultTextColors { + checked: "#000000" + } + textSubline: DefaultTextColors { + basic: "#80cdec" + disabled: "#798183" + } + textTitle: DefaultTextColors { + basic: "#80cdec" + checked: "#ffffff" + disabled: "#798183" + } + + component DefaultControlColors: ControlComponents { + background: ComponentColors { + basic: "#232323" + checked: "#0098eb" + disabled: "#303030" + hovered: "#80cdec" + pressed: transparent + } + border: ComponentColors { + basic: "#ffffff" + checked: "#0098eb" + disabled: "#798183" + hovered: "#80cdec" + pressed: "#0098eb" + } + content: ComponentColors { + basic: "#ffffff" + checked: "#232323" + disabled: "#798183" + hovered: "#ffffff" + pressed: "#0098eb" + } + } + component DefaultLinkColors: ComponentColors { + basic: "#80cdec" + checked: basic + disabled: "#bcc0c1" + hovered: "#0098eb" + pressed: "#0b7ab7" + } + component DefaultPaneColors: CoreComponents { + background: ComponentColors { + basic: "#303030" + checked: "#0098eb" + disabled: "#303030" + hovered: lighter(basic, 0.05) + pressed: lighter(basic, 0.10) + } + border: ComponentColors { + basic: software_renderer ? "#ffffff" : transparent + checked: basic + disabled: basic + hovered: basic + pressed: basic + } + } + component DefaultTextColors: ComponentColors { + basic: "#ffffff" + checked: basic + disabled: "#bcc0c1" + hovered: basic + pressed: basic + } +} diff --git a/src/ui/qml/modules/Style/internal/ColorsLight.qml b/src/ui/qml/modules/Style/internal/ColorsLight.qml new file mode 100644 index 000000000..1b67fb60c --- /dev/null +++ b/src/ui/qml/modules/Style/internal/ColorsLight.qml @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick + +Colors { + background: "#ffffff" + border: "#bbbbbb" + fail: "#db6a00" + focus_indicator: "#0077b6" + image: "#0077b6" + progressbar_text: "#232323" + success: "#3e8401" + warning: "#db6a00" + + control: DefaultControlColors { + background.basic: "#0077b6" + background.checked: "#ffffff" + border.basic: "#0077b6" + border.checked: "#576164" + content.basic: "#ffffff" + content.checked: "#576164" + } + controlCheckbox: DefaultControlColors { + background.basic: transparent + background.pressed: "#80cdec" + border.pressed: "#80cdec" + content.pressed: "#ffffff" + } + controlOptional: DefaultControlColors { + background.basic: transparent + background.pressed: "#0077b6" + border.basic: "#0077b6" + border.pressed: "#0077b6" + content.basic: "#0077b6" + content.pressed: "#ffffff" + } + controlRadiobutton: DefaultControlColors { + background.pressed: "#0077b6" + } + controlScrollbar: DefaultControlColors { + background.basic: "#0077b6" + background.checked: "#ffffff" + background.pressed: "#80cdec" + border.basic: "#0077b6" + border.checked: "#576164" + border.pressed: "#80cdec" + content.basic: "#ffffff" + content.checked: "#576164" + content.pressed: "#ffffff" + } + controlSwitch: DefaultControlColors { + background.pressed: "#80cdec" + border.pressed: "#80cdec" + content.pressed: "#ffffff" + } + linkBasic: DefaultLinkColors { + hovered: "#379ec8" + } + linkNavigation: DefaultLinkColors { + basic: "#004b76" + } + linkTitle: DefaultLinkColors { + basic: "#576164" + } + pane: DefaultPaneColors { + } + paneSublevel: DefaultPaneColors { + background.basic: "#f2f3f4" + border.basic: "#f2f3f4" + } + textHeadline: DefaultTextColors { + } + textNormal: DefaultTextColors { + checked: "#ffffff" + } + textSubline: DefaultTextColors { + basic: "#0077b6" + disabled: "#80cdec" + } + textTitle: DefaultTextColors { + basic: "#004b76" + checked: "#0077b6" + disabled: "#798183" + } + + component DefaultControlColors: ControlComponents { + background: ComponentColors { + basic: "#ffffff" + checked: "#0077b6" + disabled: "#bcc0c1" + hovered: "#80cdec" + pressed: transparent + } + border: ComponentColors { + basic: "#576164" + checked: "#0077b6" + disabled: "#bcc0c1" + hovered: "#80cdec" + pressed: "#0077b6" + } + content: ComponentColors { + basic: "#576164" + checked: "#ffffff" + disabled: "#ffffff" + hovered: "#ffffff" + pressed: "#0077b6" + } + } + component DefaultLinkColors: ComponentColors { + basic: "#0077b6" + checked: basic + disabled: "#bcc0c1" + hovered: "#0077b6" + pressed: "#80cdec" + } + component DefaultPaneColors: CoreComponents { + background: ComponentColors { + basic: "#ffffff" + checked: "#0077b6" + disabled: "#f2f3f4" + hovered: darker(basic, 0.05) + pressed: darker(basic, 0.10) + } + border: ComponentColors { + basic: software_renderer ? "#bbbbbb" : transparent + checked: basic + disabled: basic + hovered: basic + pressed: basic + } + } + component DefaultTextColors: ComponentColors { + basic: "#576164" + checked: basic + disabled: "#bcc0c1" + hovered: basic + pressed: basic + } +} diff --git a/resources/qml/Governikus/Style/Dimensions.qml b/src/ui/qml/modules/Style/internal/Dimensions.qml similarity index 57% rename from resources/qml/Governikus/Style/Dimensions.qml rename to src/ui/qml/modules/Style/internal/Dimensions.qml index fc8a941c2..e9591797c 100644 --- a/resources/qml/Governikus/Style/Dimensions.qml +++ b/src/ui/qml/modules/Style/internal/Dimensions.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ PlatformDimensions { diff --git a/src/ui/qml/modules/Style/internal/TextStyles.qml b/src/ui/qml/modules/Style/internal/TextStyles.qml new file mode 100644 index 000000000..648a15d20 --- /dev/null +++ b/src/ui/qml/modules/Style/internal/TextStyles.qml @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global + +QtObject { + readonly property var button: TextStyle { + lineHeight: Style.dimens.lineHeight_button + textColor: Style.color.control.content.basic + } + readonly property var headline: TextStyle { + fontWeight: Font.Medium + lineHeight: Style.dimens.lineHeight_headline + textColor: Style.color.textHeadline.basic + textSize: Style.dimens.textHeadline + } + readonly property var link: TextStyle { + textColor: Style.color.linkBasic.basic + } + readonly property var navigation: TextStyle { + fontWeight: Constants.is_desktop ? Font.Medium : Font.Normal + lineHeight: Style.dimens.lineHeight_navigation + textColor: Style.color.linkNavigation.basic + textSize: Style.dimens.text_navigation + } + readonly property var normal: TextStyle { + } + readonly property var subline: TextStyle { + fontWeight: Font.Medium + lineHeight: Style.dimens.lineHeight_subline + textColor: Style.color.textSubline.basic + textSize: Style.dimens.textSubline + } + readonly property var tile: TextStyle { + fontWeight: Font.Medium + lineHeight: Style.dimens.lineHeight_tile + textColor: Style.color.textTitle.basic + textSize: Style.dimens.text_tile + } + readonly property var title: TextStyle { + fontWeight: Font.Bold + lineHeight: Style.dimens.lineHeight_title + textColor: Style.color.textTitle.basic + textSize: Style.dimens.textTitle + } +} diff --git a/resources/qml/Governikus/TechnologyInfo/+mobile/TechnologyInfo.qml b/src/ui/qml/modules/TechnologyInfo/+mobile/TechnologyInfo.qml similarity index 77% rename from resources/qml/Governikus/TechnologyInfo/+mobile/TechnologyInfo.qml rename to src/ui/qml/modules/TechnologyInfo/+mobile/TechnologyInfo.qml index c99eb6f5f..33a1e0f82 100644 --- a/resources/qml/Governikus/TechnologyInfo/+mobile/TechnologyInfo.qml +++ b/src/ui/qml/modules/TechnologyInfo/+mobile/TechnologyInfo.qml @@ -1,12 +1,11 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.NumberModel +import Governikus.Type ColumnLayout { id: root @@ -18,6 +17,7 @@ ColumnLayout { property alias titleText: title.text signal enableClicked + signal receivedFocus(var pItem) spacing: Constants.component_spacing @@ -34,7 +34,6 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignTop visible: text !== "" } GText { @@ -42,15 +41,12 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter horizontalAlignment: Text.AlignHCenter - textStyle: Style.text.normal_warning - verticalAlignment: Text.AlignBottom visible: text !== "" } - Column { + ColumnLayout { id: additionalContentItem - Layout.fillWidth: true - visible: children.length !== 0 + visible: visibleChildren.length !== 0 } GSpacer { Layout.fillHeight: true @@ -63,5 +59,7 @@ ColumnLayout { visible: text !== "" onClicked: enableClicked() + onFocusChanged: if (focus) + root.receivedFocus(this) } } diff --git a/src/ui/qml/modules/TechnologyInfo/+mobile/TechnologySwitch.qml b/src/ui/qml/modules/TechnologyInfo/+mobile/TechnologySwitch.qml new file mode 100644 index 000000000..0760a5373 --- /dev/null +++ b/src/ui/qml/modules/TechnologyInfo/+mobile/TechnologySwitch.qml @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.Type + +GFlickableColumnLayout { + id: baseItem + + property bool flowVertically: false + readonly property int maxItemHeight: Math.max(nfc.implicitHeight, smart.implicitHeight, remote.implicitHeight, sim.implicitHeight) + readonly property int maxItemWidth: Math.max(nfc.implicitWidth, smart.implicitWidth, remote.implicitWidth, sim.implicitWidth) + property int selectedTechnology + property var supportedTechnologies + + signal requestPluginType(int pReaderPluginType) + + clip: true + implicitHeight: maxItemHeight + 2 * Constants.pane_padding + implicitWidth: maxItemWidth + 2 * Constants.pane_padding + leftMargin: 0 + rightMargin: 0 + + QtObject { + id: d + + //: INFO ANDROID IOS A11y text on button indicating the currently active technology. %1 will be replaced with the name of the technology (e.g. NFC). + readonly property string activatedTechnologyA11yText: qsTr("%1 mode is active.") + //: INFO ANDROID IOS A11y text on button to switch to another technology. %1 will be replaced with the name of the technology (e.g. NFC). + readonly property string deactivatedTechnologyA11yText: qsTr("Click here to change the mode to %1.") + + function getTechnologyA11yText(pChecked, pTechnologyName) { + return pChecked ? d.activatedTechnologyA11yText.arg(pTechnologyName) : d.deactivatedTechnologyA11yText.arg(pTechnologyName); + } + } + GSpacer { + Layout.fillHeight: true + visible: flowVertically + } + GridLayout { + id: switcher + + readonly property int columnCount: 1 + (baseItem.width - maxItemWidth) / (maxItemWidth + columnSpacing) + + Layout.alignment: Qt.AlignCenter + columnSpacing: Constants.component_spacing * 2 + columns: flowVertically ? 1 : columnCount + rowSpacing: Constants.component_spacing + + GButton { + id: nfc + + Accessible.name: d.getTechnologyA11yText(checked, text) + checkable: !checked + checked: selectedTechnology === ReaderManagerPluginType.NFC + icon.source: "qrc:///images/mobile/icon_nfc.svg" + style: Style.color.controlOptional + //: LABEL ANDROID IOS + text: qsTr("NFC") + tintIcon: true + visible: supportedTechnologies.includes(ReaderManagerPluginType.NFC) + + onClicked: baseItem.requestPluginType(ReaderManagerPluginType.NFC) + } + GButton { + id: smart + + Accessible.name: d.getTechnologyA11yText(checked, text) + checkable: !checked + checked: selectedTechnology === ReaderManagerPluginType.SMART + icon.source: "qrc:///images/mobile/icon_smart.svg" + style: Style.color.controlOptional + //: LABEL ANDROID IOS + text: qsTr("SMART") + tintIcon: true + visible: supportedTechnologies.includes(ReaderManagerPluginType.SMART) + + onClicked: baseItem.requestPluginType(ReaderManagerPluginType.SMART) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GButton { + id: remote + + Accessible.name: d.getTechnologyA11yText(checked, text) + checkable: !checked + checked: selectedTechnology === ReaderManagerPluginType.REMOTE_IFD + icon.source: "qrc:///images/mobile/icon_remote.svg" + style: Style.color.controlOptional + //: LABEL ANDROID IOS + text: qsTr("WiFi") + tintIcon: true + visible: supportedTechnologies.includes(ReaderManagerPluginType.REMOTE_IFD) + + onClicked: baseItem.requestPluginType(ReaderManagerPluginType.REMOTE_IFD) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + GButton { + id: sim + + Accessible.name: d.getTechnologyA11yText(checked, text) + checkable: !checked + checked: selectedTechnology === ReaderManagerPluginType.SIMULATOR + icon.source: "qrc:///images/mobile/icon_simulator.svg" + style: Style.color.controlOptional + //: LABEL ANDROID IOS + text: qsTr("SIM") + tintIcon: true + visible: supportedTechnologies.includes(ReaderManagerPluginType.SIMULATOR) + + onClicked: baseItem.requestPluginType(ReaderManagerPluginType.SIMULATOR) + onFocusChanged: if (focus) + baseItem.positionViewAtItem(this) + } + } + GSpacer { + Layout.fillHeight: true + visible: flowVertically + } +} diff --git a/resources/qml/Governikus/TitleBar/+desktop/NavigationAction.qml b/src/ui/qml/modules/TitleBar/+desktop/NavigationAction.qml similarity index 61% rename from resources/qml/Governikus/TitleBar/+desktop/NavigationAction.qml rename to src/ui/qml/modules/TitleBar/+desktop/NavigationAction.qml index f4c3e674e..da2f60b5b 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/NavigationAction.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/NavigationAction.qml @@ -1,14 +1,14 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel +import Governikus.Type -GButton { +GLink { id: root enum Action { @@ -16,18 +16,17 @@ GButton { Back } - readonly property color pressColor: Qt.darker(Style.color.text_title, Constants.highlightDarkerFactor) + readonly property color pressColor: Qt.darker(Style.color.textTitle.basic, Constants.highlightDarkerFactor) property int type: NavigationAction.Action.Cancel - background: null + colorStyle: Style.color.linkTitle height: if (parent) parent.height + horizontalPadding: 0 icon.source: root.type === NavigationAction.Action.Cancel ? "qrc:///images/material_close.svg" : "qrc:///images/material_arrow_back.svg" - iconSize: Style.dimens.icon_size + iconSize: Style.dimens.small_icon_size * 1.5 text: root.type === NavigationAction.Action.Cancel ? qsTr("Cancel") : qsTr("Back") - textDisabledColor: Style.color.text_subline_disabled - textStyle: Style.text.normal tintIcon: true verticalPadding: 0 - visible: ApplicationModel.currentWorkflow !== ApplicationModel.WORKFLOW_NONE + visible: ApplicationModel.currentWorkflow !== ApplicationModel.Workflow.NONE } diff --git a/resources/qml/Governikus/TitleBar/+desktop/Notifications.qml b/src/ui/qml/modules/TitleBar/+desktop/Notifications.qml similarity index 68% rename from resources/qml/Governikus/TitleBar/+desktop/Notifications.qml rename to src/ui/qml/modules/TitleBar/+desktop/Notifications.qml index ac916e502..8560199b9 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/Notifications.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/Notifications.qml @@ -1,12 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style -import Governikus.Type.NotificationModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.View Item { @@ -15,12 +14,13 @@ Item { readonly property color iconColor: { if (d.unreadMsg) { if (NotificationModel.lastType === "developermode") - return Constants.red; - return Style.color.text_subline; + return Style.color.warning; + return Style.color.textSubline.basic; } - return Style.color.text; + return Style.color.textNormal.basic; } readonly property bool unreadMessages: d.unreadMsg + readonly property bool visibleToUser: d.fadeIn && !fadeOutTimer.running signal newNotification @@ -55,12 +55,12 @@ Item { anchors.left: parent.left anchors.leftMargin: d.fadeIn ? -(width + Constants.pane_spacing) : 0 anchors.top: parent.top - border.color: Style.color.control_border + border.color: Style.color.control.border.basic border.width: Style.dimens.border_width - color: Style.color.control - height: plugin.scaleFactor * 200 + color: Style.color.control.background.basic + height: UiPluginModel.scaleFactor * 200 radius: Style.dimens.control_radius - width: plugin.scaleFactor * 800 + width: UiPluginModel.scaleFactor * 800 Behavior on anchors.leftMargin { PropertyAnimation { @@ -77,26 +77,28 @@ Item { GListView { id: logEntryList + activeFocusOnTab: baseItem.visibleToUser anchors.fill: parent - anchors.leftMargin: Constants.pane_padding bottomMargin: Constants.pane_padding clip: true model: NotificationModel scrollBarBottomPadding: spacing - scrollBarColor: Style.color.control_content + scrollBarColor: Style.color.control.content.basic scrollBarTopPadding: spacing spacing: Constants.text_spacing topMargin: Constants.pane_padding delegate: Item { Accessible.name: notificationTime.text + " " + notificationBody.text - activeFocusOnTab: d.fadeIn && !fadeOutTimer.running - height: row.height - width: row.width + Accessible.role: Accessible.StaticText + implicitHeight: row.height + implicitWidth: row.width + 2 * Constants.pane_padding Row { id: row + anchors.left: parent.left + anchors.leftMargin: Constants.pane_padding spacing: logEntryList.spacing Component.onCompleted: { @@ -116,18 +118,20 @@ Item { GText { id: notificationTime + color: Style.color.control.content.basic text: model.time - textStyle: Style.text.button } GText { id: notificationBody + color: model.type === "developermode" ? Style.color.warning : Style.color.control.content.basic text: model.text - textStyle: model.type === "developermode" ? Style.text.normal_warning : Style.text.button - width: logEntryList.width - notificationTime.width - 3 * logEntryList.spacing + width: logEntryList.width - 2 * Constants.pane_padding - notificationTime.width - 3 * logEntryList.spacing } } FocusFrame { + borderColor: Style.color.control.content.basic + framee: row } } diff --git a/resources/qml/Governikus/TitleBar/+desktop/TitleBar.qml b/src/ui/qml/modules/TitleBar/+desktop/TitleBar.qml similarity index 69% rename from resources/qml/Governikus/TitleBar/+desktop/TitleBar.qml rename to src/ui/qml/modules/TitleBar/+desktop/TitleBar.qml index 80c392aaf..a908b0f2d 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/TitleBar.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/TitleBar.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type +import QtQuick.Layouts Rectangle { id: titleBar @@ -62,14 +62,17 @@ Rectangle { height: rootAction.height + 2 * Style.dimens.titlebar_padding width: parent.width + z: 1 TitleBarAction { id: rootAction activeFocusOnTab: true anchors.left: parent.left + anchors.leftMargin: Constants.pane_padding anchors.verticalCenter: parent.verticalCenter enabled: d.currentAction.rootEnabled + horizontalPadding: 0 icon.source: "qrc:///images/desktop/home.svg" //: LABEL DESKTOP text: qsTr("Start page") @@ -88,7 +91,7 @@ Rectangle { TitleBarButton { Accessible.description: qsTr("Open settings view of %1").arg(Qt.application.name) height: rightTitleBarActions.height - source: "qrc:///images/desktop/material_settings_white.svg" + source: "qrc:///images/desktop/material_settings.svg" text: qsTr("Settings") visible: d.currentAction.showSettings @@ -97,7 +100,14 @@ Rectangle { TitleBarButton { id: notifyButton - Accessible.description: qsTr("Show in-app notifications of %1").arg(Qt.application.name) + Accessible.description: checked ? + //: LABEL DESKTOP + qsTr("Hide in-app notifications of %1").arg(Qt.application.name) : + //: LABEL DESKTOP + qsTr("Show in-app notifications of %1").arg(Qt.application.name) + Accessible.role: Accessible.CheckBox + checkable: true + checked: notifications.visibleToUser height: rightTitleBarActions.height iconColor: notifications.iconColor source: notifications.unreadMessages ? "qrc:///images/desktop/notifications_on.svg" : "qrc:///images/desktop/notifications_off.svg" @@ -107,6 +117,15 @@ Rectangle { onClicked: notifications.toggle() } } + Notifications { + id: notifications + + anchors.left: parent.right + anchors.top: parent.top + anchors.topMargin: firstRow.height + + onNewNotification: notifyButton.notify() + } } TitlePane { id: titlePane @@ -120,32 +139,41 @@ Rectangle { visible: titlePane.visible width: parent.width - Item { - data: d.currentAction.customSubAction + RowLayout { height: parent.height - width: d.currentAction.customSubAction.visible ? Math.max(childrenRect.width, backAction.width) : 0 - } - NavigationAction { - id: backAction + width: 1.5 * Math.max(backAction.implicitWidth, Style.dimens.min_button_width) - height: parent.height - type: NavigationAction.Action.Back - visible: !d.currentAction.customSubAction.visible - width: 1.5 * implicitWidth + Item { + Layout.alignment: Qt.AlignLeft + Layout.fillHeight: true + data: d.currentAction.customSubAction + } + NavigationAction { + id: backAction + + Layout.alignment: Qt.AlignLeft + Layout.fillHeight: true + type: NavigationAction.Action.Back + visible: !d.currentAction.customSubAction.visible - onClicked: d.prevAction.clicked() + onClicked: d.prevAction.clicked() + } } GText { id: title - font.bold: true + Accessible.role: Accessible.Heading + activeFocusOnTab: true text: d.currentAction.text textStyle: Style.text.title + + FocusFrame { + } } } } GSeparator { - color: Style.color.pane_border + color: Style.color.pane.border.basic height: Style.dimens.border_width anchors { @@ -154,13 +182,4 @@ Rectangle { right: parent.right } } - Notifications { - id: notifications - - anchors.left: parent.right - anchors.top: parent.top - anchors.topMargin: firstRow.height - - onNewNotification: notifyButton.notify() - } } diff --git a/resources/qml/Governikus/TitleBar/+desktop/TitleBarAction.qml b/src/ui/qml/modules/TitleBar/+desktop/TitleBarAction.qml similarity index 68% rename from resources/qml/Governikus/TitleBar/+desktop/TitleBarAction.qml rename to src/ui/qml/modules/TitleBar/+desktop/TitleBarAction.qml index a101be84a..ca9e4e078 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/TitleBarAction.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/TitleBarAction.qml @@ -1,24 +1,23 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style import Governikus.View +import Governikus.Type -GButton { +GLink { property var customSettingsHandler property Item customSubAction: Item { visible: false } property bool rootEnabled: true readonly property var settingsHandler: customSettingsHandler ? customSettingsHandler : function () {} - property bool showHelp: true property bool showSettings: false - background: null - textDisabledColor: Style.color.text_subline_disabled + colorStyle: Style.color.linkNavigation + iconSize: Style.dimens.icon_size textStyle: Style.text.navigation - tintIcon: true verticalPadding: 0 } diff --git a/resources/qml/Governikus/TitleBar/+desktop/TitleBarButton.qml b/src/ui/qml/modules/TitleBar/+desktop/TitleBarButton.qml similarity index 88% rename from resources/qml/Governikus/TitleBar/+desktop/TitleBarButton.qml rename to src/ui/qml/modules/TitleBar/+desktop/TitleBarButton.qml index 3c76ee213..205cc6de9 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/TitleBarButton.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/TitleBarButton.qml @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.View import Governikus.Style -import Governikus.Type.NotificationModel +import Governikus.Type Button { id: button @@ -44,7 +44,7 @@ Button { anchors.fill: parent anchors.margins: image.height / -4 - color: NotificationModel.lastType === "developermode" ? Constants.red : Constants.green + color: NotificationModel.lastType === "developermode" ? Style.color.warning : Constants.green opacity: 0 radius: height / 4 diff --git a/resources/qml/Governikus/TitleBar/+desktop/TitlePane.qml b/src/ui/qml/modules/TitleBar/+desktop/TitlePane.qml similarity index 76% rename from resources/qml/Governikus/TitleBar/+desktop/TitlePane.qml rename to src/ui/qml/modules/TitleBar/+desktop/TitlePane.qml index cc4b5dd81..b2ee0d626 100644 --- a/resources/qml/Governikus/TitleBar/+desktop/TitlePane.qml +++ b/src/ui/qml/modules/TitleBar/+desktop/TitlePane.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -15,7 +15,7 @@ Item { bottomLeftCorner: false bottomRightCorner: false - color: Style.color.pane_title + color: Style.color.paneSublevel.background.basic height: bottomRectangle.height / 2 radius: Style.dimens.titlepane_radius width: bottomRectangle.width - 2 * Style.dimens.titlepane_radius @@ -29,12 +29,12 @@ Item { id: bottomRectangle anchors.bottom: root.bottom - borderColor: Style.color.pane_border + borderColor: Style.color.pane.border.basic bottomLeftCorner: false bottomRightCorner: false color: Style.color.background - height: Style.dimens.titlepane_radius - radius: Style.dimens.titlepane_radius + height: Math.ceil(Style.dimens.titlepane_radius) + radius: height width: root.width layer { @@ -43,7 +43,7 @@ Item { effect: GDropShadow { autoPaddingEnabled: false paddingRect: Qt.rect(0, root.height, 0, 0) - verticalOffset: -3 + shadowVerticalOffset: -3 } } } diff --git a/resources/qml/Governikus/TitleBar/+mobile/NavigationAction.qml b/src/ui/qml/modules/TitleBar/+mobile/NavigationAction.qml similarity index 70% rename from resources/qml/Governikus/TitleBar/+mobile/NavigationAction.qml rename to src/ui/qml/modules/TitleBar/+mobile/NavigationAction.qml index 640745ca8..70e65239d 100644 --- a/resources/qml/Governikus/TitleBar/+mobile/NavigationAction.qml +++ b/src/ui/qml/modules/TitleBar/+mobile/NavigationAction.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/TitleBar/+mobile/TitleBar.qml b/src/ui/qml/modules/TitleBar/+mobile/TitleBar.qml similarity index 65% rename from resources/qml/Governikus/TitleBar/+mobile/TitleBar.qml rename to src/ui/qml/modules/TitleBar/+mobile/TitleBar.qml index 5d48d6aed..cbc6ef603 100644 --- a/resources/qml/Governikus/TitleBar/+mobile/TitleBar.qml +++ b/src/ui/qml/modules/TitleBar/+mobile/TitleBar.qml @@ -1,28 +1,31 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import QtQuick.Controls import Governikus.Global import Governikus.Style +import Governikus.Type -Item { +Rectangle { id: titleBar + property alias enableTileStyle: titlePane.visible property NavigationAction navigationAction property var rightAction + property alias showContent: contentLayout.visible property bool showSeparator: false property bool smartEidUsed: false property alias title: titleText.text - property alias titleBarOpacity: background.opacity - property var topSafeAreaMargin: plugin.safeAreaMargins.top + property var topSafeAreaMargin: UiPluginModel.safeAreaMargins.top function setActiveFocus() { titleText.forceActiveFocus(Qt.MouseFocusReason); } - height: contentLayout.implicitHeight + topSafeAreaMargin + Style.dimens.titlebar_padding + color: Style.color.background + height: Math.ceil((showContent ? contentLayout.implicitHeight : 0) + topSafeAreaMargin + titlePane.shadowHeight) Rectangle { id: safeAreaBackground @@ -42,16 +45,8 @@ Item { top: parent.top } } - Rectangle { - id: background - - color: Style.color.background - - Behavior on color { - ColorAnimation { - duration: Constants.animation_duration - } - } + TitlePane { + id: titlePane anchors { bottom: parent.bottom @@ -64,26 +59,27 @@ Item { id: contentLayout spacing: Constants.text_spacing - width: Math.min(parent.width - 2 * Style.dimens.titlebar_padding - plugin.safeAreaMargins.left - plugin.safeAreaMargins.right, Style.dimens.max_text_width) + width: Math.min(parent.width - 2 * Style.dimens.titlebar_padding - UiPluginModel.safeAreaMargins.left - UiPluginModel.safeAreaMargins.right, Style.dimens.max_text_width) anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter - horizontalCenterOffset: (plugin.safeAreaMargins.left - plugin.safeAreaMargins.right) / 2 + horizontalCenterOffset: (UiPluginModel.safeAreaMargins.left - UiPluginModel.safeAreaMargins.right) / 2 } TitleBarNavigation { id: leftAction Layout.minimumHeight: Style.dimens.small_icon_size - action: titleBar.navigationAction ? titleBar.navigationAction.action : NavigationAction.Action.None + Layout.topMargin: Style.dimens.titlebar_padding enabled: titleBar.navigationAction ? titleBar.navigationAction.enabled : false + navAction: titleBar.navigationAction ? titleBar.navigationAction.action : NavigationAction.Action.None onClicked: titleBar.navigationAction.clicked() } RowLayout { spacing: Constants.component_spacing - GText { + GCrossBlendedText { id: titleText Accessible.focusable: true @@ -92,29 +88,6 @@ Item { elide: Text.ElideRight maximumLineCount: 2 textStyle: Style.text.title - - Behavior on text { - SequentialAnimation { - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.InCubic - property: "opacity" - target: titleText - to: 0 - } - PropertyAction { - property: "text" - target: titleText - } - PropertyAnimation { - duration: Constants.animation_duration - easing.type: Easing.OutCubic - property: "opacity" - target: titleText - to: 1 - } - } - } } GSpacer { Layout.fillWidth: true @@ -156,14 +129,9 @@ Item { } } } - } - GSeparator { - visible: titleBar.showSeparator - width: contentLayout.width - - anchors { - horizontalCenter: contentLayout.horizontalCenter - top: parent.bottom + GSeparator { + Layout.fillWidth: true + opacity: titleBar.showSeparator } } } diff --git a/src/ui/qml/modules/TitleBar/+mobile/TitleBarAction.qml b/src/ui/qml/modules/TitleBar/+mobile/TitleBarAction.qml new file mode 100644 index 000000000..32297fbcb --- /dev/null +++ b/src/ui/qml/modules/TitleBar/+mobile/TitleBarAction.qml @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtQuick.Layouts +import Governikus.Global +import Governikus.Style +import Governikus.View + +GLink { + id: baseItem + + Accessible.focusable: true + Accessible.ignored: icon.source == "" && text === "" + Accessible.name: text + Accessible.role: Accessible.Button + activeFocusOnTab: !Accessible.ignored + colorStyle: Style.color.linkTitle + horizontalPadding: 0 + textStyle: Style.text.navigation + + Keys.onSpacePressed: clicked() + + MouseArea { + id: mouseArea + + anchors.fill: parent + + onClicked: baseItem.clicked() + } +} diff --git a/resources/qml/Governikus/TitleBar/+mobile/TitleBarNavigation.qml b/src/ui/qml/modules/TitleBar/+mobile/TitleBarNavigation.qml similarity index 74% rename from resources/qml/Governikus/TitleBar/+mobile/TitleBarNavigation.qml rename to src/ui/qml/modules/TitleBar/+mobile/TitleBarNavigation.qml index 13b2a6c81..a3aab9471 100644 --- a/resources/qml/Governikus/TitleBar/+mobile/TitleBarNavigation.qml +++ b/src/ui/qml/modules/TitleBar/+mobile/TitleBarNavigation.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -8,11 +8,11 @@ import Governikus.Style TitleBarAction { id: baseItem - property int action: navigationAction.Action.None + property int navAction: NavigationAction.Action.None Accessible.name: text - icon: { - switch (baseItem.action) { + icon.source: { + switch (baseItem.navAction) { case NavigationAction.Action.Cancel: return "qrc:///images/material_close.svg"; case NavigationAction.Action.Back: @@ -22,7 +22,7 @@ TitleBarAction { } } text: { - switch (baseItem.action) { + switch (baseItem.navAction) { //: LABEL ANDROID IOS case NavigationAction.Action.Cancel: return qsTr("Cancel"); diff --git a/src/ui/qml/modules/TitleBar/+mobile/TitlePane.qml b/src/ui/qml/modules/TitleBar/+mobile/TitlePane.qml new file mode 100644 index 000000000..d9a45b009 --- /dev/null +++ b/src/ui/qml/modules/TitleBar/+mobile/TitlePane.qml @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Global + +Item { + id: root + + readonly property int shadowHeight: visible ? 15 : 0 + + RoundedRectangle { + id: background + + bottomLeftCorner: false + bottomRightCorner: false + + Behavior on color { + ColorAnimation { + duration: Constants.animation_duration + } + } + + layer { + enabled: GraphicsInfo.api !== GraphicsInfo.Software + + effect: GDropShadow { + shadowOpacity: 0.2 + shadowScale: 0.975 + shadowVerticalOffset: -root.shadowHeight + } + } + anchors { + fill: parent + topMargin: root.shadowHeight + } + } +} diff --git a/resources/qml/Governikus/UpdateView/+desktop/UpdateView.qml b/src/ui/qml/modules/UpdateView/+desktop/UpdateView.qml similarity index 74% rename from resources/qml/Governikus/UpdateView/+desktop/UpdateView.qml rename to src/ui/qml/modules/UpdateView/+desktop/UpdateView.qml index 15a2fd123..a3bd0fee3 100644 --- a/resources/qml/Governikus/UpdateView/+desktop/UpdateView.qml +++ b/src/ui/qml/modules/UpdateView/+desktop/UpdateView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import QtQuick @@ -10,13 +10,10 @@ import Governikus.InformationView import Governikus.ResultView import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel -import Governikus.Type.GlobalStatus -import Governikus.Type.ReleaseInformationModel -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.View -SectionPage { +FlickableSectionPage { id: root property alias downloadRunning: updateButtons.downloadInProgress @@ -24,14 +21,31 @@ SectionPage { signal leaveView + fillWidth: true + titleBarAction: TitleBarAction { //: LABEL DESKTOP text: qsTr("Application update") + + customSubAction: NavigationAction { + type: root.downloadRunning ? NavigationAction.Action.Cancel : NavigationAction.Action.Back + visible: true + + onClicked: { + if (root.downloadRunning) { + root.update.abortDownload(); + } + root.leaveView(); + } + } } ResultView { - buttonType: NavigationButton.Type.Back + Layout.fillHeight: true + Layout.fillWidth: true + anchors.fill: null icon: root.update.missingPlatform ? "qrc:///images/status_error_%1.svg".arg(Style.currentTheme.name) : "qrc:///images/workflow_error_network_%1.svg".arg(Style.currentTheme.name) + showOkButton: false text: root.update.missingPlatform ? //: LABEL DESKTOP Resulttext if no update information is available for the current platform. qsTr("An update information for your platform is not available.") : @@ -42,87 +56,85 @@ SectionPage { onNextView: leaveView() } ResultView { - buttonType: NavigationButton.Type.Back + Layout.fillHeight: true + Layout.fillWidth: true + anchors.fill: null icon: "qrc:///images/status_ok_%1.svg".arg(Style.currentTheme.name) + showOkButton: false //: LABEL DESKTOP The currently installed version is the most recent one, no action is required. text: qsTr("Your version %1 of %2 is up to date!").arg(Qt.application.version).arg(Qt.application.name) - visible: !SettingsModel.appUpdateAvailable && root.update.valid + visible: root.update.valid && !root.update.updateAvailable onNextView: leaveView() } - GPane { - id: pane - - activeFocusOnTab: true - title: qsTr("An update is available (installed version %1)").arg(Qt.application.version) + ColumnLayout { + spacing: Constants.pane_spacing visible: root.update.valid && root.update.updateAvailable - anchors { - fill: parent - margins: Constants.pane_padding + GText { + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Layout.leftMargin + elide: Text.ElideRight + maximumLineCount: 1 + text: qsTr("An update is available (installed version %1)").arg(Qt.application.version) + textStyle: Style.text.subline } UpdateViewInformation { id: updateInformation Layout.fillWidth: true + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Layout.leftMargin downloadSize: root.update.size releaseDate: root.update.date version: root.update.version } GSeparator { - Layout.bottomMargin: Layout.topMargin Layout.fillWidth: true - Layout.topMargin: Constants.text_spacing } - Item { - Layout.fillHeight: true - Layout.fillWidth: true - clip: true - - ReleaseNotesView { - model: releaseInformationModel.updateRelease + UpdateViewButtonRow { + id: updateButtons - anchors { - bottomMargin: Constants.pane_padding - fill: parent - leftMargin: Constants.pane_padding - topMargin: Constants.pane_padding - } - ReleaseInformationModel { - id: releaseInformationModel + Layout.fillWidth: true + Layout.leftMargin: Constants.pane_padding + Layout.rightMargin: Layout.leftMargin + progressText: "%1 KiB / %2 KiB".arg(root.update.downloadProgress.toLocaleString(Qt.locale(SettingsModel.language), "f", 0)).arg(root.update.downloadTotal.toLocaleString(Qt.locale(SettingsModel.language), "f", 0)) + progressValue: root.update.downloadProgress * 100 / root.update.downloadTotal - } - } - ScrollGradients { - anchors.fill: parent - color: Style.color.pane - leftMargin: 0 - rightMargin: 0 - } + onToggleUpdate: root.downloadRunning ? root.update.abortDownload() : download.exec() } GSeparator { - Layout.bottomMargin: Layout.topMargin Layout.fillWidth: true - Layout.topMargin: Constants.text_spacing } - UpdateViewButtonRow { - id: updateButtons - + GPane { Layout.fillWidth: true - progressText: "%1 KiB / %2 KiB".arg(root.update.downloadProgress.toLocaleString(Qt.locale(SettingsModel.language), "f", 0)).arg(root.update.downloadTotal.toLocaleString(Qt.locale(SettingsModel.language), "f", 0)) - progressValue: root.update.downloadProgress * 100 / root.update.downloadTotal + contentPadding: 0 + shadowScale: 1.005 + spacing: 0 + + ReleaseInformationModel { + id: releaseInformationModel - onRemindLater: root.leaveView() - onSkipUpdate: { - root.update.skipUpdate(); - root.leaveView(); } - onToggleUpdate: root.downloadRunning ? root.update.abortDownload() : download.exec() + Repeater { + id: releaseInfoRepeater + + model: releaseInformationModel.updateRelease + + FormattedTextView { + Layout.fillWidth: true + color: Style.color.transparent + idx: index + lineType: model.lineType + text: model.content + totalItemCount: releaseInfoRepeater.count + } + } } } Connections { function onFireAppDownloadFinished() { - plugin.fireQuitApplicationRequest(); + UiPluginModel.fireQuitApplicationRequest(); } function onFireAppUpdateFailed(pError) { warning.exec(pError); @@ -165,11 +177,11 @@ SectionPage { ConfirmationPopup { id: warning - property int error: GlobalStatus.No_Error + property int error: GlobalStatus.Code.No_Error function exec(pError) { root.downloadRunning = false; - if (pError !== GlobalStatus.Downloader_Aborted) { + if (pError !== GlobalStatus.Code.Downloader_Aborted) { error = pError; open(); } @@ -177,10 +189,10 @@ SectionPage { style: ConfirmationPopup.PopupStyle.OkButton text: switch (error) { - case GlobalStatus.Downloader_Data_Corrupted: + case GlobalStatus.Code.Downloader_Data_Corrupted: //: INFO DESKTOP Text of the popup that is shown when the app download failed because of a wrong checksum. return qsTr("The received data is broken. Check your network connection and try to restart the update."); - case GlobalStatus.Update_Execution_Failed: + case GlobalStatus.Code.Update_Execution_Failed: //: INFO DESKTOP Text of the popup that is shown when the execution of the update failed (1/2). return qsTr("The update could not be started automatically after a successful download. Please try to do a manual update. You can find the downloaded file %1here%2.").arg("".arg(SettingsModel.appUpdateData.downloadFolder)).arg(""); default: @@ -195,7 +207,7 @@ SectionPage { //: INFO DESKTOP Text of the popup that is shown when the execution of the update failed (2/2). text: qsTr("If this does not help, contact our %1support%2.").arg("".arg("https://www.ausweisapp.bund.de/%1/aa2/support".arg(SettingsModel.language))).arg("") - visible: warning.error === GlobalStatus.Update_Execution_Failed + visible: warning.error === GlobalStatus.Code.Update_Execution_Failed width: parent.width FocusFrame { diff --git a/resources/qml/Governikus/UpdateView/+desktop/UpdateViewButtonRow.qml b/src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewButtonRow.qml similarity index 58% rename from resources/qml/Governikus/UpdateView/+desktop/UpdateViewButtonRow.qml rename to src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewButtonRow.qml index 769382ff4..1e7c5322b 100644 --- a/resources/qml/Governikus/UpdateView/+desktop/UpdateViewButtonRow.qml +++ b/src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewButtonRow.qml @@ -1,12 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel -import Governikus.Type.SettingsModel +import Governikus.Type RowLayout { id: root @@ -15,8 +14,6 @@ RowLayout { property alias progressText: bar.text property alias progressValue: bar.value - signal remindLater - signal skipUpdate signal toggleUpdate spacing: Constants.component_spacing @@ -26,29 +23,12 @@ RowLayout { Layout.fillWidth: true activeFocusOnTab: true - backgroundColor: Style.color.control visible: downloadInProgress } - GButton { - - //: LABEL DESKTOP User choice to skip this update, the automatic update check will *not* inform about this update again. - text: qsTr("Skip update") - visible: !downloadInProgress - - onClicked: root.skipUpdate() - } GSpacer { Layout.fillWidth: true visible: !downloadInProgress } - GButton { - - //: LABEL DESKTOP The available update is shown again after next automatic update check. - text: qsTr("Remind me later") - visible: !downloadInProgress - - onClicked: root.remindLater() - } GButton { enabledTooltipText: SettingsModel.appUpdateData.url text: Qt.platform.os === "osx" ? diff --git a/resources/qml/Governikus/UpdateView/+desktop/UpdateViewInformation.qml b/src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewInformation.qml similarity index 95% rename from resources/qml/Governikus/UpdateView/+desktop/UpdateViewInformation.qml rename to src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewInformation.qml index 179c76d24..c4977d934 100644 --- a/resources/qml/Governikus/UpdateView/+desktop/UpdateViewInformation.qml +++ b/src/ui/qml/modules/UpdateView/+desktop/internal/UpdateViewInformation.qml @@ -1,11 +1,11 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style -import Governikus.Type.SettingsModel +import Governikus.Type import Governikus.View ColumnLayout { diff --git a/resources/qml/Governikus/View/+desktop/Controller.qml b/src/ui/qml/modules/View/+desktop/Controller.qml similarity index 53% rename from resources/qml/Governikus/View/+desktop/Controller.qml rename to src/ui/qml/modules/View/+desktop/Controller.qml index 14b987402..1aa44cbc4 100644 --- a/resources/qml/Governikus/View/+desktop/Controller.qml +++ b/src/ui/qml/modules/View/+desktop/Controller.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/View/+desktop/FocusPoint.qml b/src/ui/qml/modules/View/+desktop/FocusPoint.qml similarity index 66% rename from resources/qml/Governikus/View/+desktop/FocusPoint.qml rename to src/ui/qml/modules/View/+desktop/FocusPoint.qml index c1d87a75c..61a317c3e 100644 --- a/resources/qml/Governikus/View/+desktop/FocusPoint.qml +++ b/src/ui/qml/modules/View/+desktop/FocusPoint.qml @@ -1,10 +1,10 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style -import Governikus.Type.ApplicationModel +import Governikus.Type Text { id: border @@ -17,6 +17,6 @@ Text { font.pixelSize: Style.dimens.text horizontalAlignment: Text.AlignHCenter text: "✱" - visible: scope.activeFocus && plugin.showFocusIndicator + visible: scope.activeFocus && UiPluginModel.showFocusIndicator width: height } diff --git a/resources/qml/Governikus/View/+desktop/SectionPage.qml b/src/ui/qml/modules/View/+desktop/SectionPage.qml similarity index 87% rename from resources/qml/Governikus/View/+desktop/SectionPage.qml rename to src/ui/qml/modules/View/+desktop/SectionPage.qml index 73abb600e..ab805af6b 100644 --- a/resources/qml/Governikus/View/+desktop/SectionPage.qml +++ b/src/ui/qml/modules/View/+desktop/SectionPage.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -12,6 +12,7 @@ Controller { readonly property bool breadcrumpSearchPath: true property bool isAbstract: false + property bool smartEidUsed: false property TitleBarAction titleBarAction: null function setActive() { diff --git a/resources/qml/Governikus/View/+mobile/ContentArea.qml b/src/ui/qml/modules/View/+mobile/ContentArea.qml similarity index 90% rename from resources/qml/Governikus/View/+mobile/ContentArea.qml rename to src/ui/qml/modules/View/+mobile/ContentArea.qml index bddf8d980..c969a30e3 100644 --- a/resources/qml/Governikus/View/+mobile/ContentArea.qml +++ b/src/ui/qml/modules/View/+mobile/ContentArea.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -13,8 +13,7 @@ import Governikus.SelfAuthenticationView import Governikus.SmartView import Governikus.RemoteServiceView import Governikus.View -import Governikus.Type.SettingsModel -import Governikus.Type.UiModule +import Governikus.Type Item { id: baseItem @@ -58,6 +57,10 @@ Item { initialItem: SelfAuthenticationView { onBack: show(UiModule.DEFAULT) + onWorkflowFinished: pModuleToShow => { + show(pModuleToShow); + popAll(); + } } } TabBarView { @@ -86,7 +89,10 @@ Item { initialItem: ChangePinView { onClose: show(UiModule.DEFAULT) - onWorkflowFinished: popAll() + onWorkflowFinished: { + show(UiModule.DEFAULT); + popAll(); + } } } TabBarView { diff --git a/resources/qml/Governikus/View/+mobile/Controller.qml b/src/ui/qml/modules/View/+mobile/Controller.qml similarity index 96% rename from resources/qml/Governikus/View/+mobile/Controller.qml rename to src/ui/qml/modules/View/+mobile/Controller.qml index e2690774a..6c5ba6c5b 100644 --- a/resources/qml/Governikus/View/+mobile/Controller.qml +++ b/src/ui/qml/modules/View/+mobile/Controller.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls diff --git a/resources/qml/Governikus/View/+mobile/FocusPoint.qml b/src/ui/qml/modules/View/+mobile/FocusPoint.qml similarity index 56% rename from resources/qml/Governikus/View/+mobile/FocusPoint.qml rename to src/ui/qml/modules/View/+mobile/FocusPoint.qml index 21784bafc..f4e881f47 100644 --- a/resources/qml/Governikus/View/+mobile/FocusPoint.qml +++ b/src/ui/qml/modules/View/+mobile/FocusPoint.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/resources/qml/Governikus/View/+mobile/SectionPage.qml b/src/ui/qml/modules/View/+mobile/SectionPage.qml similarity index 59% rename from resources/qml/Governikus/View/+mobile/SectionPage.qml rename to src/ui/qml/modules/View/+mobile/SectionPage.qml index b9aa42ce8..5f01ef997 100644 --- a/resources/qml/Governikus/View/+mobile/SectionPage.qml +++ b/src/ui/qml/modules/View/+mobile/SectionPage.qml @@ -1,27 +1,24 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global import Governikus.Style import Governikus.TitleBar -import Governikus.Type.ApplicationModel +import Governikus.Type Controller { id: root - property bool contentIsScrolled: false - property bool hiddenNavbarPadding: false + property bool enableTileStyle: true property var navigationAction: null property var rightTitleBarAction: null + property bool showTitleBarContent: true property bool smartEidUsed: false required property string title - property real titleBarOpacity: 1 - property bool titleBarVisible: true - signal activate - signal reset + clip: true Connections { function onActivate() { diff --git a/resources/qml/Governikus/View/+mobile/TabBarView.qml b/src/ui/qml/modules/View/+mobile/TabBarView.qml similarity index 88% rename from resources/qml/Governikus/View/+mobile/TabBarView.qml rename to src/ui/qml/modules/View/+mobile/TabBarView.qml index d70facf68..9843535c2 100644 --- a/resources/qml/Governikus/View/+mobile/TabBarView.qml +++ b/src/ui/qml/modules/View/+mobile/TabBarView.qml @@ -1,15 +1,15 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls import Governikus.Global -import Governikus.Type.ApplicationModel +import Governikus.Type StackView { id: root - readonly property bool animationEnabled: !ApplicationModel.isScreenReaderRunning() + readonly property bool animationEnabled: !ApplicationModel.isScreenReaderRunning() && SettingsModel.useAnimations function doActivate() { if (visible && currentItem && typeof currentItem.activate === "function") { @@ -20,12 +20,12 @@ StackView { popEnter: enterAnimation.createObject(root) popExit: exitAnimation.createObject(root) pushEnter: enterAnimation.createObject(root, { - "reversed": true - }) + "reversed": true + }) pushExit: exitAnimation.createObject(root) replaceEnter: enterAnimation.createObject(root, { - "reversed": true - }) + "reversed": true + }) replaceExit: exitAnimation.createObject(root) onCurrentItemChanged: doActivate() diff --git a/resources/qml/Governikus/View/+mobile/FlickableSectionPage.qml b/src/ui/qml/modules/View/FlickableSectionPage.qml similarity index 78% rename from resources/qml/Governikus/View/+mobile/FlickableSectionPage.qml rename to src/ui/qml/modules/View/FlickableSectionPage.qml index 48f621309..0bdffafaa 100644 --- a/resources/qml/Governikus/View/+mobile/FlickableSectionPage.qml +++ b/src/ui/qml/modules/View/FlickableSectionPage.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -13,11 +13,14 @@ SectionPage { property real margins: Constants.pane_padding property alias spacing: flickable.spacing + function positionViewAtItem(pItem) { + flickable.positionViewAtItem(pItem); + } function scrollPageDown() { - flickable.scrollPageDown(baseItem); + flickable.scrollPageDown(); } function scrollPageUp() { - flickable.scrollPageUp(baseItem); + flickable.scrollPageUp(); } contentIsScrolled: !flickable.atYBeginning diff --git a/resources/qml/Governikus/View/+desktop/FocusFrame.qml b/src/ui/qml/modules/View/FocusFrame.qml similarity index 57% rename from resources/qml/Governikus/View/+desktop/FocusFrame.qml rename to src/ui/qml/modules/View/FocusFrame.qml index 2174323d9..585c83d95 100644 --- a/resources/qml/Governikus/View/+desktop/FocusFrame.qml +++ b/src/ui/qml/modules/View/FocusFrame.qml @@ -1,9 +1,10 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style +import Governikus.Type Rectangle { id: baseItem @@ -12,12 +13,12 @@ Rectangle { property Item framee: parent property real marginFactor: 1 property Item scope: parent - readonly property real size: Math.max(plugin.scaleFactor * 4, 1) + property real size: Math.max(UiPluginModel.scaleFactor * 4, 1) anchors.fill: framee anchors.margins: marginFactor * -size * 2 border.color: baseItem.borderColor - border.width: scope.activeFocus && plugin.showFocusIndicator ? size : 0 + border.width: scope.activeFocus && UiPluginModel.showFocusIndicator ? size : 0 color: Style.color.transparent - radius: size * 2 + radius: Math.min(height / 4, Style.dimens.control_radius) } diff --git a/resources/qml/Governikus/View/BaseController.qml b/src/ui/qml/modules/View/internal/BaseController.qml similarity index 90% rename from resources/qml/Governikus/View/BaseController.qml rename to src/ui/qml/modules/View/internal/BaseController.qml index 5b0a52b4a..dc8a88af1 100644 --- a/resources/qml/Governikus/View/BaseController.qml +++ b/src/ui/qml/modules/View/internal/BaseController.qml @@ -1,13 +1,17 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls -import Governikus.Type.ApplicationModel +import Governikus.Type Item { id: root + property bool contentIsScrolled: false + + signal activate + function showRemoveCardFeedback(workflowModel, success) { if (workflowModel.showRemoveCardFeedback) { workflowModel.showRemoveCardFeedback = false; @@ -15,7 +19,7 @@ Item { // The feedback notification will crash Apple's VoiceOver if it happens at the same time the app is redirecting // back to the browser. This happens with both the iOS toasts and our own toast-like replacement. To work around // this, we will not show the notification during an authentication on iOS with VoiceOver running. - if (ApplicationModel.isScreenReaderRunning() && ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_AUTHENTICATION) { + if (ApplicationModel.isScreenReaderRunning() && ApplicationModel.currentWorkflow === ApplicationModel.Workflow.AUTHENTICATION) { return; } } diff --git a/resources/qml/Governikus/WhiteListClient/+mobile/WhiteListSurveyView.qml b/src/ui/qml/modules/WhiteListClient/+mobile/WhiteListSurveyView.qml similarity index 93% rename from resources/qml/Governikus/WhiteListClient/+mobile/WhiteListSurveyView.qml rename to src/ui/qml/modules/WhiteListClient/+mobile/WhiteListSurveyView.qml index af37b5d75..8d7d93980 100644 --- a/resources/qml/Governikus/WhiteListClient/+mobile/WhiteListSurveyView.qml +++ b/src/ui/qml/modules/WhiteListClient/+mobile/WhiteListSurveyView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -8,9 +8,7 @@ import Governikus.Global import Governikus.Style import Governikus.TitleBar import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.SurveyModel +import Governikus.Type FlickableSectionPage { id: root @@ -104,12 +102,16 @@ FlickableSectionPage { text: qsTr("Do not send") onClicked: root.done(false) + onFocusChanged: if (focus) + root.positionViewAtItem(this) } GButton { //: LABEL ANDROID IOS text: qsTr("Send") onClicked: root.done(true) + onFocusChanged: if (focus) + root.positionViewAtItem(this) } } } diff --git a/resources/qml/Governikus/Workflow/+desktop/GeneralWorkflow.qml b/src/ui/qml/modules/Workflow/+desktop/GeneralWorkflow.qml similarity index 67% rename from resources/qml/Governikus/Workflow/+desktop/GeneralWorkflow.qml rename to src/ui/qml/modules/Workflow/+desktop/GeneralWorkflow.qml index fbd8e89d7..116131def 100644 --- a/resources/qml/Governikus/Workflow/+desktop/GeneralWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+desktop/GeneralWorkflow.qml @@ -1,17 +1,13 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls +import Governikus.Animations import Governikus.Global import Governikus.Style import Governikus.View -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.NumberModel -import Governikus.Type.PasswordType -import Governikus.Type.ReaderPlugIn -import Governikus.Type.RemoteServiceModel +import Governikus.Type SectionPage { id: root @@ -28,9 +24,14 @@ SectionPage { QtObject { id: d - readonly property bool foundPCSCReader: ApplicationModel.availableReader > 0 && ApplicationModel.isReaderTypeAvailable(ReaderPlugIn.PCSC) - readonly property bool foundRemoteReader: ApplicationModel.availableReader > 0 && ApplicationModel.isReaderTypeAvailable(ReaderPlugIn.REMOTE_IFD) + readonly property bool foundPCSCReader: ApplicationModel.availableReader > 0 && ApplicationModel.isReaderTypeAvailable(ReaderManagerPluginType.PCSC) + readonly property bool foundRemoteReader: ApplicationModel.availableReader > 0 && ApplicationModel.isReaderTypeAvailable(ReaderManagerPluginType.REMOTE_IFD) readonly property bool foundSelectedReader: ApplicationModel.availableReader > 0 + + onFoundPCSCReaderChanged: if (ApplicationModel.isScreenReaderRunning()) + subText.forceActiveFocus() + onFoundRemoteReaderChanged: if (ApplicationModel.isScreenReaderRunning()) + subText.forceActiveFocus() } Connections { function onFireCertificateRemoved(pDeviceName) { @@ -39,45 +40,27 @@ SectionPage { target: RemoteServiceModel } - GText { - Accessible.ignored: true - anchors.bottom: retryCounter.top - anchors.bottomMargin: Constants.component_spacing - anchors.horizontalCenter: retryCounter.horizontalCenter - font.bold: true - //: LABEL DESKTOP - text: qsTr("Attempts") - visible: retryCounter.visible - } - RetryCounter { - id: retryCounter - - anchors.left: parent.left - anchors.margins: height - anchors.top: parent.top - visible: NumberModel.retryCounter >= 0 && NumberModel.passwordType === PasswordType.PIN - } - TintableAnimation { - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.top - anchors.verticalCenterOffset: parent.height / 4 - height: Style.dimens.header_icon_size - source: { - if (d.foundRemoteReader) { - return "qrc:///images/desktop/workflow_waitfor_idcard_sak.webp"; - } - if (d.foundPCSCReader) { - return "qrc:///images/desktop/workflow_waitfor_idcard_usb.webp"; + AnimationLoader { + type: { + if (waitingFor === Workflow.WaitingFor.Reader) { + if (d.foundRemoteReader) { + return AnimationLoader.Type.WAIT_FOR_CARD_SAC; + } + if (d.foundPCSCReader) { + return AnimationLoader.Type.WAIT_FOR_CARD_USB; + } + return AnimationLoader.Type.WAIT_FOR_READER; } - return "qrc:///images/desktop/workflow_waitfor_reader.webp"; + return AnimationLoader.Type.NONE; + } + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: Constants.component_spacing } - tintColor: Style.color.control - visible: waitingFor === Workflow.WaitingFor.Reader } TintableIcon { - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.top - anchors.verticalCenterOffset: parent.height / 4 source: { if (d.foundRemoteReader) { return "qrc:///images/desktop/workflow_idcard_nfc.svg"; @@ -85,8 +68,14 @@ SectionPage { return "qrc:///images/desktop/workflow_idcard_usb.svg"; } sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image visible: waitingFor === Workflow.WaitingFor.Password + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: Constants.component_spacing + } } ProgressCircle { id: progressCircle @@ -95,8 +84,6 @@ SectionPage { Accessible.name: qsTr("Step %1 of 3").arg(state) Accessible.role: Accessible.ProgressBar activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.verticalCenter state: switch (waitingFor) { case Workflow.WaitingFor.Reader: return d.foundSelectedReader ? "2" : "1"; @@ -107,6 +94,11 @@ SectionPage { } visible: waitingFor !== Workflow.WaitingFor.None + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 3 * Constants.component_spacing + Style.dimens.header_icon_size + } FocusFrame { } } @@ -115,9 +107,6 @@ SectionPage { Accessible.name: mainText.text activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: progressCircle.bottom - anchors.topMargin: Constants.component_spacing horizontalAlignment: Text.AlignHCenter text: { switch (waitingFor) { @@ -145,6 +134,11 @@ SectionPage { visible: text !== "" width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) + anchors { + horizontalCenter: parent.horizontalCenter + top: progressCircle.bottom + topMargin: Constants.component_spacing * 2 + } FocusFrame { } } @@ -165,15 +159,12 @@ SectionPage { } activeFocusOnTab: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: mainText.bottom - anchors.topMargin: Constants.text_spacing horizontalAlignment: Text.AlignHCenter text: { switch (waitingFor) { case Workflow.WaitingFor.Reader: //: INFO DESKTOP AA2 is waiting for the card reader or the ID card. - return d.foundSelectedReader ? requestCardText : qsTr("No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and available. Open the reader settings to configure readers and get more information about supported readers."); + return d.foundSelectedReader ? requestCardText : qsTr("No card reader detected. Please make sure that an USB card reader is connected or a smartphone as card reader is paired and ready. Open the reader settings to configure readers and get more information about supported readers."); case Workflow.WaitingFor.Password: //: INFO DESKTOP The card reader is a comfort reader with its own display, the user is requested to pay attention to that display (instead of the AA2). return qsTr("Please observe the display of your card reader."); @@ -185,20 +176,27 @@ SectionPage { visible: text !== "" && !ApplicationModel.extendedLengthApdusUnsupported && AuthModel.eidTypeMismatchError === "" width: Math.min(parent.width - (2 * Constants.pane_padding), Style.dimens.max_text_width) + anchors { + horizontalCenter: parent.horizontalCenter + top: mainText.bottom + topMargin: Constants.text_spacing * 2 + } FocusFrame { } } GButton { id: readerSettingsLink - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: subText.bottom - anchors.topMargin: Constants.component_spacing - //: INFO DESKTOP text: qsTr("Go to reader settings") visible: waitingFor === Workflow.WaitingFor.Reader && !d.foundSelectedReader onClicked: root.settingsRequested() + + anchors { + horizontalCenter: parent.horizontalCenter + top: subText.bottom + topMargin: Constants.component_spacing + } } } diff --git a/resources/qml/Governikus/Workflow/+desktop/ProgressCircle.qml b/src/ui/qml/modules/Workflow/+desktop/internal/ProgressCircle.qml similarity index 75% rename from resources/qml/Governikus/Workflow/+desktop/ProgressCircle.qml rename to src/ui/qml/modules/Workflow/+desktop/internal/ProgressCircle.qml index ab620c455..79654076c 100644 --- a/resources/qml/Governikus/Workflow/+desktop/ProgressCircle.qml +++ b/src/ui/qml/modules/Workflow/+desktop/internal/ProgressCircle.qml @@ -1,9 +1,10 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style +import Governikus.Type Item { height: Math.max(circle1.maximumHeight, circle2.maximumHeight, circle3.maximumHeight) @@ -15,48 +16,27 @@ Item { name: "1" PropertyChanges { - enabled: true - target: circle1 - } - PropertyChanges { - enabled: false - target: circle2 - } - PropertyChanges { - enabled: false - target: circle3 + circle1.enabled: true + circle2.enabled: false + circle3.enabled: false } }, State { name: "2" PropertyChanges { - enabled: false - target: circle1 - } - PropertyChanges { - enabled: true - target: circle2 - } - PropertyChanges { - enabled: false - target: circle3 + circle1.enabled: false + circle2.enabled: true + circle3.enabled: false } }, State { name: "3" PropertyChanges { - enabled: false - target: circle1 - } - PropertyChanges { - enabled: false - target: circle2 - } - PropertyChanges { - enabled: true - target: circle3 + circle1.enabled: false + circle2.enabled: false + circle3.enabled: true } } ] @@ -85,7 +65,7 @@ Item { QtObject { id: d - readonly property int stepWidth: plugin.scaleFactor * 250 + readonly property int stepWidth: UiPluginModel.scaleFactor * 250 } Rectangle { id: line1 diff --git a/resources/qml/Governikus/Workflow/+desktop/TextCircle.qml b/src/ui/qml/modules/Workflow/+desktop/internal/TextCircle.qml similarity index 77% rename from resources/qml/Governikus/Workflow/+desktop/TextCircle.qml rename to src/ui/qml/modules/Workflow/+desktop/internal/TextCircle.qml index 146a73e91..b9da627da 100644 --- a/resources/qml/Governikus/Workflow/+desktop/TextCircle.qml +++ b/src/ui/qml/modules/Workflow/+desktop/internal/TextCircle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -12,7 +12,7 @@ Rectangle { readonly property double maximumHeight: enabledFontMetrics.height * 2.5 property alias text: number.text - border.color: Style.color.control_border + border.color: Style.color.control.border.basic border.width: Style.dimens.border_width color: Style.color.transparent enabled: false @@ -37,12 +37,12 @@ Rectangle { Accessible.ignored: true anchors.centerIn: parent - font.pixelSize: Style.dimens.text_headline * d.scaleFactor + font.pixelSize: Style.dimens.textHeadline * d.scaleFactor textStyle: Style.text.headline } FontMetrics { id: enabledFontMetrics - font.pixelSize: Style.dimens.text_headline + font.pixelSize: Style.dimens.textHeadline } } diff --git a/resources/qml/Governikus/Workflow/+mobile/GeneralWorkflow.qml b/src/ui/qml/modules/Workflow/+mobile/GeneralWorkflow.qml similarity index 56% rename from resources/qml/Governikus/Workflow/+mobile/GeneralWorkflow.qml rename to src/ui/qml/modules/Workflow/+mobile/GeneralWorkflow.qml index 7038a2752..7b2241000 100644 --- a/resources/qml/Governikus/Workflow/+mobile/GeneralWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+mobile/GeneralWorkflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Controls @@ -11,14 +11,14 @@ import Governikus.Workflow import Governikus.ResultView import Governikus.Style import Governikus.View -import Governikus.Type.ReaderPlugIn +import Governikus.Type SectionPage { id: baseItem property alias autoInsertCard: technologyInfo.autoInsertCard property bool hideSwitch: false - property var initialPlugIn: null + property var initialPlugin: null readonly property bool isLandscape: ApplicationWindow.window && ApplicationWindow.menuBar ? ApplicationWindow.window.height - ApplicationWindow.menuBar.height < ApplicationWindow.window.width : false property alias workflowModel: technologyInfo.workflowModel property string workflowTitle @@ -33,11 +33,18 @@ SectionPage { } Component.onCompleted: { - if (initialPlugIn != null) { - technologySwitch.requestPluginType(initialPlugIn); + if (initialPlugin != null) { + technologySwitch.requestPluginType(initialPlugin); } } + Connections { + function onReaderPluginTypeChanged() { + baseItem.updateFocus(); + } + + target: workflowModel + } GridLayout { anchors.fill: parent columns: 3 @@ -49,6 +56,28 @@ SectionPage { Layout.fillHeight: true Layout.fillWidth: true + + onRemoteDeviceUnpaired: pDeviceName => { + baseItem.push(deviceUnpairedView, { + "deviceName": pDeviceName + }); + } + + Component { + id: deviceUnpairedView + + ResultView { + property string deviceName + + icon: "qrc:///images/workflow_error_no_sak_%1.svg".arg(Style.currentTheme.name) + //: INFO ANDROID IOS The paired smartphone was removed since it did not respond to connection attempts. It needs to be paired again before using it. + text: qsTr("The device \"%1\" was unpaired because it did not react to connection attempts. Pair the device again to use it as a card reader.").arg(deviceName) + title: baseItem.workflowTitle + + onCancelClicked: baseItem.pop() + onContinueClicked: baseItem.pop() + } + } } GSeparator { id: separator @@ -66,11 +95,11 @@ SectionPage { Layout.fillHeight: isLandscape Layout.fillWidth: !isLandscape flowVertically: isLandscape - selectedTechnology: workflowModel.readerPlugInType - supportedTechnologies: workflowModel.supportedPlugInTypes - visible: !hideSwitch && workflowModel.supportedPlugInTypes.length > 1 + selectedTechnology: workflowModel.readerPluginType + supportedTechnologies: workflowModel.supportedPluginTypes + visible: !hideSwitch && workflowModel.supportedPluginTypes.length > 1 - onRequestPluginType: pReaderPlugInType => workflowModel.readerPlugInType = pReaderPlugInType + onRequestPluginType: pReaderPluginType => workflowModel.readerPluginType = pReaderPluginType } } } diff --git a/resources/qml/Governikus/Workflow/+mobile/NfcWorkflow.qml b/src/ui/qml/modules/Workflow/+mobile/NfcWorkflow.qml similarity index 56% rename from resources/qml/Governikus/Workflow/+mobile/NfcWorkflow.qml rename to src/ui/qml/modules/Workflow/+mobile/NfcWorkflow.qml index 55567753c..747b28415 100644 --- a/resources/qml/Governikus/Workflow/+mobile/NfcWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+mobile/NfcWorkflow.qml @@ -1,22 +1,18 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.TechnologyInfo -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.ReaderPlugIn -import Governikus.Type.NumberModel -import Governikus.Type.RemoteServiceModel +import Governikus.Type GFlickableColumnLayout { id: baseItem - readonly property bool isRemoteWorkflow: ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_REMOTE_SERVICE - readonly property int nfcState: visible ? ApplicationModel.nfcState : ApplicationModel.NFC_UNAVAILABLE + readonly property bool isRemoteWorkflow: ApplicationModel.currentWorkflow === ApplicationModel.Workflow.REMOTE_SERVICE + readonly property int nfcState: visible ? ApplicationModel.nfcState : ApplicationModel.NfcState.UNAVAILABLE signal startScanIfNecessary @@ -32,9 +28,9 @@ GFlickableColumnLayout { Layout.alignment: Qt.AlignCenter state: { switch (nfcState) { - case ApplicationModel.NFC_READY: + case ApplicationModel.NfcState.READY: return "on"; - case ApplicationModel.NFC_UNAVAILABLE: + case ApplicationModel.NfcState.UNAVAILABLE: return "unavailable"; default: return "off"; @@ -44,13 +40,22 @@ GFlickableColumnLayout { TechnologyInfo { id: technologyInfo + //: INFO ANDROID Text regarding ID card position animations + readonly property string animationText: qsTr("The animations depict possible positions.") + //: INFO ANDROID Text regarding different NFC chip positions on different smartphones + readonly property string deviceText: qsTr("The exact position of the ID card is device dependent.") + //: INFO ANDROID Text that one ID card position should be kept for several seconds + readonly property string keepPositionText: qsTr("Keep one position for several seconds before trying another one and do not move the ID card after contact was established.") + //: INFO ANDROID Text regarding the ID card position on the device + readonly property string positionText: qsTr("Please place your ID card directly on the device's back side.") + Layout.alignment: Qt.AlignHCenter enableButtonText: { switch (nfcState) { - case ApplicationModel.NFC_DISABLED: + case ApplicationModel.NfcState.DISABLED: //: INFO ANDROID IOS return qsTr("Go to NFC settings"); - case ApplicationModel.NFC_INACTIVE: + case ApplicationModel.NfcState.INACTIVE: //: LABEL ANDROID IOS return qsTr("Start NFC scan"); default: @@ -59,17 +64,19 @@ GFlickableColumnLayout { } enableText: { switch (nfcState) { - case ApplicationModel.NFC_UNAVAILABLE: + case ApplicationModel.NfcState.UNAVAILABLE: + //: INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. + return qsTr("This device cannot be used to read your ID card.") + "

      " + //: INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - return qsTr("Unfortunately, this functionality is not available on your device.") + "
      " + + qsTr("If you want to use the online identification on this device anyway, you can connect another NFC capable smartphone as a card reader.") + "

      " + //: INFO ANDROID IOS AA2 can't use NFC on this device, suggest to use SaK instead. - qsTr("However, you can use a separate smartphone as card reader to utilize the eID function."); - case ApplicationModel.NFC_DISABLED: + qsTr("To pair a smartphone select the WiFi option and click Manage Pairings."); + case ApplicationModel.NfcState.DISABLED: //: INFO ANDROID IOS NFC is available but needs to be activated in the settings of the smartphone. return qsTr("NFC is switched off.") + "
      " + //: INFO ANDROID IOS NFC is available but needs to be activated in the settings of the smartphone. qsTr("Please enable NFC in your system settings."); - case ApplicationModel.NFC_INACTIVE: + case ApplicationModel.NfcState.INACTIVE: //: INFO ANDROID IOS NFC is available and enabled but needs to be started. return qsTr("NFC scan is not running.") + "
      " + //: INFO ANDROID IOS NFC is available and enabled but needs to be started. @@ -79,7 +86,7 @@ GFlickableColumnLayout { } } subTitleText: { - if (nfcState !== ApplicationModel.NFC_READY) { + if (nfcState !== ApplicationModel.NfcState.READY) { return ""; } if (AuthModel.eidTypeMismatchError !== "") { @@ -91,9 +98,10 @@ GFlickableColumnLayout { } else if (Constants.is_layout_ios) { //: INFO IOS The ID card may be inserted, the authentication process may be started. return qsTr("Please place your ID card on the top of the device's back side."); + } else if (SettingsModel.useAnimations) { + return "%1

      %2 %3 %4".arg(positionText).arg(deviceText).arg(animationText).arg(keepPositionText); } else { - //: INFO ANDROID The ID card may be inserted, the authentication process may be started. - return qsTr("Please place your ID card directly on the device's back side.

      The exact position of the ID card is device dependent. The animations depict possible positions. Keep one position for several seconds before trying another one and do not move the ID card after contact was established."); + return "%1

      %2 %3".arg(positionText).arg(deviceText).arg(keepPositionText); } } titleText: { @@ -102,13 +110,13 @@ GFlickableColumnLayout { return qsTr("The device \"%1\" wants to use this smartphone as card reader and connect to your id card.").arg(RemoteServiceModel.connectedClientName); } switch (nfcState) { - case ApplicationModel.NFC_UNAVAILABLE: + case ApplicationModel.NfcState.UNAVAILABLE: //: INFO ANDROID IOS return qsTr("NFC is not available"); - case ApplicationModel.NFC_DISABLED: + case ApplicationModel.NfcState.DISABLED: //: INFO ANDROID IOS return qsTr("NFC is disabled"); - case ApplicationModel.NFC_INACTIVE: + case ApplicationModel.NfcState.INACTIVE: //: INFO ANDROID IOS return qsTr("Start scan"); default: @@ -117,6 +125,7 @@ GFlickableColumnLayout { } } - onEnableClicked: nfcState === ApplicationModel.NFC_DISABLED ? ApplicationModel.showSettings(ApplicationModel.SETTING_NFC) : startScanIfNecessary() + onEnableClicked: nfcState === ApplicationModel.NfcState.DISABLED ? ApplicationModel.showSettings(ApplicationModel.Settings.NFC) : startScanIfNecessary() + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) } } diff --git a/resources/qml/Governikus/Workflow/+mobile/SimulatorWorkflow.qml b/src/ui/qml/modules/Workflow/+mobile/SimulatorWorkflow.qml similarity index 88% rename from resources/qml/Governikus/Workflow/+mobile/SimulatorWorkflow.qml rename to src/ui/qml/modules/Workflow/+mobile/SimulatorWorkflow.qml index 9b0aa8605..0e94661a6 100644 --- a/resources/qml/Governikus/Workflow/+mobile/SimulatorWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+mobile/SimulatorWorkflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -45,5 +45,6 @@ GFlickableColumnLayout { titleText: qsTr("Simulator") onEnableClicked: workflowModel.insertSimulator() + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) } } diff --git a/resources/qml/Governikus/Workflow/+mobile/SmartWorkflow.qml b/src/ui/qml/modules/Workflow/+mobile/SmartWorkflow.qml similarity index 84% rename from resources/qml/Governikus/Workflow/+mobile/SmartWorkflow.qml rename to src/ui/qml/modules/Workflow/+mobile/SmartWorkflow.qml index 3e21c9351..3b4da9fc9 100644 --- a/resources/qml/Governikus/Workflow/+mobile/SmartWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+mobile/SmartWorkflow.qml @@ -1,25 +1,21 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts import Governikus.Global import Governikus.Style import Governikus.TechnologyInfo -import Governikus.Type.ApplicationModel -import Governikus.Type.SmartModel -import Governikus.Type.NumberModel -import Governikus.Type.PersonalizationModel -import Governikus.Type.RemoteServiceModel +import Governikus.Type GFlickableColumnLayout { id: baseItem property bool autoInsertCard: false - readonly property bool canUseSmart: smartState === SmartModel.SMART_READY && isSmartCardAllowed && SmartModel.isScanRunning - readonly property bool isRemoteWorkflow: ApplicationModel.currentWorkflow === ApplicationModel.WORKFLOW_REMOTE_SERVICE + readonly property bool canUseSmart: smartState === SmartModel.State.READY && isSmartCardAllowed && SmartModel.isScanRunning + readonly property bool isRemoteWorkflow: ApplicationModel.currentWorkflow === ApplicationModel.Workflow.REMOTE_SERVICE readonly property bool isSmartCardAllowed: workflowModel.isCurrentSmartCardAllowed - readonly property int smartState: SmartModel.smartState + readonly property int smartState: SmartModel.state property var workflowModel clip: true @@ -49,13 +45,13 @@ GFlickableColumnLayout { } enableText: { switch (smartState) { - case SmartModel.SMART_UPDATING_STATUS: + case SmartModel.State.UPDATING_STATUS: //: LABEL ANDROID IOS return qsTr("Please wait a moment."); - case SmartModel.SMART_UNAVAILABLE: + case SmartModel.State.UNAVAILABLE: //: LABEL ANDROID IOS return qsTr("Unfortunately, Smart-eID is not supported by your device.\n\nTo proceed use your ID card by selecting the NFC interface or choose \"WiFi\" to connect with another device as cardreader."); - case SmartModel.SMART_READY: + case SmartModel.State.READY: if (!isSmartCardAllowed) { //: LABEL ANDROID IOS return qsTr("Unfortunately, using your Smart-eID for this authentication is not allowed by the provider.\n\nTo proceed use your ID card by selecting the NFC interface or choose \"WiFi\" to connect with another device as cardreader."); @@ -87,13 +83,13 @@ GFlickableColumnLayout { return qsTr("The device \"%1\" wants to access your Smart-eID.").arg(RemoteServiceModel.connectedClientName); } switch (smartState) { - case SmartModel.SMART_UPDATING_STATUS: + case SmartModel.State.UPDATING_STATUS: //: LABEL ANDROID IOS return qsTr("Updating Smart-eID status..."); - case SmartModel.SMART_UNAVAILABLE: + case SmartModel.State.UNAVAILABLE: //: LABEL ANDROID IOS return qsTr("Smart-eID unsupported"); - case SmartModel.SMART_READY: + case SmartModel.State.READY: if (!isSmartCardAllowed) { //: LABEL ANDROID IOS return qsTr("Smart-eID disallowed"); @@ -113,5 +109,6 @@ GFlickableColumnLayout { onEnableClicked: if (canUseSmart) workflowModel.insertSmartCard() + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) } } diff --git a/resources/qml/Governikus/Workflow/+mobile/NfcProgressIndicator.qml b/src/ui/qml/modules/Workflow/+mobile/internal/NfcProgressIndicator.qml similarity index 59% rename from resources/qml/Governikus/Workflow/+mobile/NfcProgressIndicator.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/NfcProgressIndicator.qml index 16a670069..8ac7d85a5 100644 --- a/resources/qml/Governikus/Workflow/+mobile/NfcProgressIndicator.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/NfcProgressIndicator.qml @@ -1,10 +1,10 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global import Governikus.Style -import Governikus.Type.CardPositionModel +import Governikus.Type Item { id: root @@ -22,64 +22,50 @@ Item { name: "unavailable" PropertyChanges { - source: "qrc:///images/mobile/x.svg" - target: symbol - tintColor: Style.color.text_warning - visible: true + modelActivationTimer.running: false + symbol.source: "qrc:///images/mobile/x.svg" + symbol.tintColor: Style.color.error + symbol.visible: true } PropertyChanges { - opacity: 0 + card.opacity: 0 + cardPositionModel.running: false restoreEntryValues: false - target: card - } - PropertyChanges { - running: false - target: modelActivationTimer - } - PropertyChanges { - restoreEntryValues: false - running: false - target: cardPositionModel } }, State { name: "off" PropertyChanges { - source: "qrc:///images/mobile/questionmark.svg" - target: symbol - tintColor: Style.color.control - visible: true + modelActivationTimer.running: false + symbol.source: "qrc:///images/mobile/questionmark.svg" + symbol.tintColor: Style.color.image + symbol.visible: true } PropertyChanges { - opacity: 0 + card.opacity: 0 + cardPositionModel.running: false restoreEntryValues: false - target: card - } - PropertyChanges { - running: false - target: modelActivationTimer - } - PropertyChanges { - restoreEntryValues: false - running: false - target: cardPositionModel } }, State { name: "on" PropertyChanges { - target: symbol - visible: false - } - PropertyChanges { - running: true - target: modelActivationTimer + modelActivationTimer.running: SettingsModel.useAnimations + symbol.visible: false } } ] + Component.onCompleted: { + if (!SettingsModel.useAnimations) { + cardPosition = cardPositionModel.getCardPosition(); + animation.start(); + animation.complete(); + } + } + Connections { function onFireCardPositionChanged() { cardPosition = cardPositionModel.getCardPosition(); @@ -165,7 +151,7 @@ Item { easing.type: Easing.InCubic property: "opacity" target: card - to: 0 + to: SettingsModel.useAnimations ? 0 : 1 } PauseAnimation { duration: animation.pauseDuration * 0.1 @@ -177,55 +163,48 @@ Item { anchors.centerIn: parent source: symbol.visible ? "qrc:///images/mobile/phone_nfc_info.svg" : "qrc:///images/mobile/phone_nfc.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image z: 0 + } + TintableIcon { + id: card + + anchors.centerIn: fakephone + opacity: 0 + source: "qrc:///images/mobile/card.svg" + sourceSize.height: fakephone.height * 0.5 + tintColor: Style.color.image + visible: !symbol.visible + } + Item { + id: fakephone - TintableIcon { - id: card + anchors.bottom: phone.bottom + anchors.horizontalCenter: phone.horizontalCenter + anchors.horizontalCenterOffset: -phone.width * 0.06 + anchors.top: phone.top + clip: true + width: phone.width * 0.43 - anchors.centerIn: fakephone - asynchronous: true - fillMode: Image.PreserveAspectFit - opacity: 0 - source: "qrc:///images/mobile/card.svg" - sourceSize.height: fakephone.height * 0.5 - tintColor: Style.color.control - visible: !symbol.visible - } - Item { - id: fakephone - - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - anchors.horizontalCenterOffset: -parent.width * 0.06 - anchors.top: parent.top - clip: true - width: parent.width * 0.43 - - TintableIcon { - asynchronous: true - fillMode: Image.PreserveAspectFit - opacity: card.z < 0 ? card.opacity : 0 - rotation: card.rotation - source: "qrc:///images/mobile/card.svg" - sourceSize.height: card.sourceSize.height - tintColor: Style.color.control_disabled - visible: card.visible - x: card.x - fakephone.x - y: card.y - fakephone.y - z: 1 - } - } TintableIcon { - id: symbol - - anchors.horizontalCenter: phone.right - anchors.horizontalCenterOffset: -phone.width * 0.19 - anchors.verticalCenter: phone.bottom - anchors.verticalCenterOffset: -phone.height * 0.36 - asynchronous: true - fillMode: Image.PreserveAspectFit - sourceSize.height: phone.height * 0.2 + opacity: card.z < 0 ? card.opacity : 0 + rotation: card.rotation + source: "qrc:///images/mobile/card.svg" + sourceSize.height: card.sourceSize.height + tintColor: Style.color.control.background.disabled + visible: card.visible + x: card.x - fakephone.x + y: card.y - fakephone.y + z: 1 } } + TintableIcon { + id: symbol + + anchors.horizontalCenter: phone.right + anchors.horizontalCenterOffset: -phone.width * 0.19 + anchors.verticalCenter: phone.bottom + anchors.verticalCenterOffset: -phone.height * 0.36 + sourceSize.height: phone.height * 0.2 + } } diff --git a/resources/qml/Governikus/Workflow/+mobile/ProgressCircle.qml b/src/ui/qml/modules/Workflow/+mobile/internal/ProgressCircle.qml similarity index 68% rename from resources/qml/Governikus/Workflow/+mobile/ProgressCircle.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/ProgressCircle.qml index 19b3308e9..e64073cad 100644 --- a/resources/qml/Governikus/Workflow/+mobile/ProgressCircle.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/ProgressCircle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global @@ -8,9 +8,9 @@ import Governikus.Style Item { id: baseItem - readonly property int _stepWidth: 60 + readonly property int stepWidth: 60 - height: 70 + implicitHeight: 70 state: "inactive" states: [ @@ -18,48 +18,27 @@ Item { name: "inactive" PropertyChanges { - state: "inactive" - target: tCircle1 - } - PropertyChanges { - state: "inactive" - target: tCircle2 - } - PropertyChanges { - anchors.leftMargin: 0 - target: rec1 + rec1.anchors.leftMargin: 0 + tCircle1.state: "inactive" + tCircle2.state: "inactive" } }, State { name: "one" PropertyChanges { - state: "active" - target: tCircle1 - } - PropertyChanges { - state: "inactive" - target: tCircle2 - } - PropertyChanges { - anchors.leftMargin: 0 - target: rec1 + rec1.anchors.leftMargin: 0 + tCircle1.state: "active" + tCircle2.state: "inactive" } }, State { name: "two" PropertyChanges { - state: "inactive" - target: tCircle1 - } - PropertyChanges { - state: "active" - target: tCircle2 - } - PropertyChanges { - anchors.leftMargin: -_stepWidth - target: rec1 + rec1.anchors.leftMargin: -stepWidth + tCircle1.state: "inactive" + tCircle2.state: "active" } } ] @@ -83,7 +62,7 @@ Item { anchors.verticalCenter: parent.verticalCenter color: Constants.blue height: 2 - width: _stepWidth + width: stepWidth } Rectangle { id: tCircle1 @@ -103,16 +82,14 @@ Item { name: "active" PropertyChanges { - target: innerDisc - width: 50 + innerDisc.width: 50 } }, State { name: "inactive" PropertyChanges { - target: innerDisc - width: 25 + innerDisc.width: 25 } } ] @@ -135,14 +112,14 @@ Item { anchors.centerIn: parent border.color: Constants.blue border.width: 1 - color: tCircle1.state === "active" ? Style.color.control : Constants.white + color: tCircle1.state === "active" ? Style.color.control.background.basic : Constants.white height: width radius: width / 2 GText { Accessible.ignored: true anchors.centerIn: parent - color: tCircle1.state === "active" ? Constants.white : Style.color.control + color: tCircle1.state === "active" ? Constants.white : Style.color.control.background.basic font.bold: true font.pixelSize: parent.height / 3 text: "1" diff --git a/resources/qml/Governikus/Workflow/+mobile/RemoteProgressIndicator.qml b/src/ui/qml/modules/Workflow/+mobile/internal/RemoteProgressIndicator.qml similarity index 53% rename from resources/qml/Governikus/Workflow/+mobile/RemoteProgressIndicator.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/RemoteProgressIndicator.qml index 4a400bf7b..b26c1c627 100644 --- a/resources/qml/Governikus/Workflow/+mobile/RemoteProgressIndicator.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/RemoteProgressIndicator.qml @@ -1,25 +1,32 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick +import QtQuick.Layouts +import Governikus.Animations import Governikus.Global import Governikus.Style -Item { +ColumnLayout { id: baseItem property bool foundSelectedReader: false - implicitHeight: Style.dimens.workflow_progress_indicator_size - implicitWidth: phone.implicitWidth + Layout.maximumHeight: Style.dimens.workflow_progress_indicator_size + Layout.minimumHeight: Style.dimens.workflow_progress_indicator_size + Layout.preferredHeight: Style.dimens.workflow_progress_indicator_size + spacing: 0 + GSpacer { + Layout.fillHeight: true + } TintableIcon { id: phone - anchors.centerIn: parent + Layout.alignment: Qt.AlignHCenter source: "qrc:///images/mobile/phone_remote_info.svg" sourceSize.height: Style.dimens.header_icon_size - tintColor: Style.color.control + tintColor: Style.color.image visible: !baseItem.foundSelectedReader Image { @@ -35,28 +42,18 @@ Item { sourceSize.height: phone.height * 0.2 } } - Item { - id: currentAction - - anchors.bottom: pCircle.top - anchors.left: parent.left - anchors.margins: Constants.component_spacing - anchors.right: parent.right - anchors.top: parent.top - - CardReader { - anchors.centerIn: parent - height: parent.height - pinFieldAnimation: false - visible: baseItem.foundSelectedReader - } + WaitForCardSacAnimation { + Layout.alignment: Qt.AlignHCenter + sourceSize.height: Style.dimens.medium_icon_size + visible: baseItem.foundSelectedReader + } + GSpacer { + Layout.fillHeight: true } ProgressCircle { id: pCircle - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right + Layout.alignment: Qt.AlignHCenter state: baseItem.foundSelectedReader ? "two" : "off" visible: baseItem.foundSelectedReader } diff --git a/resources/qml/Governikus/Workflow/+mobile/RemoteWorkflow.qml b/src/ui/qml/modules/Workflow/+mobile/internal/RemoteWorkflow.qml similarity index 83% rename from resources/qml/Governikus/Workflow/+mobile/RemoteWorkflow.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/RemoteWorkflow.qml index 90bd72c49..3aa9fbdbd 100644 --- a/resources/qml/Governikus/Workflow/+mobile/RemoteWorkflow.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/RemoteWorkflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQuick.Layouts @@ -7,17 +7,12 @@ import Governikus.Global import Governikus.Style import Governikus.RemoteServiceView import Governikus.TechnologyInfo -import Governikus.Type.ApplicationModel -import Governikus.Type.AuthModel -import Governikus.Type.RemoteServiceModel -import Governikus.Type.ReaderPlugIn -import Governikus.Type.NumberModel +import Governikus.Type GFlickableColumnLayout { id: baseItem property bool foundSelectedReader: ApplicationModel.availableReader > 0 - property bool settingsPushed: remoteServiceSettings.visible property bool wifiEnabled: ApplicationModel.wifiEnabled signal deviceUnpaired(var pDeviceName) @@ -27,12 +22,6 @@ GFlickableColumnLayout { spacing: 0 topMargin: 0 - onFoundSelectedReaderChanged: { - if (baseItem.settingsPushed && foundSelectedReader) { - remoteServiceSettings.pop(); - } - } - Connections { function onFireCertificateRemoved(pDeviceName) { deviceUnpaired(pDeviceName); @@ -41,10 +30,8 @@ GFlickableColumnLayout { target: RemoteServiceModel } RemoteProgressIndicator { - id: progressIndicator - Accessible.ignored: true - Layout.alignment: Qt.AlignCenter + Layout.alignment: Qt.AlignHCenter foundSelectedReader: baseItem.foundSelectedReader } TechnologyInfo { @@ -104,20 +91,22 @@ GFlickableColumnLayout { additionalContent: LocalNetworkInfo { visible: RemoteServiceModel.requiresLocalNetworkPermission && baseItem.wifiEnabled && !baseItem.foundSelectedReader - width: parent.width } onEnableClicked: { if (!wifiEnabled) { ApplicationModel.enableWifi(); - } else if (!baseItem.settingsPushed) { + } else if (!foundSelectedReader) { push(remoteServiceSettings); } } + onReceivedFocus: pItem => baseItem.positionViewAtItem(pItem) } - RemoteServiceSettings { + Component { id: remoteServiceSettings - visible: false + RemoteServiceSettings { + onPairingSuccessful: pop() + } } } diff --git a/resources/qml/Governikus/Workflow/+mobile/SmartProgressIndicator.qml b/src/ui/qml/modules/Workflow/+mobile/internal/SmartProgressIndicator.qml similarity index 88% rename from resources/qml/Governikus/Workflow/+mobile/SmartProgressIndicator.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/SmartProgressIndicator.qml index b488dba7d..c3918982d 100644 --- a/resources/qml/Governikus/Workflow/+mobile/SmartProgressIndicator.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/SmartProgressIndicator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import Governikus.Global diff --git a/resources/qml/Governikus/Workflow/+mobile/TextCircle.qml b/src/ui/qml/modules/Workflow/+mobile/internal/TextCircle.qml similarity index 88% rename from resources/qml/Governikus/Workflow/+mobile/TextCircle.qml rename to src/ui/qml/modules/Workflow/+mobile/internal/TextCircle.qml index 28e727751..5c85851b0 100644 --- a/resources/qml/Governikus/Workflow/+mobile/TextCircle.qml +++ b/src/ui/qml/modules/Workflow/+mobile/internal/TextCircle.qml @@ -1,8 +1,7 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick -import QtQuick.Controls import Governikus.Global import Governikus.Style @@ -78,7 +77,7 @@ Item { anchors.centerIn: parent border.color: Constants.blue border.width: 1 - color: parent.state === "active" ? Style.color.control : Constants.white + color: parent.state === "active" ? Style.color.control.background.basic : Constants.white height: parent.state === "active" ? parent.height : parent.height / 2 radius: width * 0.5 width: height @@ -87,7 +86,7 @@ Item { id: t anchors.centerIn: rec - color: parent.state === "active" ? Constants.white : Style.color.control + color: parent.state === "active" ? Constants.white : Style.color.control.background.basic font.bold: parent.state === "active" } } diff --git a/src/ui/qml/modules/Workflow/+mobile/internal/WorkflowInfoList.qml b/src/ui/qml/modules/Workflow/+mobile/internal/WorkflowInfoList.qml new file mode 100644 index 000000000..01c27c98b --- /dev/null +++ b/src/ui/qml/modules/Workflow/+mobile/internal/WorkflowInfoList.qml @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import Governikus.Workflow +import Governikus.Type + +Item { + id: baseItem + + property alias autoInsertCard: smartWorkflow.autoInsertCard + readonly property bool contentIsScrolled: nfcWorkflow.visible && !nfcWorkflow.atYBeginning || smartWorkflow.visible && !smartWorkflow.atYBeginning || remoteWorkflow.visible && !remoteWorkflow.atYBeginning || simulatorWorkflow.visible && !simulatorWorkflow.atYBeginning + required property var workflowModel + + signal remoteDeviceUnpaired(var pDeviceName) + + NfcWorkflow { + id: nfcWorkflow + + anchors.fill: parent + visible: baseItem.workflowModel.readerPluginType === ReaderManagerPluginType.NFC + + onStartScanIfNecessary: baseItem.workflowModel.startScanExplicitly() + } + SmartWorkflow { + id: smartWorkflow + + anchors.fill: parent + visible: baseItem.workflowModel.readerPluginType === ReaderManagerPluginType.SMART + workflowModel: baseItem.workflowModel + } + RemoteWorkflow { + id: remoteWorkflow + + anchors.fill: parent + visible: baseItem.workflowModel.readerPluginType === ReaderManagerPluginType.REMOTE_IFD || baseItem.workflowModel.readerPluginType === ReaderManagerPluginType.PCSC + + onDeviceUnpaired: pDeviceName => baseItem.remoteDeviceUnpaired(pDeviceName) + } + SimulatorWorkflow { + id: simulatorWorkflow + + anchors.fill: parent + visible: baseItem.workflowModel.readerPluginType === ReaderManagerPluginType.SIMULATOR + workflowModel: baseItem.workflowModel + } +} diff --git a/resources/qml/Governikus/Workflow/Workflow.qml b/src/ui/qml/modules/Workflow/Workflow.qml similarity index 59% rename from resources/qml/Governikus/Workflow/Workflow.qml rename to src/ui/qml/modules/Workflow/Workflow.qml index b5eb2f770..50a69836f 100644 --- a/resources/qml/Governikus/Workflow/Workflow.qml +++ b/src/ui/qml/modules/Workflow/Workflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick diff --git a/src/ui/scheme/UIPlugInScheme.cpp b/src/ui/scheme/UiPluginScheme.cpp similarity index 51% rename from src/ui/scheme/UIPlugInScheme.cpp rename to src/ui/scheme/UiPluginScheme.cpp index 58d0ce19e..9a75a3d55 100644 --- a/src/ui/scheme/UIPlugInScheme.cpp +++ b/src/ui/scheme/UiPluginScheme.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInScheme.h" +#include "UiPluginScheme.h" #include "UrlUtil.h" #include "controller/AuthController.h" @@ -14,13 +14,15 @@ #include #endif + using namespace governikus; + Q_DECLARE_LOGGING_CATEGORY(scheme) -UIPlugInScheme::UIPlugInScheme() - : UIPlugIn() +UiPluginScheme::UiPluginScheme() + : UiPlugin() { QDesktopServices::setUrlHandler(QStringLiteral("eid"), this, "onCustomUrl"); QDesktopServices::setUrlHandler(QStringLiteral("http"), this, "onCustomUrl"); @@ -28,7 +30,7 @@ UIPlugInScheme::UIPlugInScheme() } -UIPlugInScheme::~UIPlugInScheme() +UiPluginScheme::~UiPluginScheme() { QDesktopServices::unsetUrlHandler(QStringLiteral("eid")); QDesktopServices::unsetUrlHandler(QStringLiteral("http")); @@ -36,9 +38,9 @@ UIPlugInScheme::~UIPlugInScheme() } -void UIPlugInScheme::onCustomUrl(const QUrl& pUrl) +void UiPluginScheme::onCustomUrl(const QUrl& pUrl) { - QString referrer; + Referrer referrer; #ifdef Q_OS_ANDROID referrer = QJniObject::callStaticObjectMethod("com/governikus/ausweisapp2/MainActivity", "fetchStoredReferrer").toString(); qCDebug(scheme) << "Got new request by:" << referrer; @@ -79,7 +81,7 @@ void UIPlugInScheme::onCustomUrl(const QUrl& pUrl) case UrlQueryRequest::TCTOKENURL: { qCDebug(scheme) << "Request type: authentication"; - handleTcTokenUrl(pUrl, referrer); + Q_EMIT fireWorkflowRequested(AuthController::createWorkflowRequest(pUrl, QVariant::fromValue(referrer))); return; } @@ -89,81 +91,77 @@ void UIPlugInScheme::onCustomUrl(const QUrl& pUrl) } -void UIPlugInScheme::handleTcTokenUrl(const QUrl& pActivationUrl, const QString& pReferrer) +void UiPluginScheme::sendRedirect(const Referrer& pReferrer, const QUrl& pRedirectAddress) const { - const RedirectHandler handler = [pReferrer](const QUrl& pRefreshUrl, const GlobalStatus& pStatus){ - const auto& redirectAddress = UrlUtil::addMajorMinor(pRefreshUrl, pStatus); - qCDebug(scheme) << "Determined redirect URL" << redirectAddress; + if (!pRedirectAddress.isValid()) + { + qCDebug(scheme) << "Invalid redirect URL:" << pRedirectAddress; + return; + } - if (!redirectAddress.isEmpty()) - { - qCDebug(scheme) << "Perform redirect to URL" << redirectAddress; + qCDebug(scheme) << "Perform redirect to URL" << pRedirectAddress; #ifdef Q_OS_ANDROID - QJniObject context = QNativeInterface::QAndroidApplication::context(); - if (context.callMethod("openUrl", "(Ljava/lang/String;Ljava/lang/String;)Z", QJniObject::fromString(redirectAddress.url()).object(), QJniObject::fromString(pReferrer).object())) - { - return; - } + QJniObject context = QNativeInterface::QAndroidApplication::context(); + if (context.callMethod("openUrl", "(Ljava/lang/String;Ljava/lang/String;)Z", QJniObject::fromString(pRedirectAddress.url()).object(), QJniObject::fromString(pReferrer).object())) + { + return; + } #else - Q_UNUSED(pReferrer) + Q_UNUSED(pReferrer) #endif - QDesktopServices::openUrl(redirectAddress); - } - }; - - Q_EMIT fireWorkflowRequested(AuthController::createWorkflowRequest(pActivationUrl, QVariant::fromValue(handler))); + QDesktopServices::openUrl(pRedirectAddress); } -void UIPlugInScheme::doShutdown() +void UiPluginScheme::doShutdown() { } -void UIPlugInScheme::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginScheme::onWorkflowStarted(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) } -void UIPlugInScheme::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginScheme::onWorkflowFinished(const QSharedPointer& pRequest) { - if (const auto& handler = pRequest->getData().value(); handler) + if (pRequest->getData().metaType() != QMetaType::fromType()) + { + return; + } + + if (const auto& context = pRequest->getContext().objectCast(); context) { - if (const auto& context = pRequest->getContext().objectCast(); context) - { #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - // Only skip redirects on mobile platforms because it induces a forced focus change - if (context->isSkipMobileRedirect()) - { - qDebug() << "Skipping redirect, Workflow pending"; - return; - } + // Only skip redirects on mobile platforms because it induces a forced focus change + if (context->isSkipMobileRedirect()) + { + qCDebug(scheme) << "Skipping redirect, Workflow pending"; + return; + } #endif - const auto& url = context->getRefreshUrl(); - if (!url.isEmpty()) - { - const auto& status = context->getStatus(); - - /* - * Opening an URL on iOS will bring Safari to the foreground, our app - * will go to the background, causing the authentication controller to stop. - * - * Therefore we open the URL after workflow finished. - */ - QMetaObject::invokeMethod(QCoreApplication::instance(), [handler, url, status] { - handler(url, status); - }, Qt::QueuedConnection); - } + if (const auto& url = context->getRefreshUrl(); url.isValid()) + { + /* + * Opening an URL on iOS will bring Safari to the foreground, our app + * will go to the background, causing the authentication controller to stop. + * + * Therefore we open the URL after workflow finished. + */ + const auto& referrer = pRequest->getData().value(); + QMetaObject::invokeMethod(this, [this, referrer, url] { + sendRedirect(referrer, url); + }, Qt::QueuedConnection); } } } -void UIPlugInScheme::onWorkflowUnhandled(const QSharedPointer& pRequest) +void UiPluginScheme::onWorkflowUnhandled(const QSharedPointer& pRequest) { - if (pRequest->getData().value()) // workflow is started by this plugin + if (pRequest->getData().metaType() == QMetaType::fromType()) // workflow is started by this plugin { Q_EMIT fireShowUserInformationRequested(GlobalStatus(GlobalStatus::Code::Workflow_AlreadyInProgress_Error).toErrorDescription()); } diff --git a/src/ui/scheme/UIPlugInScheme.h b/src/ui/scheme/UiPluginScheme.h similarity index 51% rename from src/ui/scheme/UIPlugInScheme.h rename to src/ui/scheme/UiPluginScheme.h index f29186296..2dfeee2e4 100644 --- a/src/ui/scheme/UIPlugInScheme.h +++ b/src/ui/scheme/UiPluginScheme.h @@ -1,13 +1,17 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "GlobalStatus.h" -#include "UIPlugIn.h" +#include "UiPlugin.h" + +#include +#include + + +class test_UiPluginScheme; -class test_UIPlugInScheme; namespace governikus { @@ -17,19 +21,29 @@ namespace governikus * as specified by TR-03124-1. * Custom schemes can be registered for iOS apps. */ -class UIPlugInScheme - : public UIPlugIn +class UiPluginScheme + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) - - friend class ::test_UIPlugInScheme; + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) - using RedirectHandler = std::function; + friend class ::test_UiPluginScheme; private: - void handleTcTokenUrl(const QUrl& pActivationUrl, const QString& pReferrer); + class Referrer + : public QString + { + public: + void operator=(const QString& pOther) + { + QString::operator=(pOther); + } + + + }; + + void sendRedirect(const Referrer& pReferrer, const QUrl& pRedirectAddress) const; private Q_SLOTS: void onCustomUrl(const QUrl& pUrl); @@ -39,8 +53,8 @@ class UIPlugInScheme void onWorkflowUnhandled(const QSharedPointer& pRequest) override; public: - UIPlugInScheme(); - ~UIPlugInScheme() override; + UiPluginScheme(); + ~UiPluginScheme() override; }; } // namespace governikus diff --git a/src/ui/webservice/UIPlugInWebService.cpp b/src/ui/webservice/UiPluginWebService.cpp similarity index 81% rename from src/ui/webservice/UIPlugInWebService.cpp rename to src/ui/webservice/UiPluginWebService.cpp index 43964f19e..22c4256b4 100644 --- a/src/ui/webservice/UIPlugInWebService.cpp +++ b/src/ui/webservice/UiPluginWebService.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInWebService.h" +#include "UiPluginWebService.h" #include "Env.h" #include "HttpServerStatusParser.h" @@ -26,27 +26,27 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(webservice) -UIPlugInWebService::UIPlugInWebService() - : UIPlugIn() +UiPluginWebService::UiPluginWebService() + : UiPlugin() , HttpHandler() , mServer() { } -bool UIPlugInWebService::initialize() +bool UiPluginWebService::initialize() { return (mServer && mServer->isListening()) || listening(); } -bool UIPlugInWebService::listening() +bool UiPluginWebService::listening() { mServer = Env::getShared(); if (mServer->isListening()) { - connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UIPlugInWebService::onNewRequest); + connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UiPluginWebService::onNewRequest); return true; } @@ -55,7 +55,7 @@ bool UIPlugInWebService::listening() for (const auto& address : std::as_const(HttpServer::cAddresses)) { HttpServerStatusParser parser(port, address); - const QString serverAppName = parser.request() ? parser.getVersionInfo().getImplementationTitle() : parser.getServerHeader(); + const QString serverAppName = (parser.request() ? parser.getVersionInfo().getImplementationTitle() : parser.getServerHeader()).toHtmlEscaped(); if (serverAppName.startsWith(VersionInfo::getInstance().getImplementationTitle())) { switch (handleExistingApp(port, address)) @@ -102,7 +102,7 @@ bool UIPlugInWebService::listening() } -UIPlugInWebService::ExistingAppResult UIPlugInWebService::handleExistingApp(quint16 pPort, const QHostAddress& pHost) const +UiPluginWebService::ExistingAppResult UiPluginWebService::handleExistingApp(quint16 pPort, const QHostAddress& pHost) const { qCDebug(webservice) << "We are already started... calling ShowUI"; HttpServerRequestor requestor; @@ -119,7 +119,7 @@ UIPlugInWebService::ExistingAppResult UIPlugInWebService::handleExistingApp(quin mServer->rebind(); if (mServer->isListening()) { - connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UIPlugInWebService::onNewRequest); + connect(mServer.data(), &HttpServer::fireNewHttpRequest, this, &UiPluginWebService::onNewRequest); return ExistingAppResult::REBIND_SUCCEED; } @@ -131,13 +131,13 @@ UIPlugInWebService::ExistingAppResult UIPlugInWebService::handleExistingApp(quin } -void UIPlugInWebService::onNewRequest(const QSharedPointer& pRequest) +void UiPluginWebService::onNewRequest(const QSharedPointer& pRequest) { handle(pRequest); } -void UIPlugInWebService::handleWorkflowRequest(const QSharedPointer& pRequest) +void UiPluginWebService::handleWorkflowRequest(const QSharedPointer& pRequest) { const AuthContext::BrowserHandler handler = [this, pRequest](const QSharedPointer& pContext){ return sendRedirect(pRequest, pContext); @@ -146,11 +146,11 @@ void UIPlugInWebService::handleWorkflowRequest(const QSharedPointer } -void UIPlugInWebService::handleShowUiRequest(const QString& pUiModule, const QSharedPointer& pRequest) +void UiPluginWebService::handleShowUiRequest(const QString& pUiModule, const QSharedPointer& pRequest) { pRequest->send(HTTP_STATUS_OK); - QString userAgent = QString::fromLatin1(pRequest->getHeader(QByteArrayLiteral("user-agent"))); + QString userAgent = QString::fromLatin1(pRequest->getHeader(QByteArrayLiteral("user-agent"))).toHtmlEscaped(); if (userAgent.startsWith(VersionInfo::getInstance().getImplementationTitle())) { QString version = userAgent.remove(VersionInfo::getInstance().getImplementationTitle() + QLatin1Char('/')).split(QLatin1Char(' ')).at(0); @@ -176,7 +176,7 @@ void UIPlugInWebService::handleShowUiRequest(const QString& pUiModule, const QSh } -void UIPlugInWebService::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginWebService::onWorkflowStarted(const QSharedPointer& pRequest) { if (pRequest->getContext().objectCast()) { @@ -196,13 +196,13 @@ void UIPlugInWebService::onWorkflowStarted(const QSharedPointer } -void UIPlugInWebService::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginWebService::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) } -void UIPlugInWebService::onWorkflowUnhandled(const QSharedPointer& pRequest) +void UiPluginWebService::onWorkflowUnhandled(const QSharedPointer& pRequest) { const auto& request = pRequest->getData().value>(); if (request) @@ -212,7 +212,7 @@ void UIPlugInWebService::onWorkflowUnhandled(const QSharedPointer& pRequest) const +void UiPluginWebService::sendWorkflowAlreadyActive(const QSharedPointer& pRequest) const { if (!pRequest || !pRequest->isConnected()) { @@ -252,7 +252,7 @@ void UIPlugInWebService::sendWorkflowAlreadyActive(const QSharedPointer& pRequest, http_status pStatusCode, const GlobalStatus& pStatus) const +QString UiPluginWebService::sendErrorPage(const QSharedPointer& pRequest, http_status pStatusCode, const GlobalStatus& pStatus) const { if (!pRequest->isConnected()) { @@ -288,51 +288,47 @@ QString UIPlugInWebService::sendErrorPage(const QSharedPointer& pRe } -QString UIPlugInWebService::sendRedirect(const QSharedPointer& pRequest, const QSharedPointer& pContext) const +QString UiPluginWebService::sendRedirect(const QSharedPointer& pRequest, const QSharedPointer& pContext) const { if (pContext->getStatus() == GlobalStatus::Code::Workflow_InternalError_BeforeTcToken) { return sendErrorPage(pRequest, HTTP_STATUS_INTERNAL_SERVER_ERROR, pContext->getStatus()); } - else if (pContext->isTcTokenNotFound()) + + if (pContext->isTcTokenNotFound()) { return sendErrorPage(pRequest, HTTP_STATUS_NOT_FOUND, pContext->getStatus()); } - else if (pContext->getRefreshUrl().isEmpty()) + + const auto& url = pContext->getRefreshUrl(); + if (!url.isValid()) { - if (pContext->getTcToken() != nullptr && pContext->getTcToken()->getCommunicationErrorAddress().isValid()) - { - return sendRedirect(pRequest, pContext->getTcToken()->getCommunicationErrorAddress(), ECardApiResult(GlobalStatus::Code::Workflow_Communication_Missing_Redirect_Url)); - } + qCDebug(webservice) << "Invalid redirect URL:" << url; return sendErrorPage(pRequest, HTTP_STATUS_BAD_REQUEST, pContext->getStatus()); } - const auto& result = pContext->getStartPaosResult().isOk() ? ECardApiResult(pContext->getStatus()) : pContext->getStartPaosResult(); - return sendRedirect(pRequest, pContext->getRefreshUrl(), result); + return sendRedirect(pRequest, url); } -QString UIPlugInWebService::sendRedirect(const QSharedPointer& pRequest, const QUrl& pRedirectAddress, const ECardApiResult& pResult) const +QString UiPluginWebService::sendRedirect(const QSharedPointer& pRequest, const QUrl& pRedirectAddress) const { - QUrl redirectAddressWithResult = UrlUtil::addMajorMinor(pRedirectAddress, GlobalStatus(pResult)); - qCDebug(webservice) << "Redirect URL:" << redirectAddressWithResult; - + qCDebug(webservice) << "Perform redirect to URL:" << pRedirectAddress; if (!pRequest->isConnected()) { - const auto& url = QStringLiteral("%2").arg(redirectAddressWithResult.toString(), redirectAddressWithResult.host()); //: ERROR ALL_PLATFORMS The connection to the browser was lost/timed out.. - return tr("The connection to the browser was lost. No forwarding was executed. Please try to call the URL again manually: %1").arg(url); + return tr("The connection to the browser was lost while redirecting to the provider (%1). No automatic redirection could be performed.").arg(pRedirectAddress.host()); } HttpResponse response(HTTP_STATUS_SEE_OTHER); setCommonHeaders(response); - response.setHeader(QByteArrayLiteral("Location"), redirectAddressWithResult.toEncoded()); + response.setHeader(QByteArrayLiteral("Location"), pRedirectAddress.toEncoded()); pRequest->send(response); return QString(); } -void UIPlugInWebService::setCommonHeaders(HttpResponse& pResponse) const +void UiPluginWebService::setCommonHeaders(HttpResponse& pResponse) const { pResponse.setHeader(QByteArrayLiteral("Connection"), QByteArrayLiteral("close")); pResponse.setHeader(QByteArrayLiteral("Cache-Control"), QByteArrayLiteral("no-cache, no-store")); diff --git a/src/ui/webservice/UIPlugInWebService.h b/src/ui/webservice/UiPluginWebService.h similarity index 73% rename from src/ui/webservice/UIPlugInWebService.h rename to src/ui/webservice/UiPluginWebService.h index 2365fca59..47ecb93e2 100644 --- a/src/ui/webservice/UIPlugInWebService.h +++ b/src/ui/webservice/UiPluginWebService.h @@ -1,9 +1,9 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the UIPlugInWebService. + * \brief UiPlugin implementation of the UiPluginWebService. */ #pragma once @@ -11,12 +11,12 @@ #include "HttpHandler.h" #include "HttpRequest.h" #include "HttpServer.h" -#include "UIPlugIn.h" +#include "UiPlugin.h" #include "context/AuthContext.h" -class test_UIPlugInWebService; -class test_UIPlugInWebServiceBrowserHandler; +class test_UiPluginWebService; +class test_UiPluginWebServiceBrowserHandler; namespace governikus { @@ -24,15 +24,15 @@ namespace governikus /*! * This an API through a local web service as specified by TR-03124-1. */ -class UIPlugInWebService - : public UIPlugIn +class UiPluginWebService + : public UiPlugin , private HttpHandler { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) - friend class ::test_UIPlugInWebService; - friend class ::test_UIPlugInWebServiceBrowserHandler; + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) + friend class ::test_UiPluginWebService; + friend class ::test_UiPluginWebServiceBrowserHandler; private: enum class ExistingAppResult : int @@ -51,7 +51,7 @@ class UIPlugInWebService void setCommonHeaders(HttpResponse& pResponse) const; QString sendErrorPage(const QSharedPointer& pRequest, http_status pStatusCode, const GlobalStatus& pStatus) const; - QString sendRedirect(const QSharedPointer& pRequest, const QUrl& pRedirectAddress, const ECardApiResult& pResult) const; + QString sendRedirect(const QSharedPointer& pRequest, const QUrl& pRedirectAddress) const; QString sendRedirect(const QSharedPointer& pRequest, const QSharedPointer& pContext) const; void sendWorkflowAlreadyActive(const QSharedPointer& pRequest) const; @@ -66,8 +66,8 @@ class UIPlugInWebService void onNewRequest(const QSharedPointer& pRequest); public: - UIPlugInWebService(); - ~UIPlugInWebService() override = default; + UiPluginWebService(); + ~UiPluginWebService() override = default; }; } // namespace governikus diff --git a/src/ui/websocket/UIPlugInWebSocket.cpp b/src/ui/websocket/UiPluginWebSocket.cpp similarity index 71% rename from src/ui/websocket/UIPlugInWebSocket.cpp rename to src/ui/websocket/UiPluginWebSocket.cpp index 2c79338f7..3e4fb7cda 100644 --- a/src/ui/websocket/UIPlugInWebSocket.cpp +++ b/src/ui/websocket/UiPluginWebSocket.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInWebSocket.h" +#include "UiPluginWebSocket.h" #include "Env.h" #include "ReaderManager.h" -#include "UILoader.h" +#include "UiLoader.h" #include "VolatileSettings.h" #include "WorkflowRequest.h" @@ -24,8 +24,8 @@ Q_DECLARE_LOGGING_CATEGORY(websocket) using namespace governikus; -UIPlugInWebSocket::UIPlugInWebSocket() - : UIPlugIn() +UiPluginWebSocket::UiPluginWebSocket() + : UiPlugin() , mServer(QCoreApplication::applicationName() + QLatin1Char('/') + QCoreApplication::applicationVersion(), QWebSocketServer::NonSecureMode) , mConnection(nullptr) , mRequest() @@ -37,20 +37,20 @@ UIPlugInWebSocket::UIPlugInWebSocket() } -bool UIPlugInWebSocket::initialize() +bool UiPluginWebSocket::initialize() { if (mHttpServer) { return true; } - if (!Env::getSingleton()->load()) + if (!Env::getSingleton()->load()) { qCWarning(websocket) << "Cannot start WebSocket because JSON-API is missing"; return false; } - mJson = Env::getSingleton()->getLoaded(); + mJson = Env::getSingleton()->getLoaded(); mHttpServer = Env::getShared(); if (!mHttpServer->isListening()) { @@ -59,32 +59,32 @@ bool UIPlugInWebSocket::initialize() } qCDebug(websocket) << "Enable WebSocket..."; - connect(mHttpServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UIPlugInWebSocket::onNewWebSocketRequest); + connect(mHttpServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UiPluginWebSocket::onNewWebSocketRequest); connect(mHttpServer.data(), &HttpServer::fireRebound, this, [this]{ if (!mHttpServer->isListening()) { qCDebug(websocket) << "Disable WebSocket..."; - disconnect(mHttpServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UIPlugInWebSocket::onNewWebSocketRequest); + disconnect(mHttpServer.data(), &HttpServer::fireNewWebSocketRequest, this, &UiPluginWebSocket::onNewWebSocketRequest); mHttpServer.clear(); } }); - connect(&mServer, &QWebSocketServer::newConnection, this, &UIPlugInWebSocket::onNewConnection); + connect(&mServer, &QWebSocketServer::newConnection, this, &UiPluginWebSocket::onNewConnection); return true; } -void UIPlugInWebSocket::onWorkflowStarted(const QSharedPointer& pRequest) +void UiPluginWebSocket::onWorkflowStarted(const QSharedPointer& pRequest) { if (mUiDomination) { mContext = pRequest->getContext(); mContext->claim(this); - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::PCSC, ReaderManagerPlugInType::REMOTE_IFD, ReaderManagerPlugInType::SIMULATOR}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::PCSC, ReaderManagerPluginType::REMOTE_IFD, ReaderManagerPluginType::SIMULATOR}); } } -void UIPlugInWebSocket::onWorkflowFinished(const QSharedPointer& pRequest) +void UiPluginWebSocket::onWorkflowFinished(const QSharedPointer& pRequest) { Q_UNUSED(pRequest) @@ -92,7 +92,7 @@ void UIPlugInWebSocket::onWorkflowFinished(const QSharedPointer } -void UIPlugInWebSocket::onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) +void UiPluginWebSocket::onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) { Q_UNUSED(pInformation) @@ -118,7 +118,7 @@ void UIPlugInWebSocket::onUiDomination(const UIPlugIn* pUi, const QString& pInfo } -void UIPlugInWebSocket::onUiDominationReleased() +void UiPluginWebSocket::onUiDominationReleased() { if (mUiDomination) { @@ -130,7 +130,7 @@ void UIPlugInWebSocket::onUiDominationReleased() } -void UIPlugInWebSocket::onNewWebSocketRequest(const QSharedPointer& pRequest) +void UiPluginWebSocket::onNewWebSocketRequest(const QSharedPointer& pRequest) { const auto& url = pRequest->getUrl(); @@ -150,18 +150,18 @@ void UIPlugInWebSocket::onNewWebSocketRequest(const QSharedPointer& } mRequest = pRequest; - Q_EMIT fireUiDominationRequest(this, QString::fromLatin1(pRequest->getHeader().value(QByteArrayLiteral("user-agent")))); + Q_EMIT fireUiDominationRequest(this, QString::fromLatin1(pRequest->getHeader().value(QByteArrayLiteral("user-agent"))).toHtmlEscaped()); } -void UIPlugInWebSocket::onNewConnection() +void UiPluginWebSocket::onNewConnection() { if (mServer.hasPendingConnections()) { mConnection.reset(mServer.nextPendingConnection()); - connect(mJson, &UIPlugInJson::fireMessage, this, &UIPlugInWebSocket::onJsonMessage); - connect(mConnection.data(), &QWebSocket::textMessageReceived, this, &UIPlugInWebSocket::onTextMessageReceived); - connect(mConnection.data(), &QWebSocket::disconnected, this, &UIPlugInWebSocket::onClientDisconnected); + connect(mJson, &UiPluginJson::fireMessage, this, &UiPluginWebSocket::onJsonMessage); + connect(mConnection.data(), &QWebSocket::textMessageReceived, this, &UiPluginWebSocket::onTextMessageReceived); + connect(mConnection.data(), &QWebSocket::disconnected, this, &UiPluginWebSocket::onClientDisconnected); mJson->setEnabled(); } else @@ -173,7 +173,7 @@ void UIPlugInWebSocket::onNewConnection() } -void UIPlugInWebSocket::onClientDisconnected() +void UiPluginWebSocket::onClientDisconnected() { qCDebug(websocket) << "Client disconnected..."; @@ -185,12 +185,12 @@ void UIPlugInWebSocket::onClientDisconnected() mConnection.reset(); mRequest.reset(); - disconnect(mJson, &UIPlugInJson::fireMessage, this, &UIPlugInWebSocket::onJsonMessage); + disconnect(mJson, &UiPluginJson::fireMessage, this, &UiPluginWebSocket::onJsonMessage); Q_EMIT fireUiDominationRelease(); } -void UIPlugInWebSocket::onTextMessageReceived(const QString& pMessage) +void UiPluginWebSocket::onTextMessageReceived(const QString& pMessage) { if (mConnection) { @@ -199,7 +199,7 @@ void UIPlugInWebSocket::onTextMessageReceived(const QString& pMessage) } -void UIPlugInWebSocket::onJsonMessage(const QByteArray& pMessage) +void UiPluginWebSocket::onJsonMessage(const QByteArray& pMessage) { if (mConnection) { @@ -208,7 +208,7 @@ void UIPlugInWebSocket::onJsonMessage(const QByteArray& pMessage) } -void UIPlugInWebSocket::doShutdown() +void UiPluginWebSocket::doShutdown() { if (mConnection) { diff --git a/src/ui/websocket/UIPlugInWebSocket.h b/src/ui/websocket/UiPluginWebSocket.h similarity index 70% rename from src/ui/websocket/UIPlugInWebSocket.h rename to src/ui/websocket/UiPluginWebSocket.h index d642e3f99..11f14d09a 100644 --- a/src/ui/websocket/UIPlugInWebSocket.h +++ b/src/ui/websocket/UiPluginWebSocket.h @@ -1,17 +1,17 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief UIPlugIn implementation of the Websocket. + * \brief UiPlugin implementation of the Websocket. */ #pragma once #include "HttpRequest.h" #include "HttpServer.h" -#include "UIPlugIn.h" -#include "UIPlugInJson.h" +#include "UiPlugin.h" +#include "UiPluginJson.h" #include #include @@ -22,19 +22,19 @@ namespace governikus { -class UIPlugInWebSocket - : public UIPlugIn +class UiPluginWebSocket + : public UiPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.UIPlugIn" FILE "metadata.json") - Q_INTERFACES(governikus::UIPlugIn) + Q_PLUGIN_METADATA(IID "governikus.UiPlugin" FILE "metadata.json") + Q_INTERFACES(governikus::UiPlugin) private: QSharedPointer mHttpServer; QWebSocketServer mServer; QScopedPointer mConnection; QSharedPointer mRequest; - QPointer mJson; + QPointer mJson; QSharedPointer mContext; bool mUiDomination; bool mUiDominationPrevUsedAsSDK; @@ -43,7 +43,7 @@ class UIPlugInWebSocket void doShutdown() override; void onWorkflowStarted(const QSharedPointer& pRequest) override; void onWorkflowFinished(const QSharedPointer& pRequest) override; - void onUiDomination(const UIPlugIn* pUi, const QString& pInformation, bool pAccepted) override; + void onUiDomination(const UiPlugin* pUi, const QString& pInformation, bool pAccepted) override; void onUiDominationReleased() override; void onNewWebSocketRequest(const QSharedPointer& pRequest); void onNewConnection(); @@ -52,8 +52,8 @@ class UIPlugInWebSocket void onJsonMessage(const QByteArray& pMessage); public: - UIPlugInWebSocket(); - ~UIPlugInWebSocket() override = default; + UiPluginWebSocket(); + ~UiPluginWebSocket() override = default; [[nodiscard]] bool initialize() override; }; diff --git a/src/whitelist_client/CMakeLists.txt b/src/whitelist_client/CMakeLists.txt deleted file mode 100644 index 71063008f..000000000 --- a/src/whitelist_client/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -######################################################################## -# The module whitelist client is responsible for collecting information -# about the NFC interface on an Android device and sending them to the -# whitelist server. -####################################################################### - -ADD_PLATFORM_LIBRARY(AusweisAppWhitelistClient) - -target_link_libraries(AusweisAppWhitelistClient ${Qt}::Core AusweisAppSettings AusweisAppNetwork AusweisAppCard) diff --git a/src/workflows/base/CMakeLists.txt b/src/workflows/base/CMakeLists.txt index 0dab0529a..d7fbb837a 100644 --- a/src/workflows/base/CMakeLists.txt +++ b/src/workflows/base/CMakeLists.txt @@ -1,6 +1,6 @@ ADD_PLATFORM_LIBRARY(AusweisAppWorkflows) -target_link_libraries(AusweisAppWorkflows ${Qt}::Network AusweisAppCard AusweisAppGlobal AusweisAppSettings AusweisAppNetwork AusweisAppWhitelistClient) +target_link_libraries(AusweisAppWorkflows ${Qt}::Network AusweisAppCard AusweisAppGlobal AusweisAppSettings AusweisAppNetwork) if(TARGET ${Qt}::StateMachine) target_link_libraries(AusweisAppWorkflows ${Qt}::StateMachine) diff --git a/src/workflows/base/CertificateChecker.cpp b/src/workflows/base/CertificateChecker.cpp index 249a1baaa..6e6076f30 100644 --- a/src/workflows/base/CertificateChecker.cpp +++ b/src/workflows/base/CertificateChecker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CertificateChecker.h" diff --git a/src/workflows/base/CertificateChecker.h b/src/workflows/base/CertificateChecker.h index a7b210bd4..6aa3423c6 100644 --- a/src/workflows/base/CertificateChecker.h +++ b/src/workflows/base/CertificateChecker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/whitelist_client/SurveyModel.cpp b/src/workflows/base/Survey.cpp similarity index 77% rename from src/whitelist_client/SurveyModel.cpp rename to src/workflows/base/Survey.cpp index 7e7998e90..bad9338b6 100644 --- a/src/whitelist_client/SurveyModel.cpp +++ b/src/workflows/base/Survey.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ -#include "SurveyModel.h" +#include "Survey.h" #include "AppSettings.h" #include "DeviceInfo.h" @@ -45,8 +45,8 @@ VALUE_NAME(NFC_TAG_TYPE, "NfcTagType") } // namespace -SurveyModel::SurveyModel() - : QAbstractListModel() +Survey::Survey() + : QObject() , mBuildNumber(DeviceInfo::getOSBuildNumber()) , mOsVersion(DeviceInfo::getOSVersion()) , mKernelVersion(DeviceInfo::getKernelVersion()) @@ -63,42 +63,8 @@ SurveyModel::SurveyModel() } -int SurveyModel::rowCount(const QModelIndex&) const +void Survey::buildDataObject() { - return static_cast(mData.size()); -} - - -QVariant SurveyModel::data(const QModelIndex& pIndex, int pRole) const -{ - if (pIndex.isValid() && pIndex.row() < rowCount()) - { - auto entry = mData[pIndex.row()]; - if (pRole == TITLE) - { - return entry.first; - } - if (pRole == VALUE) - { - return entry.second; - } - } - return QVariant(); -} - - -QHash SurveyModel::roleNames() const -{ - QHash roles = QAbstractListModel::roleNames(); - roles.insert(TITLE, "title"); - roles.insert(VALUE, "value"); - return roles; -} - - -void SurveyModel::buildDataObject() -{ - beginResetModel(); mData.clear(); mData += qMakePair(tr("Vendor"), mVendor); mData += qMakePair(tr("Model Name"), mModelName); @@ -109,11 +75,11 @@ void SurveyModel::buildDataObject() mData += qMakePair(tr("Max. NFC Packet Length"), QString::number(mMaximumNfcPacketLength)); mData += qMakePair(tr("%1 Version").arg(QCoreApplication::applicationName()), mAusweisAppVersionNumber); mData += qMakePair(tr("NFC Tag Type"), mNfcTagType); - endResetModel(); + Q_EMIT fireSurveyDataChanged(); } -QByteArray SurveyModel::toJsonByteArray() const +QByteArray Survey::toJsonByteArray() const { QJsonObject rom; rom[BUILD_NUMBER()] = mBuildNumber; @@ -140,7 +106,7 @@ QByteArray SurveyModel::toJsonByteArray() const } -void SurveyModel::resetNfcData() +void Survey::resetNfcData() { mNfcDataAvailable = false; mNfcTagType = QStringLiteral("U"); @@ -149,14 +115,14 @@ void SurveyModel::resetNfcData() } -void SurveyModel::setReaderInfo(const ReaderInfo& pReaderInfo) +void Survey::setReaderInfo(const ReaderInfo& pReaderInfo) { if (Env::getSingleton()->isUsedAsSDK()) { return; } - if (pReaderInfo.getPlugInType() != ReaderManagerPlugInType::NFC) + if (pReaderInfo.getPluginType() != ReaderManagerPluginType::NFC) { if (!mAuthWasSuccessful) { @@ -189,33 +155,33 @@ void SurveyModel::setReaderInfo(const ReaderInfo& pReaderInfo) } -void SurveyModel::setAuthWasSuccessful(bool pSuccess) +void Survey::setAuthWasSuccessful(bool pSuccess) { mAuthWasSuccessful = pSuccess && mNfcDataAvailable; } -bool SurveyModel::askForDeviceSurvey() const +bool Survey::askForDeviceSurvey() const { const auto& settings = Env::getSingleton()->getGeneralSettings(); return mNfcDataAvailable && mAuthWasSuccessful && settings.askForDeviceSurvey(); } -bool SurveyModel::isDeviceSurveyPending() const +bool Survey::isDeviceSurveyPending() const { const auto& settings = Env::getSingleton()->getGeneralSettings(); return mNfcDataAvailable && mAuthWasSuccessful && settings.isDeviceSurveyPending(); } -void SurveyModel::setDeviceSurveyPending(bool pValue) const +void Survey::setDeviceSurveyPending(bool pValue) const { Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(pValue); } -void SurveyModel::transmitSurvey() +void Survey::transmitSurvey() { const QUrl whitelistServerBaseUrl = Env::getSingleton()->getWhitelistServerBaseUrl(); @@ -226,13 +192,13 @@ void SurveyModel::transmitSurvey() const QByteArray jsonData = toJsonByteArray(); mReply = Env::getSingleton()->postAsUpdater(request, jsonData); - connect(mReply.data(), &QNetworkReply::finished, this, &SurveyModel::onNetworkReplyFinished); + connect(mReply.data(), &QNetworkReply::finished, this, &Survey::onNetworkReplyFinished); qDebug().noquote() << "Sent survey to whitelist server:" << jsonData; } -void SurveyModel::onNetworkReplyFinished() +void Survey::onNetworkReplyFinished() { if (mReply) { @@ -242,3 +208,9 @@ void SurveyModel::onNetworkReplyFinished() mReply.reset(); } } + + +Survey::SurveyData Survey::getSurveyData() const +{ + return mData; +} diff --git a/src/whitelist_client/SurveyModel.h b/src/workflows/base/Survey.h similarity index 61% rename from src/whitelist_client/SurveyModel.h rename to src/workflows/base/Survey.h index 8809b49b6..3567b0950 100644 --- a/src/whitelist_client/SurveyModel.h +++ b/src/workflows/base/Survey.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,25 +9,26 @@ #pragma once -#include #include -#include #include #include #include "ReaderInfo.h" -class test_SurveyModel; +class test_Survey; namespace governikus { -class SurveyModel - : public QAbstractListModel +class Survey + : public QObject { Q_OBJECT friend class Env; - friend class ::test_SurveyModel; + friend class ::test_Survey; + + public: + using SurveyData = QList>; private: const QString mBuildNumber; @@ -42,7 +43,7 @@ class SurveyModel bool mNfcDataAvailable; bool mAuthWasSuccessful; - QVector> mData; + SurveyData mData; QSharedPointer mReply; enum UserRoles @@ -51,8 +52,8 @@ class SurveyModel VALUE }; - SurveyModel(); - ~SurveyModel() override = default; + Survey(); + ~Survey() override = default; void buildDataObject(); [[nodiscard]] QByteArray toJsonByteArray() const; @@ -62,19 +63,19 @@ class SurveyModel void onNetworkReplyFinished(); public: - [[nodiscard]] int rowCount(const QModelIndex& = QModelIndex()) const override; - [[nodiscard]] QVariant data(const QModelIndex& pIndex, int pRole = Qt::DisplayRole) const override; - [[nodiscard]] QHash roleNames() const override; + [[nodiscard]] SurveyData getSurveyData() const; void setReaderInfo(const ReaderInfo& pReaderInfo); void setAuthWasSuccessful(bool pSuccess); - [[nodiscard]] Q_INVOKABLE bool askForDeviceSurvey() const; + [[nodiscard]] bool askForDeviceSurvey() const; [[nodiscard]] bool isDeviceSurveyPending() const; - Q_INVOKABLE void setDeviceSurveyPending(bool pValue) const; - + void setDeviceSurveyPending(bool pValue) const; void transmitSurvey(); + + Q_SIGNALS: + void fireSurveyDataChanged(); }; } // namespace governikus diff --git a/src/workflows/base/TcToken.cpp b/src/workflows/base/TcToken.cpp index f5c710a2c..65dca7b07 100644 --- a/src/workflows/base/TcToken.cpp +++ b/src/workflows/base/TcToken.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ @@ -7,6 +7,7 @@ #include "AppSettings.h" +#include #include #include #include @@ -14,9 +15,10 @@ using namespace governikus; Q_DECLARE_LOGGING_CATEGORY(developermode) +Q_DECLARE_LOGGING_CATEGORY(secure) -TcToken::TcToken(const QByteArray& pData) +TcToken::TcToken(const QSharedPointer& pStream) : mSchemaConform(false) , mBinding() , mPathSecurityProtocol() @@ -26,17 +28,22 @@ TcToken::TcToken(const QByteArray& pData) , mCommunicationErrorAddress() , mRefreshAddress() { - parse(pData); + if (pStream && (pStream->isOpen() || pStream->open(QIODeviceBase::ReadOnly))) + { + parse(pStream); + } } -TcToken::~TcToken() = default; +TcToken::TcToken(QByteArray pData) // clazy:exclude=function-args-by-ref + : TcToken(QSharedPointer::create(&pData)) +{ +} -void TcToken::parse(const QByteArray& pData) +void TcToken::parse(const QSharedPointer& pStream) { - qDebug().noquote() << "Parsing TcToken:\n" << pData; - QXmlStreamReader reader(pData); + QXmlStreamReader reader(pStream.data()); QString binding; QString pathSecurityProtocol; @@ -50,7 +57,7 @@ void TcToken::parse(const QByteArray& pData) { if (reader.isStartElement()) { - QString currentName = reader.name().toString(); + const QStringView currentName = reader.name(); if (currentName == QLatin1String("Binding")) { binding = readElementValue(reader); @@ -61,7 +68,7 @@ void TcToken::parse(const QByteArray& pData) } else if (currentName == QLatin1String("PSK")) { - psk = readElementValue(reader).toUtf8(); + psk = readElementValue(reader, false).toUtf8(); } else if (currentName == QLatin1String("ServerAddress")) { @@ -102,13 +109,16 @@ void TcToken::parse(const QByteArray& pData) } -QString TcToken::readElementValue(QXmlStreamReader& pReader) const +QString TcToken::readElementValue(QXmlStreamReader& pReader, bool pLogValue) const { // helper method to distinguish between the cases, // 1) where the element was present but empty (so the value is not null but empty) and // 2) where the element was absent (so the value is null). - QString value = pReader.readElementText(); - return value.isNull() ? QLatin1String("") : value.trimmed(); + const auto& value = pReader.readElementText().trimmed(); + qDebug() << pReader.name() + << '=' + << (pLogValue || secure().isDebugEnabled() ? value : QStringLiteral("(...)")); + return value.isNull() ? QLatin1String("") : value; } @@ -262,6 +272,12 @@ const QByteArray& TcToken::getPsk() const } +bool TcToken::isSchemaConform() const +{ + return mSchemaConform; +} + + const QString& TcToken::getBinding() const { return mBinding; diff --git a/src/workflows/base/TcToken.h b/src/workflows/base/TcToken.h index eb4b84e8f..47bf642df 100644 --- a/src/workflows/base/TcToken.h +++ b/src/workflows/base/TcToken.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -31,7 +32,7 @@ class TcToken QUrl mCommunicationErrorAddress; QUrl mRefreshAddress; - void parse(const QByteArray& pData); + void parse(const QSharedPointer& pStream); [[nodiscard]] bool valuesAreSchemaConform(const QString& pBinding, const QString& pPathSecurityProtocol, const QByteArray& pPsk, @@ -41,11 +42,11 @@ class TcToken const QString& pRefreshAddress) const; [[nodiscard]] bool isAnyUri(const QString& pCandidate) const; [[nodiscard]] bool isHexBinary(const QString& pCandidate) const; - QString readElementValue(QXmlStreamReader& pReader) const; + QString readElementValue(QXmlStreamReader& pReader, bool pLogValue = true) const; public: - explicit TcToken(const QByteArray& pData); - virtual ~TcToken(); + explicit TcToken(const QSharedPointer& pStream); + explicit TcToken(QByteArray pData); /** * Check if parsing of given data was successful. @@ -59,13 +60,7 @@ class TcToken [[nodiscard]] const QUrl& getCommunicationErrorAddress() const; [[nodiscard]] bool usePsk() const; [[nodiscard]] const QByteArray& getPsk() const; - - [[nodiscard]] bool isSchemaConform() const - { - return mSchemaConform; - } - - + [[nodiscard]] bool isSchemaConform() const; }; } // namespace governikus diff --git a/src/workflows/base/WorkflowRequest.cpp b/src/workflows/base/WorkflowRequest.cpp index 16c8c4b7c..117abbf02 100644 --- a/src/workflows/base/WorkflowRequest.cpp +++ b/src/workflows/base/WorkflowRequest.cpp @@ -1,9 +1,11 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "WorkflowRequest.h" +#include "Initializer.h" + using namespace governikus; INIT_FUNCTION([] { diff --git a/src/workflows/base/WorkflowRequest.h b/src/workflows/base/WorkflowRequest.h index 61d0420bd..4325f1687 100644 --- a/src/workflows/base/WorkflowRequest.h +++ b/src/workflows/base/WorkflowRequest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -52,33 +52,26 @@ class WorkflowRequest final } public: - template + template static QSharedPointer create(Args&& ... pArgs) { auto [controller, context] = getGenerator(std::forward(pArgs) ...); - return QSharedPointer::create(controller, context); + return QSharedPointer::create(controller, context); } - template + template static QSharedPointer createHandler(const BusyHandler& pBusyHandler, Args&& ... pArgs) { - return createHandler(pBusyHandler, QVariant(), std::forward(pArgs) ...); + return createHandler(pBusyHandler, QVariant(), std::forward(pArgs) ...); } - template - static QSharedPointer createHandler(const QVariant& pData, Args&& ... pArgs) - { - return createHandler(BusyHandler(), pData, std::forward(pArgs) ...); - } - - - template + template static QSharedPointer createHandler(const BusyHandler& pBusyHandler, const QVariant& pData, Args&& ... pArgs) { auto [controller, context] = getGenerator(std::forward(pArgs) ...); - return QSharedPointer::create(controller, context, pBusyHandler, pData); + return QSharedPointer::create(controller, context, pBusyHandler, pData); } diff --git a/src/workflows/base/context/AccessRightManager.cpp b/src/workflows/base/context/AccessRightManager.cpp index 531b26d3a..4f97fbb25 100644 --- a/src/workflows/base/context/AccessRightManager.cpp +++ b/src/workflows/base/context/AccessRightManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AccessRightManager.h" @@ -92,7 +92,7 @@ void AccessRightManager::removeForbiddenAccessRights(QSet& pAccessR const auto& allowedCvcAccessRights = mTerminalCvc->getBody().getCHAT().getAccessRights(); - const auto rights = AccessRoleAndRightsUtil::allDisplayedOrderedRights(); + const auto& rights = AccessRoleAndRightsUtil::allDisplayedOrderedRights(); const auto& allDisplayedOrderedRights = QSet(rights.constBegin(), rights.constEnd()); const auto& allowedAccessRights = allowedCvcAccessRights & allDisplayedOrderedRights; diff --git a/src/workflows/base/context/AccessRightManager.h b/src/workflows/base/context/AccessRightManager.h index b866fdbdc..53004d186 100644 --- a/src/workflows/base/context/AccessRightManager.h +++ b/src/workflows/base/context/AccessRightManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/context/AuthContext.cpp b/src/workflows/base/context/AuthContext.cpp index b7f1186fd..bc628b7dd 100644 --- a/src/workflows/base/context/AuthContext.cpp +++ b/src/workflows/base/context/AuthContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AuthContext.h" @@ -17,6 +17,7 @@ AuthContext::AuthContext(const Action pAction, bool pActivateUi, const QUrl& pAc : WorkflowContext(pAction, pActivateUi) , mTcTokenNotFound(true) , mErrorReportedToServer(false) + , mReceivedBrowserSendFailed(false) , mSkipMobileRedirect(false) , mShowChangePinView(false) , mActivationUrl(pActivationUrl) @@ -53,6 +54,16 @@ AuthContext::AuthContext(bool pActivateUi, const QUrl& pActivationUrl, const Bro } +void AuthContext::setReceivedBrowserSendFailed(bool pReceivedBrowserSendFailed) +{ + if (mReceivedBrowserSendFailed != pReceivedBrowserSendFailed) + { + mReceivedBrowserSendFailed = pReceivedBrowserSendFailed; + Q_EMIT fireResultChanged(); + } +} + + void AuthContext::requestChangePinView() { if (mShowChangePinView) @@ -142,11 +153,11 @@ CVCertificateChain AuthContext::getChainForCertificationAuthority(const Establis } -void AuthContext::initCvcChainBuilder(const QVector>& pAdditionalCertificates) +void AuthContext::initCvcChainBuilder(const QList>& pAdditionalCertificates) { Q_ASSERT(mDIDAuthenticateEAC1); - QVector> cvcs; + QList> cvcs; cvcs += CVCertificate::fromRaw(Env::getSingleton()->getPreVerificationSettings().getLinkCertificates()); cvcs += getDidAuthenticateEac1()->getCvCertificates(); cvcs += pAdditionalCertificates; diff --git a/src/workflows/base/context/AuthContext.h b/src/workflows/base/context/AuthContext.h index ba71e1afb..882f589ba 100644 --- a/src/workflows/base/context/AuthContext.h +++ b/src/workflows/base/context/AuthContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -59,6 +59,7 @@ class AuthContext private: bool mTcTokenNotFound; bool mErrorReportedToServer; + bool mReceivedBrowserSendFailed; bool mSkipMobileRedirect; bool mShowChangePinView; @@ -110,6 +111,15 @@ class AuthContext } + [[nodiscard]] bool isReceivedBrowserSendFailed() const + { + return mReceivedBrowserSendFailed; + } + + + void setReceivedBrowserSendFailed(bool pReceivedBrowserSendFailed); + + void setErrorReportedToServer(bool pErrorReportedToServer) { mErrorReportedToServer = pErrorReportedToServer; @@ -137,9 +147,8 @@ class AuthContext } - [[nodiscard]] QVector getAcceptedEidTypes() const override + [[nodiscard]] QList getAcceptedEidTypes() const override { - if (isCanAllowedMode() || !mDIDAuthenticateEAC1) { return {AcceptedEidType::CARD_CERTIFIED}; @@ -396,7 +405,7 @@ class AuthContext [[nodiscard]] CVCertificateChain getChainForCertificationAuthority(const EstablishPaceChannelOutput& pPaceOutput) const; - void initCvcChainBuilder(const QVector>& pAdditionalCertificates = QVector>()); + void initCvcChainBuilder(const QList>& pAdditionalCertificates = QList>()); [[nodiscard]] const QSharedPointer& getDvCvc() const diff --git a/src/workflows/base/context/ChangePinContext.cpp b/src/workflows/base/context/ChangePinContext.cpp index b62dc3fdc..b1902e6de 100644 --- a/src/workflows/base/context/ChangePinContext.cpp +++ b/src/workflows/base/context/ChangePinContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "ChangePinContext.h" @@ -72,7 +72,7 @@ bool ChangePinContext::isRequestTransportPin() const } -QVector ChangePinContext::getAcceptedEidTypes() const +QList ChangePinContext::getAcceptedEidTypes() const { if (mRequestTransportPin) { diff --git a/src/workflows/base/context/ChangePinContext.h b/src/workflows/base/context/ChangePinContext.h index ec976dd9b..e6fe761e1 100644 --- a/src/workflows/base/context/ChangePinContext.h +++ b/src/workflows/base/context/ChangePinContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -37,7 +37,7 @@ class ChangePinContext [[nodiscard]] bool isRequestTransportPin() const override; - [[nodiscard]] QVector getAcceptedEidTypes() const override; + [[nodiscard]] QList getAcceptedEidTypes() const override; Q_SIGNALS: void fireNewPinChanged(); diff --git a/src/workflows/base/context/WorkflowContext.cpp b/src/workflows/base/context/WorkflowContext.cpp index 733abdf26..39f56b6a9 100644 --- a/src/workflows/base/context/WorkflowContext.cpp +++ b/src/workflows/base/context/WorkflowContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "WorkflowContext.h" @@ -21,7 +21,7 @@ WorkflowContext::WorkflowContext(const Action pAction, bool pActivateUi) , mStateApproved(false) , mWorkflowKilled(false) , mCurrentState() - , mReaderPlugInTypes() + , mReaderPluginTypes() , mReaderName() , mCardConnection() , mCardVanishedDuringPacePinCount(0) @@ -36,8 +36,6 @@ WorkflowContext::WorkflowContext(const Action pAction, bool pActivateUi) , mStatus(GlobalStatus::Code::No_Error) , mFailureCode() , mStartPaosResult(ECardApiResult::createOk()) - , mErrorReportedToUser(true) - , mPaceResultReportedToUser(false) , mWorkflowFinished(false) , mWorkflowCancelled(false) , mWorkflowCancelledInState(false) @@ -48,6 +46,8 @@ WorkflowContext::WorkflowContext(const Action pAction, bool pActivateUi) , mProgressMessage() , mShowRemoveCardFeedback(false) , mClaimedBy() + , mInterruptRequested(false) + , mInitialInputErrorShown(false) { connect(this, &WorkflowContext::fireCancelWorkflow, this, &WorkflowContext::onWorkflowCancelled); } @@ -94,30 +94,6 @@ void WorkflowContext::onWorkflowCancelled() } -bool WorkflowContext::isErrorReportedToUser() const -{ - return mErrorReportedToUser || mWorkflowKilled; -} - - -void WorkflowContext::setErrorReportedToUser(bool pErrorReportedToUser) -{ - mErrorReportedToUser = pErrorReportedToUser; -} - - -bool WorkflowContext::isPaceResultReportedToUser() const -{ - return mPaceResultReportedToUser; -} - - -void WorkflowContext::setPaceResultReportedToUser(bool pReported) -{ - mPaceResultReportedToUser = pReported; -} - - void WorkflowContext::setStateApproved(bool pApproved) { if (mStateApproved != pApproved) @@ -132,7 +108,7 @@ void WorkflowContext::killWorkflow(GlobalStatus::Code pCode) { qWarning() << "Killing the current workflow."; mWorkflowKilled = true; - mStatus = pCode; + setStatus(pCode); if (!mStateApproved) { setStateApproved(true); @@ -172,24 +148,24 @@ void WorkflowContext::setCurrentState(const QString& pNewState) } -const QVector& WorkflowContext::getReaderPlugInTypes() const +const QList& WorkflowContext::getReaderPluginTypes() const { - return mReaderPlugInTypes; + return mReaderPluginTypes; } -void WorkflowContext::setReaderPlugInTypes(const QVector& pReaderPlugInTypes) +void WorkflowContext::setReaderPluginTypes(const QList& pReaderPluginTypes) { - if (mReaderPlugInTypes != pReaderPlugInTypes) + if (mReaderPluginTypes != pReaderPluginTypes) { #ifdef Q_OS_IOS const bool usedAsSdk = Env::getSingleton()->isUsedAsSDK(); - const bool containsNfc = pReaderPlugInTypes.contains(ReaderManagerPlugInType::NFC); + const bool containsNfc = pReaderPluginTypes.contains(ReaderManagerPluginType::NFC); setSkipStartScan(containsNfc && !usedAsSdk); #endif - mReaderPlugInTypes = pReaderPlugInTypes; - Q_EMIT fireReaderPlugInTypesChanged(); + mReaderPluginTypes = pReaderPluginTypes; + Q_EMIT fireReaderPluginTypesChanged(); } } @@ -233,8 +209,7 @@ void WorkflowContext::resetCardConnection() setCardConnection(QSharedPointer()); if (!mReaderName.isEmpty()) { - const auto readerManager = Env::getSingleton(); - readerManager->updateReaderInfo(mReaderName); + Env::getSingleton()->updateReaderInfo(mReaderName); } } @@ -381,7 +356,6 @@ CardReturnCode WorkflowContext::getLastPaceResult() const void WorkflowContext::setLastPaceResult(CardReturnCode pLastPaceResult) { - mPaceResultReportedToUser = false; mLastPaceResult = pLastPaceResult; Q_EMIT firePaceResultUpdated(); } @@ -414,7 +388,7 @@ bool WorkflowContext::remembersReader() const bool WorkflowContext::isExpectedReader() const { - return mExpectedReader.getName() == mReaderName; + return remembersReader() && mExpectedReader.getName() == mReaderName; } @@ -445,7 +419,6 @@ const GlobalStatus& WorkflowContext::getStatus() const void WorkflowContext::setStatus(const GlobalStatus& pStatus) { mStatus = pStatus; - mErrorReportedToUser = false; Q_EMIT fireResultChanged(); } @@ -635,3 +608,22 @@ bool WorkflowContext::isMobileEidTypeAllowed(const MobileEidType& mobileEidType) } Q_UNREACHABLE(); } + + +void WorkflowContext::setInterruptRequested(bool pInterruptRequested) +{ + mInterruptRequested = pInterruptRequested; +} + + +bool WorkflowContext::isInitialInputErrorShown() const +{ + return mInitialInputErrorShown; +} + + +void WorkflowContext::setInitialInputErrorShown() +{ + mInitialInputErrorShown = true; + Q_EMIT fireInitialInputErrorShownChanged(); +} diff --git a/src/workflows/base/context/WorkflowContext.h b/src/workflows/base/context/WorkflowContext.h index 3c75a1a3f..6f4f1551a 100644 --- a/src/workflows/base/context/WorkflowContext.h +++ b/src/workflows/base/context/WorkflowContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -40,7 +40,7 @@ class WorkflowContext bool mStateApproved; bool mWorkflowKilled; QString mCurrentState; - QVector mReaderPlugInTypes; + QList mReaderPluginTypes; QString mReaderName; QSharedPointer mCardConnection; int mCardVanishedDuringPacePinCount; @@ -55,8 +55,6 @@ class WorkflowContext GlobalStatus mStatus; std::optional mFailureCode; ECardApiResult mStartPaosResult; - bool mErrorReportedToUser; - bool mPaceResultReportedToUser; bool mWorkflowFinished; bool mWorkflowCancelled; bool mWorkflowCancelledInState; @@ -67,6 +65,8 @@ class WorkflowContext QString mProgressMessage; bool mShowRemoveCardFeedback; QString mClaimedBy; + bool mInterruptRequested; + bool mInitialInputErrorShown; private Q_SLOTS: void onWorkflowCancelled(); @@ -74,7 +74,7 @@ class WorkflowContext Q_SIGNALS: void fireStateApprovedChanged(bool pApproved); void fireStateChanged(const QString& pNewState); - void fireReaderPlugInTypesChanged(bool pExplicitStart = false); + void fireReaderPluginTypesChanged(bool pExplicitStart = false); void fireReaderInfoChanged(); void fireReaderNameChanged(); void fireCardConnectionChanged(); @@ -89,6 +89,7 @@ class WorkflowContext void firePasswordTypeChanged(); void fireProgressChanged(); void fireRemoveCardFeedbackChanged(); + void fireInitialInputErrorShownChanged(); void fireCancelWorkflow(); @@ -113,12 +114,6 @@ class WorkflowContext [[nodiscard]] bool wasClaimed() const; void claim(const QObject* pClaimant); - [[nodiscard]] bool isErrorReportedToUser() const; - void setErrorReportedToUser(bool pErrorReportedToUser = true); - - [[nodiscard]] bool isPaceResultReportedToUser() const; - void setPaceResultReportedToUser(bool pReported = true); - void setStateApproved(bool pApproved = true); [[nodiscard]] bool isStateApproved() const; @@ -130,8 +125,8 @@ class WorkflowContext [[nodiscard]] bool isSmartCardUsed() const; - [[nodiscard]] const QVector& getReaderPlugInTypes() const; - void setReaderPlugInTypes(const QVector& pReaderPlugInTypes); + [[nodiscard]] const QList& getReaderPluginTypes() const; + void setReaderPluginTypes(const QList& pReaderPluginTypes); [[nodiscard]] const QString& getReaderName() const; void setReaderName(const QString& pReaderName); @@ -223,12 +218,22 @@ class WorkflowContext } + void setInterruptRequested(bool pInterruptRequested); + [[nodiscard]] bool interruptRequested() const + { + return mInterruptRequested; + } + + void setRemoveCardFeedback(bool pEnabled); - [[nodiscard]] virtual QVector getAcceptedEidTypes() const = 0; + [[nodiscard]] virtual QList getAcceptedEidTypes() const = 0; [[nodiscard]] bool eidTypeMismatch() const; [[nodiscard]] bool isMobileEidTypeAllowed(const MobileEidType& mobileEidType) const; + + [[nodiscard]] bool isInitialInputErrorShown() const; + void setInitialInputErrorShown(); }; } // namespace governikus diff --git a/src/workflows/base/controller/AuthController.cpp b/src/workflows/base/controller/AuthController.cpp index 57db55145..5f1688c3a 100644 --- a/src/workflows/base/controller/AuthController.cpp +++ b/src/workflows/base/controller/AuthController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/AuthController.h" @@ -15,7 +15,6 @@ #include "states/StateSendWhitelistSurvey.h" #include -#include using namespace governikus; @@ -60,17 +59,19 @@ AuthController::AuthController(QSharedPointer pContext) QSharedPointer AuthController::createWorkflowRequest(const QUrl& pUrl, const QVariant& pData, const AuthContext::BrowserHandler& pBrowserHandler) { const auto& handler = [](const QSharedPointer& pActiveWorkflow, const QSharedPointer& pWaitingWorkflow){ - if (QVector{Action::AUTH, Action::SELF, Action::PIN}.contains(pActiveWorkflow->getAction())) + if (QList{Action::AUTH, Action::SELF, Action::PIN}.contains(pActiveWorkflow->getAction())) { const auto activeContext = pActiveWorkflow->getContext(); - if (activeContext->isWorkflowFinished()) + if (activeContext->isWorkflowFinished() && pWaitingWorkflow.isNull()) { qDebug() << "Auto-approving the current state"; - if (pWaitingWorkflow.isNull()) + if (const auto& context = activeContext.objectCast(); context) { - activeContext->setStateApproved(true); - return WorkflowControl::ENQUEUE; + context->setMobileSkipRedirect(true); } + + activeContext->setStateApproved(true); + return WorkflowControl::ENQUEUE; } } diff --git a/src/workflows/base/controller/AuthController.h b/src/workflows/base/controller/AuthController.h index 9646374fd..c38b44eff 100644 --- a/src/workflows/base/controller/AuthController.h +++ b/src/workflows/base/controller/AuthController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/controller/ChangePinController.cpp b/src/workflows/base/controller/ChangePinController.cpp index 839cd1155..6bdaee91f 100644 --- a/src/workflows/base/controller/ChangePinController.cpp +++ b/src/workflows/base/controller/ChangePinController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ChangePinController.h" @@ -48,7 +48,7 @@ ChangePinController::ChangePinController(QSharedPointer pConte sChangePin->addTransition(sChangePin, &AbstractState::fireContinue, sDestroyPace); sChangePin->addTransition(sChangePin, &AbstractState::fireAbort, sDestroyPace); - sChangePin->addTransition(sChangePin, &StateChangePin::fireRetry, sStatePace); + sChangePin->addTransition(sChangePin, &StateChangePin::fireNoCardConnection, sStatePace); sDestroyPace->addTransition(sDestroyPace, &AbstractState::fireContinue, sClearPacePasswords); sDestroyPace->addTransition(sDestroyPace, &AbstractState::fireAbort, sClearPacePasswords); diff --git a/src/workflows/base/controller/ChangePinController.h b/src/workflows/base/controller/ChangePinController.h index 49dc1147a..1296c84d0 100644 --- a/src/workflows/base/controller/ChangePinController.h +++ b/src/workflows/base/controller/ChangePinController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/controller/WorkflowController.cpp b/src/workflows/base/controller/WorkflowController.cpp index 0fb2b417b..b6e0c37de 100644 --- a/src/workflows/base/controller/WorkflowController.cpp +++ b/src/workflows/base/controller/WorkflowController.cpp @@ -1,11 +1,9 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/WorkflowController.h" -#include "states/AbstractState.h" - using namespace governikus; @@ -18,12 +16,6 @@ WorkflowController::WorkflowController(const QSharedPointer& pC } -void WorkflowController::forceStartStopScan() -{ - mStateMachine.setProperty(AbstractState::cFORCE_START_STOP_SCAN, true); -} - - void WorkflowController::run() { mStateMachine.start(); diff --git a/src/workflows/base/controller/WorkflowController.h b/src/workflows/base/controller/WorkflowController.h index da3af83f6..650312c59 100644 --- a/src/workflows/base/controller/WorkflowController.h +++ b/src/workflows/base/controller/WorkflowController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -33,7 +33,7 @@ class WorkflowController template [[nodiscard]] T* addState() { - auto state = StateBuilder::createState(mContext); + auto* state = StateBuilder::createState(mContext); mStateMachine.addState(state); return state; } @@ -42,14 +42,11 @@ class WorkflowController template [[nodiscard]] T* addInitialState() { - auto state = addState(); + auto* state = addState(); mStateMachine.setInitialState(state); return state; } - - void forceStartStopScan(); - public: explicit WorkflowController(const QSharedPointer& pContext); diff --git a/src/workflows/base/paos/ElementDetector.cpp b/src/workflows/base/paos/ElementDetector.cpp index 70c3a7d88..1baf62eee 100644 --- a/src/workflows/base/paos/ElementDetector.cpp +++ b/src/workflows/base/paos/ElementDetector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ElementDetector.h" @@ -31,17 +31,17 @@ void ElementDetector::detectStartElements(const QStringList& pStartElementNames) qCWarning(paos) << "Error parsing PAOS message:" << mReader.errorString(); return; } - else if (mReader.isStartElement()) + else if (mReader.isStartElement() && !handleStartElements(pStartElementNames)) { - handleStartElements(pStartElementNames); + return; } } } -void ElementDetector::handleStartElements(const QStringList& pStartElementNames) +bool ElementDetector::handleStartElements(const QStringList& pStartElementNames) { - QString name = mReader.name().toString(); + const QString name = mReader.name().toString(); if (pStartElementNames.contains(name)) { QXmlStreamAttributes attributes = mReader.attributes(); @@ -50,9 +50,9 @@ void ElementDetector::handleStartElements(const QStringList& pStartElementNames) { value = mReader.text().toString().simplified(); } - if (!handleFoundElement(name, value, attributes)) - { - return; - } + + return handleFoundElement(name, value, attributes); } + + return true; } diff --git a/src/workflows/base/paos/ElementDetector.h b/src/workflows/base/paos/ElementDetector.h index 25d03032b..88494c553 100644 --- a/src/workflows/base/paos/ElementDetector.h +++ b/src/workflows/base/paos/ElementDetector.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /** @@ -23,9 +23,9 @@ class ElementDetector QXmlStreamReader mReader; protected: - void handleStartElements(const QStringList& pStartElementNames); + bool handleStartElements(const QStringList& pStartElementNames); void detectStartElements(const QStringList& pStartElementNames); - virtual bool handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) = 0; + virtual bool handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) = 0; public: explicit ElementDetector(const QByteArray& pXmlData); diff --git a/src/workflows/base/paos/PaosHandler.cpp b/src/workflows/base/paos/PaosHandler.cpp index d928b55e5..adca34ea0 100644 --- a/src/workflows/base/paos/PaosHandler.cpp +++ b/src/workflows/base/paos/PaosHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PaosHandler.h" @@ -11,9 +11,13 @@ #include "retrieve/DidAuthenticateEacAdditionalParser.h" #include "retrieve/TransmitParser.h" + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(paos) + + PaosHandler::PaosHandler(const QByteArray& pXmlData) : ElementDetector(pXmlData) , mXmlData(pXmlData) @@ -68,7 +72,7 @@ void PaosHandler::setParsedObject(PaosMessage* pParsedObject) } -bool PaosHandler::handleFoundElement(const QString& pElementName, const QString&, const QXmlStreamAttributes& pAttributes) +bool PaosHandler::handleFoundElement(QStringView pElementName, const QString&, const QXmlStreamAttributes& pAttributes) { if (pElementName == QLatin1String("InitializeFramework")) { @@ -104,7 +108,8 @@ bool PaosHandler::handleFoundElement(const QString& pElementName, const QString& { mDetectedType = PaosType::STARTPAOS_RESPONSE; } - return false; + + return mDetectedType == PaosType::UNKNOWN; } diff --git a/src/workflows/base/paos/PaosHandler.h b/src/workflows/base/paos/PaosHandler.h index dc3bb3ab6..3d524b6f3 100644 --- a/src/workflows/base/paos/PaosHandler.h +++ b/src/workflows/base/paos/PaosHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -31,7 +31,7 @@ class PaosHandler void parse(); void setParsedObject(PaosMessage* pParsedObject); - bool handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; + bool handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; public: explicit PaosHandler(const QByteArray& pXmlData); diff --git a/src/workflows/base/paos/PaosMessage.cpp b/src/workflows/base/paos/PaosMessage.cpp index 39b68c753..9b050de09 100644 --- a/src/workflows/base/paos/PaosMessage.cpp +++ b/src/workflows/base/paos/PaosMessage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PaosMessage.h" @@ -17,7 +17,7 @@ PaosMessage::PaosMessage(PaosType pType) PaosMessage::~PaosMessage() = default; -bool PaosMessage::handleWSAddressingHeaders(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes&) +bool PaosMessage::handleWSAddressingHeaders(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes&) { if (pElementName == QLatin1String("MessageID")) { diff --git a/src/workflows/base/paos/PaosMessage.h b/src/workflows/base/paos/PaosMessage.h index d915c8f84..1bc852db6 100644 --- a/src/workflows/base/paos/PaosMessage.h +++ b/src/workflows/base/paos/PaosMessage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -26,7 +26,7 @@ class PaosMessage QString mRelatesTo; protected: - bool handleWSAddressingHeaders(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes); + bool handleWSAddressingHeaders(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes); public: const PaosType mType; diff --git a/src/workflows/base/paos/PaosType.cpp b/src/workflows/base/paos/PaosType.cpp index f9f89cc8b..d5d66b889 100644 --- a/src/workflows/base/paos/PaosType.cpp +++ b/src/workflows/base/paos/PaosType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PaosType.h" diff --git a/src/workflows/base/paos/PaosType.h b/src/workflows/base/paos/PaosType.h index 909df715b..b7bef26cc 100644 --- a/src/workflows/base/paos/PaosType.h +++ b/src/workflows/base/paos/PaosType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/RequestType.cpp b/src/workflows/base/paos/RequestType.cpp index 7943c5e92..e625c3132 100644 --- a/src/workflows/base/paos/RequestType.cpp +++ b/src/workflows/base/paos/RequestType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "RequestType.h" diff --git a/src/workflows/base/paos/RequestType.h b/src/workflows/base/paos/RequestType.h index 574360800..2d9fbb1a9 100644 --- a/src/workflows/base/paos/RequestType.h +++ b/src/workflows/base/paos/RequestType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/ResponseType.cpp b/src/workflows/base/paos/ResponseType.cpp index a4b6c6d34..72d85ac4f 100644 --- a/src/workflows/base/paos/ResponseType.cpp +++ b/src/workflows/base/paos/ResponseType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ResponseType.h" diff --git a/src/workflows/base/paos/ResponseType.h b/src/workflows/base/paos/ResponseType.h index a9b1e7a0f..c824ed08f 100644 --- a/src/workflows/base/paos/ResponseType.h +++ b/src/workflows/base/paos/ResponseType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/element/ConnectionHandle.cpp b/src/workflows/base/paos/element/ConnectionHandle.cpp index ecb5db90f..79590b56d 100644 --- a/src/workflows/base/paos/element/ConnectionHandle.cpp +++ b/src/workflows/base/paos/element/ConnectionHandle.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ConnectionHandle.h" diff --git a/src/workflows/base/paos/element/ConnectionHandle.h b/src/workflows/base/paos/element/ConnectionHandle.h index 34969afb6..747c2f306 100644 --- a/src/workflows/base/paos/element/ConnectionHandle.h +++ b/src/workflows/base/paos/element/ConnectionHandle.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/element/ConnectionHandleParser.cpp b/src/workflows/base/paos/element/ConnectionHandleParser.cpp index 99ada8416..d8bfe60f2 100644 --- a/src/workflows/base/paos/element/ConnectionHandleParser.cpp +++ b/src/workflows/base/paos/element/ConnectionHandleParser.cpp @@ -1,12 +1,20 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ConnectionHandleParser.h" #include "ConnectionHandle.h" +#include + + using namespace governikus; +using namespace std::placeholders; + + +Q_DECLARE_LOGGING_CATEGORY(paos) + ConnectionHandleParser::ConnectionHandleParser(QSharedPointer pXmlReader) : ElementParser(pXmlReader) @@ -17,6 +25,15 @@ ConnectionHandleParser::ConnectionHandleParser(QSharedPointer ConnectionHandleParser::~ConnectionHandleParser() = default; +void ConnectionHandleParser::parseUniqueElementText(const std::function& pFunc, QString& pText) +{ + if (readUniqueElementText(pText)) + { + pFunc(pText); + } +} + + ConnectionHandle ConnectionHandleParser::parse() { ConnectionHandle connectionHandle; @@ -31,49 +48,38 @@ ConnectionHandle ConnectionHandleParser::parse() const auto& name = getElementName(); if (name == QLatin1String("ContextHandle")) { - if (readUniqueElementText(contexthandle)) - { - connectionHandle.setContextHandle(contexthandle); - } + parseUniqueElementText(std::bind(&ConnectionHandle::setContextHandle, &connectionHandle, _1), contexthandle); + continue; } - else if (name == QLatin1String("IFDName")) + if (name == QLatin1String("IFDName")) { - if (readUniqueElementText(ifdName)) - { - connectionHandle.setIfdName(ifdName); - } + parseUniqueElementText(std::bind(&ConnectionHandle::setIfdName, &connectionHandle, _1), ifdName); + continue; } - else if (name == QLatin1String("SlotIndex")) + if (name == QLatin1String("SlotIndex")) { - if (readUniqueElementText(slotIndex)) - { - connectionHandle.setSlotIndex(slotIndex); - } + parseUniqueElementText(std::bind(&ConnectionHandle::setSlotIndex, &connectionHandle, _1), slotIndex); + continue; } - else if (name == QLatin1String("CardApplication")) + if (name == QLatin1String("CardApplication")) { - if (readUniqueElementText(cardApplication)) - { - connectionHandle.setCardApplication(cardApplication); - } + parseUniqueElementText(std::bind(&ConnectionHandle::setCardApplication, &connectionHandle, _1), cardApplication); + continue; } - else if (name == QLatin1String("SlotHandle")) + if (name == QLatin1String("SlotHandle")) { - if (readUniqueElementText(slotHandle)) - { - connectionHandle.setSlotHandle(slotHandle); - } + parseUniqueElementText(std::bind(&ConnectionHandle::setSlotHandle, &connectionHandle, _1), slotHandle); + continue; } - else if (name == QLatin1String("RecognitionInfo")) + if (name == QLatin1String("RecognitionInfo")) { qCWarning(paos) << "Unsupported element:" << name; skipCurrentElement(); + continue; } - else - { - qCWarning(paos) << "Unknown element:" << name; - skipCurrentElement(); - } + + qCWarning(paos) << "Unknown element:" << name; + skipCurrentElement(); } return parserFailed() ? ConnectionHandle() : connectionHandle; diff --git a/src/workflows/base/paos/element/ConnectionHandleParser.h b/src/workflows/base/paos/element/ConnectionHandleParser.h index 204ceb7c2..9241be83b 100644 --- a/src/workflows/base/paos/element/ConnectionHandleParser.h +++ b/src/workflows/base/paos/element/ConnectionHandleParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -26,6 +26,10 @@ class ConnectionHandleParser explicit ConnectionHandleParser(QSharedPointer pXmlReader); ~ConnectionHandleParser() override; + private: + void parseUniqueElementText(const std::function& pFunc, QString& pText); + + public: ConnectionHandle parse(); }; diff --git a/src/workflows/base/paos/element/Eac1InputType.cpp b/src/workflows/base/paos/element/Eac1InputType.cpp index b920358b6..a94f18580 100644 --- a/src/workflows/base/paos/element/Eac1InputType.cpp +++ b/src/workflows/base/paos/element/Eac1InputType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Eac1InputType.h" diff --git a/src/workflows/base/paos/element/Eac1InputType.h b/src/workflows/base/paos/element/Eac1InputType.h index 9ade7c795..44c266744 100644 --- a/src/workflows/base/paos/element/Eac1InputType.h +++ b/src/workflows/base/paos/element/Eac1InputType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,9 +15,9 @@ #include "asn1/Chat.h" #include +#include #include #include -#include namespace governikus @@ -30,7 +30,7 @@ class Eac1InputType friend class TestAuthContext; private: - QVector> mCvCertificates; + QList> mCvCertificates; QByteArray mCertificateDescriptionAsBinary; QSharedPointer mCertificateDescription; QSharedPointer mRequiredChat; @@ -38,7 +38,7 @@ class Eac1InputType QByteArray mAuthenticatedAuxiliaryDataAsBinary; QSharedPointer mAuthenticatedAuxiliaryData; QString mTransactionInfo; - QVector mAcceptedEidTypes; + QList mAcceptedEidTypes; void setAuthenticatedAuxiliaryData(const QSharedPointer& pAuthenticatedAuxiliaryData) { @@ -121,7 +121,7 @@ class Eac1InputType } - [[nodiscard]] const QVector>& getCvCertificates() const + [[nodiscard]] const QList>& getCvCertificates() const { return mCvCertificates; } @@ -145,7 +145,7 @@ class Eac1InputType } - [[nodiscard]] const QVector& getAcceptedEidTypes() const + [[nodiscard]] const QList& getAcceptedEidTypes() const { return mAcceptedEidTypes; } diff --git a/src/workflows/base/paos/element/Eac2InputType.cpp b/src/workflows/base/paos/element/Eac2InputType.cpp index 0da1a534f..835b5a208 100644 --- a/src/workflows/base/paos/element/Eac2InputType.cpp +++ b/src/workflows/base/paos/element/Eac2InputType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Eac2InputType.h" @@ -15,7 +15,7 @@ const QString& Eac2InputType::getSignature() const } -const QVector>& Eac2InputType::getCvCertificates() const +const QList>& Eac2InputType::getCvCertificates() const { return mCvCertificates; } diff --git a/src/workflows/base/paos/element/Eac2InputType.h b/src/workflows/base/paos/element/Eac2InputType.h index a231102e8..263357f0c 100644 --- a/src/workflows/base/paos/element/Eac2InputType.h +++ b/src/workflows/base/paos/element/Eac2InputType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,7 +24,7 @@ class Eac2InputType friend class ::test_StateProcessCertificatesFromEac2; private: - QVector> mCvCertificates; + QList> mCvCertificates; QString mSignature; QString mEphemeralPublicKey; void appendCvcert(const QSharedPointer& pCert); @@ -37,7 +37,7 @@ class Eac2InputType [[nodiscard]] const QString& getSignature() const; [[nodiscard]] const QString& getEphemeralPublicKey() const; - [[nodiscard]] const QVector>& getCvCertificates() const; + [[nodiscard]] const QList>& getCvCertificates() const; }; } // namespace governikus diff --git a/src/workflows/base/paos/element/ElementParser.cpp b/src/workflows/base/paos/element/ElementParser.cpp index 10fbd11b7..67ebb4c0e 100644 --- a/src/workflows/base/paos/element/ElementParser.cpp +++ b/src/workflows/base/paos/element/ElementParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ElementParser.h" diff --git a/src/workflows/base/paos/element/ElementParser.h b/src/workflows/base/paos/element/ElementParser.h index 85943864b..4a154cecd 100644 --- a/src/workflows/base/paos/element/ElementParser.h +++ b/src/workflows/base/paos/element/ElementParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,9 +10,9 @@ #include "paos/element/ConnectionHandle.h" +#include #include #include -#include #include @@ -62,7 +62,7 @@ class ElementParser * \param pElementName the elements name used to generate the log message. * \return \c true, if the assertion holds, \c false otherwise. */ - template bool assertMandatoryList(const QVector& pList, const char* const pElementName); + template bool assertMandatoryList(const QList& pList, const char* const pElementName); /*! * \brief Issues a log warning and sets the error when a duplicate element has been encountered. @@ -107,7 +107,7 @@ class ElementParser }; -template bool ElementParser::assertMandatoryList(const QVector& pList, const char* const pElementName) +template bool ElementParser::assertMandatoryList(const QList& pList, const char* const pElementName) { if (pList.isEmpty()) { diff --git a/src/workflows/base/paos/element/SupportedApi.cpp b/src/workflows/base/paos/element/SupportedApi.cpp index b6ae9e00a..738a52105 100644 --- a/src/workflows/base/paos/element/SupportedApi.cpp +++ b/src/workflows/base/paos/element/SupportedApi.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SupportedApi.h" diff --git a/src/workflows/base/paos/element/SupportedApi.h b/src/workflows/base/paos/element/SupportedApi.h index 9d320a70c..39ef6b453 100644 --- a/src/workflows/base/paos/element/SupportedApi.h +++ b/src/workflows/base/paos/element/SupportedApi.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/element/UserAgent.cpp b/src/workflows/base/paos/element/UserAgent.cpp index 45432e90f..6faba6682 100644 --- a/src/workflows/base/paos/element/UserAgent.cpp +++ b/src/workflows/base/paos/element/UserAgent.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "UserAgent.h" diff --git a/src/workflows/base/paos/element/UserAgent.h b/src/workflows/base/paos/element/UserAgent.h index c64690685..a45942e5a 100644 --- a/src/workflows/base/paos/element/UserAgent.h +++ b/src/workflows/base/paos/element/UserAgent.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.cpp b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.cpp index 9691995cc..f950108f5 100644 --- a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.cpp +++ b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateResponseEac1.h" @@ -81,25 +81,25 @@ void DIDAuthenticateResponseEAC1::setChallenge(const QByteArray& pValue) } -void DIDAuthenticateResponseEAC1::createBodyElement() +void DIDAuthenticateResponseEAC1::createBodyElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("DIDAuthenticateResponse")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); - mWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); + pWriter.writeStartElement(QStringLiteral("DIDAuthenticateResponse")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); + pWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); createResultElement(*this); - createAuthenticationProtocolDataElement(); + createAuthenticationProtocolDataElement(pWriter); - mWriter.writeEndElement(); // DIDAuthenticateResponse + pWriter.writeEndElement(); // DIDAuthenticateResponse } -void DIDAuthenticateResponseEAC1::createAuthenticationProtocolDataElement() +void DIDAuthenticateResponseEAC1::createAuthenticationProtocolDataElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("AuthenticationProtocolData")); + pWriter.writeStartElement(QStringLiteral("AuthenticationProtocolData")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), getNamespaceType(Namespace::TECHSCHEMA, QStringLiteral("EAC1OutputType"))); - mWriter.writeAttribute(QStringLiteral("Protocol"), QStringLiteral("urn:oid:1.3.162.15480.3.0.14.2")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), getNamespaceType(Namespace::TECHSCHEMA, QStringLiteral("EAC1OutputType"))); + pWriter.writeAttribute(QStringLiteral("Protocol"), QStringLiteral("urn:oid:1.3.162.15480.3.0.14.2")); if (!mCertificateHolderAuthorizationTemplate.isNull()) { @@ -114,7 +114,7 @@ void DIDAuthenticateResponseEAC1::createAuthenticationProtocolDataElement() writeTextElement(QStringLiteral("IDPICC"), mIdPICC); writeTextElement(QStringLiteral("Challenge"), mChallenge); - mWriter.writeEndElement(); // AuthenticationProtocolData + pWriter.writeEndElement(); // AuthenticationProtocolData } diff --git a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.h b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.h index fc1c7fc39..7e5051410 100644 --- a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.h +++ b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac1.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -33,10 +33,9 @@ class DIDAuthenticateResponseEAC1 QByteArray mIdPICC; QByteArray mChallenge; - void createDIDAuthenticateResponseEAC1Element(); - void createAuthenticationProtocolDataElement(); + void createBodyElement(QXmlStreamWriter& pWriter) override; + void createAuthenticationProtocolDataElement(QXmlStreamWriter& pWriter); - void createBodyElement() override; [[nodiscard]] virtual ECardApiResult getResult() const; public: diff --git a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.cpp b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.cpp index 68659ceda..7872b536f 100644 --- a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.cpp +++ b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateResponseEac2.h" @@ -18,24 +18,24 @@ DIDAuthenticateResponseEAC2::DIDAuthenticateResponseEAC2() } -void DIDAuthenticateResponseEAC2::createBodyElement() +void DIDAuthenticateResponseEAC2::createBodyElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("DIDAuthenticateResponse")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); - mWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); + pWriter.writeStartElement(QStringLiteral("DIDAuthenticateResponse")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); + pWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); createResultElement(*this); - createAuthenticationProtocolDataElement(); + createAuthenticationProtocolDataElement(pWriter); - mWriter.writeEndElement(); // DIDAuthenticateResponse + pWriter.writeEndElement(); // DIDAuthenticateResponse } -void DIDAuthenticateResponseEAC2::createAuthenticationProtocolDataElement() +void DIDAuthenticateResponseEAC2::createAuthenticationProtocolDataElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("AuthenticationProtocolData")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), getNamespaceType(Namespace::TECHSCHEMA, QStringLiteral("EAC2OutputType"))); - mWriter.writeAttribute(QStringLiteral("Protocol"), QStringLiteral("urn:oid:1.3.162.15480.3.0.14.2")); + pWriter.writeStartElement(QStringLiteral("AuthenticationProtocolData")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), getNamespaceType(Namespace::TECHSCHEMA, QStringLiteral("EAC2OutputType"))); + pWriter.writeAttribute(QStringLiteral("Protocol"), QStringLiteral("urn:oid:1.3.162.15480.3.0.14.2")); if (!mEfCardSecurity.isNull()) { @@ -54,7 +54,7 @@ void DIDAuthenticateResponseEAC2::createAuthenticationProtocolDataElement() writeTextElement(QStringLiteral("Challenge"), mChallenge); } - mWriter.writeEndElement(); // AuthenticationProtocolData + pWriter.writeEndElement(); // AuthenticationProtocolData } diff --git a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.h b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.h index 4d55f221f..62379a507 100644 --- a/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.h +++ b/src/workflows/base/paos/invoke/DidAuthenticateResponseEac2.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -28,10 +28,8 @@ class DIDAuthenticateResponseEAC2 QByteArray mNonce; QByteArray mChallenge; - void createDIDAuthenticateResponseEAC2Element(); - void createAuthenticationProtocolDataElement(); - - void createBodyElement() override; + void createBodyElement(QXmlStreamWriter& pWriter) override; + void createAuthenticationProtocolDataElement(QXmlStreamWriter& pWriter); public: DIDAuthenticateResponseEAC2(); diff --git a/src/workflows/base/paos/invoke/InitializeFrameworkResponse.cpp b/src/workflows/base/paos/invoke/InitializeFrameworkResponse.cpp index 9963d6d26..a5369d338 100644 --- a/src/workflows/base/paos/invoke/InitializeFrameworkResponse.cpp +++ b/src/workflows/base/paos/invoke/InitializeFrameworkResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "InitializeFrameworkResponse.h" @@ -12,27 +12,27 @@ InitializeFrameworkResponse::InitializeFrameworkResponse() } -void InitializeFrameworkResponse::createBodyElement() +void InitializeFrameworkResponse::createBodyElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("InitializeFrameworkResponse")); + pWriter.writeStartElement(QStringLiteral("InitializeFrameworkResponse")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::ECARD)); - mWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); + pWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::ECARD)); + pWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); createResultElement(*this); - createVersionElement(); + createVersionElement(pWriter); - mWriter.writeEndElement(); // InitializeFrameworkResponse + pWriter.writeEndElement(); // InitializeFrameworkResponse } -void InitializeFrameworkResponse::createVersionElement() +void InitializeFrameworkResponse::createVersionElement(QXmlStreamWriter& pWriter) const { - mWriter.writeStartElement(QStringLiteral("Version")); + pWriter.writeStartElement(QStringLiteral("Version")); - mWriter.writeTextElement(QStringLiteral("Major"), mSupportedAPI.getMajor()); - mWriter.writeTextElement(QStringLiteral("Minor"), mSupportedAPI.getMinor()); - mWriter.writeTextElement(QStringLiteral("SubMinor"), mSupportedAPI.getSubminor()); + pWriter.writeTextElement(QStringLiteral("Major"), mSupportedAPI.getMajor()); + pWriter.writeTextElement(QStringLiteral("Minor"), mSupportedAPI.getMinor()); + pWriter.writeTextElement(QStringLiteral("SubMinor"), mSupportedAPI.getSubminor()); - mWriter.writeEndElement(); // InitializeFrameworkResponse + pWriter.writeEndElement(); // InitializeFrameworkResponse } diff --git a/src/workflows/base/paos/invoke/InitializeFrameworkResponse.h b/src/workflows/base/paos/invoke/InitializeFrameworkResponse.h index f874eab28..7d99b1910 100644 --- a/src/workflows/base/paos/invoke/InitializeFrameworkResponse.h +++ b/src/workflows/base/paos/invoke/InitializeFrameworkResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -24,10 +24,8 @@ class InitializeFrameworkResponse private: SupportedAPI mSupportedAPI; - void createVersionElement(); - void createInitializeFrameworkResponse(); - - void createBodyElement() override; + void createBodyElement(QXmlStreamWriter& pWriter) override; + void createVersionElement(QXmlStreamWriter& pWriter) const; public: InitializeFrameworkResponse(); diff --git a/src/workflows/base/paos/invoke/PaosCreator.cpp b/src/workflows/base/paos/invoke/PaosCreator.cpp index c163e02e1..ef0c871c8 100644 --- a/src/workflows/base/paos/invoke/PaosCreator.cpp +++ b/src/workflows/base/paos/invoke/PaosCreator.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PaosCreator.h" @@ -165,7 +165,7 @@ void PaosCreator::createEnvelopeElement() createHeaderElement(); mWriter.writeStartElement(getNamespacePrefix(Namespace::SOAP, QStringLiteral("Body"))); - createBodyElement(); + createBodyElement(mWriter); mWriter.writeEndElement(); // Body mWriter.writeEndElement(); // Envelope diff --git a/src/workflows/base/paos/invoke/PaosCreator.h b/src/workflows/base/paos/invoke/PaosCreator.h index 330d1e7e7..29c7d9036 100644 --- a/src/workflows/base/paos/invoke/PaosCreator.h +++ b/src/workflows/base/paos/invoke/PaosCreator.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -31,15 +31,14 @@ class PaosCreator QByteArray mContent; QString mRelatedMessageId; + QXmlStreamWriter mWriter; void createEnvelopeElement(); void createHeaderElement(); protected: - QXmlStreamWriter mWriter; - void writeTextElement(const QString& pQualifiedName, const QByteArray& pText); - virtual void createBodyElement() = 0; + virtual void createBodyElement(QXmlStreamWriter& pWriter) = 0; void createResultElement(const ResponseType& pResponse); @@ -56,9 +55,9 @@ class PaosCreator QByteArray marshall(); void setRelatedMessageId(const QString& pId); - static QString getNamespace(Namespace pPrefix); - static QString getNamespacePrefix(Namespace pPrefix, const QString& pSuffix = QString()); - static QString getNamespaceType(Namespace pPrefix, const QString& pType); + [[nodiscard]] static QString getNamespace(Namespace pPrefix); + [[nodiscard]] static QString getNamespacePrefix(Namespace pPrefix, const QString& pSuffix = QString()); + [[nodiscard]] static QString getNamespaceType(Namespace pPrefix, const QString& pType); }; } // namespace governikus diff --git a/src/workflows/base/paos/invoke/StartPaos.cpp b/src/workflows/base/paos/invoke/StartPaos.cpp index 88b085f5b..59c8fc6bb 100644 --- a/src/workflows/base/paos/invoke/StartPaos.cpp +++ b/src/workflows/base/paos/invoke/StartPaos.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StartPaos.h" @@ -19,61 +19,61 @@ StartPaos::StartPaos(const QByteArray& pSessionId) } -void StartPaos::createConnectionHandleElement() +void StartPaos::createBodyElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("ConnectionHandle")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::XSI), getNamespace(Namespace::XSI)); - mWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), QStringLiteral("ConnectionHandleType")); + pWriter.writeStartElement(QStringLiteral("StartPAOS")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); - mWriter.writeTextElement(QStringLiteral("CardApplication"), QStringLiteral("e80704007f00070302")); - mWriter.writeTextElement(QStringLiteral("SlotHandle"), QStringLiteral("00")); + createSessionIdentifierElement(); + createConnectionHandleElement(pWriter); + createUserAgentElement(pWriter); + createSupportedAPIVersionsElement(pWriter); - mWriter.writeEndElement(); // ConnectionHandle + pWriter.writeEndElement(); // StartPAOS } -void StartPaos::createUserAgentElement() +void StartPaos::createSessionIdentifierElement() { - mWriter.writeStartElement(QStringLiteral("UserAgent")); - - const UserAgent userAgent; - mWriter.writeTextElement(QStringLiteral("Name"), userAgent.getName()); - mWriter.writeTextElement(QStringLiteral("VersionMajor"), userAgent.getVersionMajor()); - mWriter.writeTextElement(QStringLiteral("VersionMinor"), userAgent.getVersionMinor()); - mWriter.writeTextElement(QStringLiteral("VersionSubminor"), userAgent.getVersionSubminor()); - - mWriter.writeEndElement(); // UserAgent + writeTextElement(QStringLiteral("SessionIdentifier"), mSessionId); } -void StartPaos::createSupportedAPIVersionsElement() +void StartPaos::createConnectionHandleElement(QXmlStreamWriter& pWriter) const { - mWriter.writeStartElement(QStringLiteral("SupportedAPIVersions")); + pWriter.writeStartElement(QStringLiteral("ConnectionHandle")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::XSI), getNamespace(Namespace::XSI)); + pWriter.writeAttribute(getNamespacePrefix(Namespace::XSI, QStringLiteral("type")), QStringLiteral("ConnectionHandleType")); - const SupportedAPI supportedAPI; - mWriter.writeTextElement(QStringLiteral("Major"), supportedAPI.getMajor()); - mWriter.writeTextElement(QStringLiteral("Minor"), supportedAPI.getMinor()); - mWriter.writeTextElement(QStringLiteral("Subminor"), supportedAPI.getSubminor()); + pWriter.writeTextElement(QStringLiteral("CardApplication"), QStringLiteral("e80704007f00070302")); + pWriter.writeTextElement(QStringLiteral("SlotHandle"), QStringLiteral("00")); - mWriter.writeEndElement(); // SupportedAPIVersions + pWriter.writeEndElement(); // ConnectionHandle } -void StartPaos::createSessionIdentifierElement() +void StartPaos::createUserAgentElement(QXmlStreamWriter& pWriter) const { - writeTextElement(QStringLiteral("SessionIdentifier"), mSessionId); + pWriter.writeStartElement(QStringLiteral("UserAgent")); + + const UserAgent userAgent; + pWriter.writeTextElement(QStringLiteral("Name"), userAgent.getName()); + pWriter.writeTextElement(QStringLiteral("VersionMajor"), userAgent.getVersionMajor()); + pWriter.writeTextElement(QStringLiteral("VersionMinor"), userAgent.getVersionMinor()); + pWriter.writeTextElement(QStringLiteral("VersionSubminor"), userAgent.getVersionSubminor()); + + pWriter.writeEndElement(); // UserAgent } -void StartPaos::createBodyElement() +void StartPaos::createSupportedAPIVersionsElement(QXmlStreamWriter& pWriter) const { - mWriter.writeStartElement(QStringLiteral("StartPAOS")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); + pWriter.writeStartElement(QStringLiteral("SupportedAPIVersions")); - createSessionIdentifierElement(); - createConnectionHandleElement(); - createUserAgentElement(); - createSupportedAPIVersionsElement(); + const SupportedAPI supportedAPI; + pWriter.writeTextElement(QStringLiteral("Major"), supportedAPI.getMajor()); + pWriter.writeTextElement(QStringLiteral("Minor"), supportedAPI.getMinor()); + pWriter.writeTextElement(QStringLiteral("Subminor"), supportedAPI.getSubminor()); - mWriter.writeEndElement(); // StartPAOS + pWriter.writeEndElement(); // SupportedAPIVersions } diff --git a/src/workflows/base/paos/invoke/StartPaos.h b/src/workflows/base/paos/invoke/StartPaos.h index 87e4960e4..c80ac8ee5 100644 --- a/src/workflows/base/paos/invoke/StartPaos.h +++ b/src/workflows/base/paos/invoke/StartPaos.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -27,12 +27,11 @@ class StartPaos private: const QByteArray mSessionId; + void createBodyElement(QXmlStreamWriter& pWriter) override; void createSessionIdentifierElement(); - void createConnectionHandleElement(); - void createUserAgentElement(); - void createSupportedAPIVersionsElement(); - - void createBodyElement() override; + void createConnectionHandleElement(QXmlStreamWriter& pWriter) const; + void createUserAgentElement(QXmlStreamWriter& pWriter) const; + void createSupportedAPIVersionsElement(QXmlStreamWriter& pWriter) const; public: explicit StartPaos(const QByteArray& pSessionId); diff --git a/src/workflows/base/paos/invoke/TransmitResponse.cpp b/src/workflows/base/paos/invoke/TransmitResponse.cpp index 6432ea5eb..feb1fdaa0 100644 --- a/src/workflows/base/paos/invoke/TransmitResponse.cpp +++ b/src/workflows/base/paos/invoke/TransmitResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TransmitResponse.h" @@ -13,11 +13,11 @@ TransmitResponse::TransmitResponse() } -void TransmitResponse::createBodyElement() +void TransmitResponse::createBodyElement(QXmlStreamWriter& pWriter) { - mWriter.writeStartElement(QStringLiteral("TransmitResponse")); - mWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); - mWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); + pWriter.writeStartElement(QStringLiteral("TransmitResponse")); + pWriter.writeAttribute(getNamespacePrefix(Namespace::DEFAULT), getNamespace(Namespace::TECHSCHEMA)); + pWriter.writeAttribute(QStringLiteral("Profile"), getNamespace(Namespace::ECARD)); createResultElement(*this); @@ -26,7 +26,7 @@ void TransmitResponse::createBodyElement() writeTextElement(QStringLiteral("OutputAPDU"), apdu); } - mWriter.writeEndElement(); // TransmitResponse + pWriter.writeEndElement(); // TransmitResponse } diff --git a/src/workflows/base/paos/invoke/TransmitResponse.h b/src/workflows/base/paos/invoke/TransmitResponse.h index a2e991e2c..4c00e89dd 100644 --- a/src/workflows/base/paos/invoke/TransmitResponse.h +++ b/src/workflows/base/paos/invoke/TransmitResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -23,9 +23,7 @@ class TransmitResponse private: QByteArrayList mOutputApdus; - void createTransmitResponse(); - - void createBodyElement() override; + void createBodyElement(QXmlStreamWriter& pWriter) override; public: TransmitResponse(); diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac1.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEac1.cpp index 857afb02b..bf65bfffb 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac1.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateEac1.h" @@ -65,7 +65,7 @@ const ConnectionHandle& DIDAuthenticateEAC1::getConnectionHandle() const } -const QVector>& DIDAuthenticateEAC1::getCvCertificates() const +const QList>& DIDAuthenticateEAC1::getCvCertificates() const { return mEac1InputType.getCvCertificates(); } @@ -95,7 +95,7 @@ const QString& DIDAuthenticateEAC1::getTransactionInfo() const } -const QVector& DIDAuthenticateEAC1::getAcceptedEidTypes() const +const QList& DIDAuthenticateEAC1::getAcceptedEidTypes() const { return mEac1InputType.getAcceptedEidTypes(); } diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac1.h b/src/workflows/base/paos/retrieve/DidAuthenticateEac1.h index 103a9f55a..2ab275b5c 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac1.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac1.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,7 +16,7 @@ #include "paos/element/ConnectionHandle.h" #include "paos/element/Eac1InputType.h" -#include +#include namespace governikus @@ -48,12 +48,12 @@ class DIDAuthenticateEAC1 [[nodiscard]] const QSharedPointer& getCertificateDescription() const; [[nodiscard]] const QByteArray& getCertificateDescriptionAsBinary() const; [[nodiscard]] const ConnectionHandle& getConnectionHandle() const; - [[nodiscard]] const QVector>& getCvCertificates() const; + [[nodiscard]] const QList>& getCvCertificates() const; [[nodiscard]] const QString& getDidName() const; [[nodiscard]] const QSharedPointer& getOptionalChat() const; [[nodiscard]] const QSharedPointer& getRequiredChat() const; [[nodiscard]] const QString& getTransactionInfo() const; - [[nodiscard]] const QVector& getAcceptedEidTypes() const; + [[nodiscard]] const QList& getAcceptedEidTypes() const; }; } // namespace governikus diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.cpp index f4dd75aab..cc1cf1b5e 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.cpp @@ -1,21 +1,22 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Parser for the PAOS DidAuthenticateEac1 element. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "paos/retrieve/DidAuthenticateEac1Parser.h" #include "paos/invoke/PaosCreator.h" +#include #include #include + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(paos) + + DidAuthenticateEac1Parser::DidAuthenticateEac1Parser() : PaosParser(QStringLiteral("DIDAuthenticate")) { diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.h b/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.h index 1a9e7a463..0be703a96 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac1Parser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac2.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEac2.cpp index 768684472..41c392493 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac2.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "paos/retrieve/DidAuthenticateEac2.h" @@ -34,7 +34,7 @@ const QString& DIDAuthenticateEAC2::getSignature() const } -const QVector>& DIDAuthenticateEAC2::getCvCertificates() const +const QList>& DIDAuthenticateEAC2::getCvCertificates() const { return mEac2.getCvCertificates(); } diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac2.h b/src/workflows/base/paos/retrieve/DidAuthenticateEac2.h index e104db59a..bb99a0fa2 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac2.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac2.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -39,7 +39,7 @@ class DIDAuthenticateEAC2 [[nodiscard]] const QString& getDidName() const; [[nodiscard]] const QString& getSignature() const; [[nodiscard]] const QString& getEphemeralPublicKey() const; - [[nodiscard]] const QVector>& getCvCertificates() const; + [[nodiscard]] const QList>& getCvCertificates() const; }; } // namespace governikus diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.cpp index ecf7dd6b3..15029164b 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "paos/retrieve/DidAuthenticateEac2Parser.h" @@ -8,11 +8,15 @@ #include "paos/retrieve/DidAuthenticateEac2.h" #include +#include using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(paos) + + DidAuthenticateEac2Parser::DidAuthenticateEac2Parser() : PaosParser(QStringLiteral("DIDAuthenticate")) { diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.h b/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.h index 8dd11d95f..9e925b79d 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEac2Parser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.cpp index 3344194ca..cf83d2aff 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "DidAuthenticateEacAdditional.h" diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.h b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.h index a1ef96b8d..3f3d15efb 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditional.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.cpp b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.cpp index 29a37ff4f..c90a9a491 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.cpp +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "paos/retrieve/DidAuthenticateEacAdditionalParser.h" @@ -8,10 +8,15 @@ #include "paos/retrieve/DidAuthenticateEacAdditional.h" #include +#include + using namespace governikus; +Q_DECLARE_LOGGING_CATEGORY(paos) + + DidAuthenticateEacAdditionalParser::DidAuthenticateEacAdditionalParser() : PaosParser(QStringLiteral("DIDAuthenticate")) { diff --git a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.h b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.h index 520a8bd86..562670de1 100644 --- a/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.h +++ b/src/workflows/base/paos/retrieve/DidAuthenticateEacAdditionalParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/retrieve/InitializeFramework.cpp b/src/workflows/base/paos/retrieve/InitializeFramework.cpp index 9b508d7e7..f05231945 100644 --- a/src/workflows/base/paos/retrieve/InitializeFramework.cpp +++ b/src/workflows/base/paos/retrieve/InitializeFramework.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -30,7 +30,7 @@ void InitializeFramework::parse() } -bool InitializeFramework::handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) +bool InitializeFramework::handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) { if (handleWSAddressingHeaders(pElementName, pValue, pAttributes)) { diff --git a/src/workflows/base/paos/retrieve/InitializeFramework.h b/src/workflows/base/paos/retrieve/InitializeFramework.h index f2e965b28..01b847a0e 100644 --- a/src/workflows/base/paos/retrieve/InitializeFramework.h +++ b/src/workflows/base/paos/retrieve/InitializeFramework.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -20,7 +20,7 @@ class InitializeFramework { private: void parse(); - bool handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; + bool handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; public: explicit InitializeFramework(const QByteArray& pXmlData); diff --git a/src/workflows/base/paos/retrieve/PaosParser.cpp b/src/workflows/base/paos/retrieve/PaosParser.cpp index dbdde12b4..4530dfe42 100644 --- a/src/workflows/base/paos/retrieve/PaosParser.cpp +++ b/src/workflows/base/paos/retrieve/PaosParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "PaosParser.h" @@ -7,9 +7,15 @@ #include "paos/invoke/PaosCreator.h" #include +#include + using namespace governikus; + +Q_DECLARE_LOGGING_CATEGORY(paos) + + PaosParser::PaosParser(const QString& pMessageName) : ElementParser(QSharedPointer::create()) , mMessageName(pMessageName) diff --git a/src/workflows/base/paos/retrieve/PaosParser.h b/src/workflows/base/paos/retrieve/PaosParser.h index 0ca2438ba..797aff7ed 100644 --- a/src/workflows/base/paos/retrieve/PaosParser.h +++ b/src/workflows/base/paos/retrieve/PaosParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/paos/retrieve/StartPaosResponse.cpp b/src/workflows/base/paos/retrieve/StartPaosResponse.cpp index c0fe6c5b1..a8ef9d617 100644 --- a/src/workflows/base/paos/retrieve/StartPaosResponse.cpp +++ b/src/workflows/base/paos/retrieve/StartPaosResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StartPaosResponse.h" @@ -64,7 +64,7 @@ void StartPaosResponse::parse() } -bool StartPaosResponse::handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) +bool StartPaosResponse::handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) { if (handleWSAddressingHeaders(pElementName, pValue, pAttributes)) { diff --git a/src/workflows/base/paos/retrieve/StartPaosResponse.h b/src/workflows/base/paos/retrieve/StartPaosResponse.h index 1ddd63f89..25bb01c16 100644 --- a/src/workflows/base/paos/retrieve/StartPaosResponse.h +++ b/src/workflows/base/paos/retrieve/StartPaosResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -40,7 +40,7 @@ class StartPaosResponse private: void parse(); - bool handleFoundElement(const QString& pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; + bool handleFoundElement(QStringView pElementName, const QString& pValue, const QXmlStreamAttributes& pAttributes) override; int valuetoInt(const QString& pValue) const; }; diff --git a/src/workflows/base/paos/retrieve/Transmit.cpp b/src/workflows/base/paos/retrieve/Transmit.cpp index f4550b688..1d9e6c0cf 100644 --- a/src/workflows/base/paos/retrieve/Transmit.cpp +++ b/src/workflows/base/paos/retrieve/Transmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Transmit.h" diff --git a/src/workflows/base/paos/retrieve/Transmit.h b/src/workflows/base/paos/retrieve/Transmit.h index 28773c45a..9b40b3983 100644 --- a/src/workflows/base/paos/retrieve/Transmit.h +++ b/src/workflows/base/paos/retrieve/Transmit.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,7 +8,7 @@ #pragma once -#include +#include #include "InputAPDUInfo.h" #include "paos/PaosMessage.h" @@ -20,7 +20,7 @@ class Transmit { private: QString mSlotHandle; - QVector mInputApduInfos; + QList mInputApduInfos; public: Transmit(); @@ -39,7 +39,7 @@ class Transmit } - [[nodiscard]] const QVector& getInputApduInfos() const + [[nodiscard]] const QList& getInputApduInfos() const { return mInputApduInfos; } diff --git a/src/workflows/base/paos/retrieve/TransmitParser.cpp b/src/workflows/base/paos/retrieve/TransmitParser.cpp index f322aea45..044dc4bc3 100644 --- a/src/workflows/base/paos/retrieve/TransmitParser.cpp +++ b/src/workflows/base/paos/retrieve/TransmitParser.cpp @@ -1,13 +1,19 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TransmitParser.h" #include +#include + using namespace governikus; + +Q_DECLARE_LOGGING_CATEGORY(paos) + + TransmitParser::TransmitParser() : PaosParser(QStringLiteral("Transmit")) { diff --git a/src/workflows/base/paos/retrieve/TransmitParser.h b/src/workflows/base/paos/retrieve/TransmitParser.h index 4c222a8e0..ff90c2ab5 100644 --- a/src/workflows/base/paos/retrieve/TransmitParser.h +++ b/src/workflows/base/paos/retrieve/TransmitParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/AbstractState.cpp b/src/workflows/base/states/AbstractState.cpp index 5b024e893..6f6a5bf2c 100644 --- a/src/workflows/base/states/AbstractState.cpp +++ b/src/workflows/base/states/AbstractState.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "AbstractState.h" @@ -19,13 +19,11 @@ Q_DECLARE_LOGGING_CATEGORY(support) using namespace governikus; -const char* const AbstractState::cFORCE_START_STOP_SCAN = "FORCE_START_STOP_SCAN"; - - AbstractState::AbstractState(const QSharedPointer& pContext) : mContext(pContext) , mConnections() , mAbortOnCardRemoved(false) + , mHandleNfcStop(false) , mKeepCardConnectionAlive(false) { Q_ASSERT(mContext); @@ -39,6 +37,12 @@ void AbstractState::setAbortOnCardRemoved() } +void AbstractState::setHandleNfcStop() +{ + mHandleNfcStop = true; +} + + void AbstractState::setKeepCardConnectionAlive() { mKeepCardConnectionAlive = true; @@ -80,12 +84,16 @@ void AbstractState::onEntry(QEvent* pEvent) } Q_ASSERT(mConnections.isEmpty()); + const auto* readerManager = Env::getSingleton(); if (mAbortOnCardRemoved) { - const auto readerManager = Env::getSingleton(); mConnections += connect(readerManager, &ReaderManager::fireCardRemoved, this, &AbstractState::onCardRemoved); mConnections += connect(readerManager, &ReaderManager::fireReaderRemoved, this, &AbstractState::onCardRemoved); } + if (mHandleNfcStop) + { + mConnections += connect(readerManager, &ReaderManager::fireStatusChanged, this, &AbstractState::onReaderStatusChanged); + } mConnections += connect(mContext.data(), &WorkflowContext::fireCancelWorkflow, this, &AbstractState::onUserCancelled); mConnections += connect(mContext.data(), &WorkflowContext::fireStateApprovedChanged, this, &AbstractState::onStateApprovedChanged, Qt::QueuedConnection); @@ -145,7 +153,7 @@ bool AbstractState::isCancellationByUser() const void AbstractState::onUserCancelled() { - qCInfo(support) << "Cancellation by user"; + qCInfo(support) << "Cancellation by user in" << getStateName(); mContext->setWorkflowCancelledInState(); updateStatus(GlobalStatus::Code::Workflow_Cancellation_By_User); Q_EMIT fireAbort({FailureCode::Reason::User_Cancelled, @@ -185,26 +193,45 @@ void AbstractState::updateStartPaosResult(const ECardApiResult& pStartPaosResult } -bool AbstractState::isStartStopEnabled() const +void AbstractState::stopNfcScanIfNecessary(const QString& pError) const { - return mContext->getReaderPlugInTypes().contains(ReaderManagerPlugInType::NFC) - || machine()->property(cFORCE_START_STOP_SCAN).toBool(); +#if defined(Q_OS_IOS) + const auto* volatileSettings = Env::getSingleton(); + if (volatileSettings->isUsedAsSDK() && !volatileSettings->handleInterrupt()) + { + return; + } + + if (mContext->getReaderPluginTypes().contains(ReaderManagerPluginType::NFC)) + { + Env::getSingleton()->stopScan(ReaderManagerPluginType::NFC, pError); + } +#else + Q_UNUSED(pError) +#endif } -void AbstractState::stopNfcScanIfNecessary(const QString& pError) const +void AbstractState::onReaderStatusChanged(const ReaderManagerPluginInfo& pInfo) const { #if defined(Q_OS_IOS) - const auto& volatileSettings = Env::getSingleton(); - if (volatileSettings->isUsedAsSDK() && !volatileSettings->handleInterrupt()) + if (!Env::getSingleton()->isUsedAsSDK() || pInfo.getPluginType() != ReaderManagerPluginType::NFC) { return; } - if (isStartStopEnabled()) + + if (!pInfo.isScanRunning()) { - Env::getSingleton()->stopScan(ReaderManagerPlugInType::NFC, pError); + if (mContext->interruptRequested()) + { + mContext->setInterruptRequested(false); + } + else + { + Q_EMIT mContext->fireCancelWorkflow(); + } } #else - Q_UNUSED(pError) + Q_UNUSED(pInfo) #endif } diff --git a/src/workflows/base/states/AbstractState.h b/src/workflows/base/states/AbstractState.h index 763e52346..e596705f3 100644 --- a/src/workflows/base/states/AbstractState.h +++ b/src/workflows/base/states/AbstractState.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -49,17 +49,18 @@ class AbstractState private: const QSharedPointer mContext; - QVector mConnections; + QList mConnections; bool mAbortOnCardRemoved; + bool mHandleNfcStop; bool mKeepCardConnectionAlive; virtual void run() = 0; - [[nodiscard]] bool isStartStopEnabled() const; protected: explicit AbstractState(const QSharedPointer& pContext); void setAbortOnCardRemoved(); + void setHandleNfcStop(); void setKeepCardConnectionAlive(); void onEntry(QEvent* pEvent) override; @@ -75,8 +76,6 @@ class AbstractState void stopNfcScanIfNecessary(const QString& pError = QString()) const; public: - static const char* const cFORCE_START_STOP_SCAN; - ~AbstractState() override = default; [[nodiscard]] QString getStateName() const; @@ -87,6 +86,7 @@ class AbstractState private Q_SLOTS: void onAbort(const FailureCode& pFailure) const; + void onReaderStatusChanged(const ReaderManagerPluginInfo& pInfo) const; public Q_SLOTS: void onStateApprovedChanged(bool pApproved); diff --git a/src/workflows/base/states/CompositeStatePace.cpp b/src/workflows/base/states/CompositeStatePace.cpp index f76275cf8..f29395f87 100644 --- a/src/workflows/base/states/CompositeStatePace.cpp +++ b/src/workflows/base/states/CompositeStatePace.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "CompositeStatePace.h" #include "context/WorkflowContext.h" #include "states/StateBuilder.h" +#include "states/StateCheckError.h" #include "states/StateClearPacePasswords.h" #include "states/StateConnectCard.h" #include "states/StateDestroyPace.h" @@ -13,11 +14,13 @@ #include "states/StateEstablishPaceChannel.h" #include "states/StateMaintainCardConnection.h" #include "states/StatePreparePace.h" +#include "states/StateResetRetryCounter.h" #include "states/StateSelectReader.h" #include "states/StateUnfortunateCardPosition.h" #include "states/StateUpdateRetryCounter.h" #include "states/StateVerifyRetryCounter.h" + using namespace governikus; @@ -25,83 +28,91 @@ CompositeStatePace::CompositeStatePace(const QSharedPointer& pC : QState() , mContext(pContext) { - auto sMaintainCardConnection = StateBuilder::createState(mContext); - auto sClearPacePasswordsOnError = StateBuilder::createState(mContext); - auto sSelectReader = StateBuilder::createState(mContext); - auto sConnectCard = StateBuilder::createState(mContext); - auto sUpdateRetryCounter = StateBuilder::createState(mContext); - auto sVerifyRetryCounter = StateBuilder::createState(mContext); - auto sPreparePace = StateBuilder::createState(mContext); - auto sUnfortunateCardPosition = StateBuilder::createState(mContext); - auto sEnterPacePassword = StateBuilder::createState(mContext); - auto sEstablishPaceChannel = StateBuilder::createState(mContext); - auto sClearPacePasswordsBeforeDestroy = StateBuilder::createState(mContext); - auto sDestroyPace = StateBuilder::createState(mContext); + auto* sMaintainCardConnection = StateBuilder::createState(mContext); + auto* sSelectReader = StateBuilder::createState(mContext); + auto* sConnectCard = StateBuilder::createState(mContext); + auto* sUpdateRetryCounter = StateBuilder::createState(mContext); + auto* sVerifyRetryCounter = StateBuilder::createState(mContext); + auto* sPreparePace = StateBuilder::createState(mContext); + auto* sEnterPacePassword = StateBuilder::createState(mContext); + auto* sEstablishPaceChannel = StateBuilder::createState(mContext); + auto* sUnfortunateCardPosition = StateBuilder::createState(mContext); + auto* sResetRetryCounter = StateBuilder::createState(mContext); + auto* sDestroyPace = StateBuilder::createState(mContext); + auto* sClearPacePasswords = StateBuilder::createState(mContext); + auto* sCheckError = StateBuilder::createState(mContext); sMaintainCardConnection->setParent(this); - sClearPacePasswordsOnError->setParent(this); sSelectReader->setParent(this); sConnectCard->setParent(this); sUpdateRetryCounter->setParent(this); sVerifyRetryCounter->setParent(this); sPreparePace->setParent(this); - sUnfortunateCardPosition->setParent(this); sEnterPacePassword->setParent(this); sEstablishPaceChannel->setParent(this); - sClearPacePasswordsBeforeDestroy->setParent(this); + sUnfortunateCardPosition->setParent(this); + sResetRetryCounter->setParent(this); sDestroyPace->setParent(this); + sClearPacePasswords->setParent(this); + sCheckError->setParent(this); setInitialState(sMaintainCardConnection); sMaintainCardConnection->addTransition(sMaintainCardConnection, &AbstractState::fireContinue, sVerifyRetryCounter); - sMaintainCardConnection->addTransition(sMaintainCardConnection, &AbstractState::fireAbort, sClearPacePasswordsOnError); - sMaintainCardConnection->addTransition(sMaintainCardConnection, &StateMaintainCardConnection::firePropagateAbort, sClearPacePasswordsOnError); + sMaintainCardConnection->addTransition(sMaintainCardConnection, &AbstractState::fireAbort, sClearPacePasswords); sMaintainCardConnection->addTransition(sMaintainCardConnection, &StateMaintainCardConnection::fireNoCardConnection, sSelectReader); sMaintainCardConnection->addTransition(sMaintainCardConnection, &StateMaintainCardConnection::fireForceUpdateRetryCounter, sUpdateRetryCounter); - connect(sClearPacePasswordsOnError, &AbstractState::fireContinue, this, &CompositeStatePace::firePropagateAbort); - connect(sClearPacePasswordsOnError, &AbstractState::fireAbort, this, &CompositeStatePace::fireAbort); - sSelectReader->addTransition(sSelectReader, &AbstractState::fireContinue, sConnectCard); - sSelectReader->addTransition(sSelectReader, &AbstractState::fireAbort, sMaintainCardConnection); + sSelectReader->addTransition(sSelectReader, &AbstractState::fireAbort, sClearPacePasswords); sSelectReader->addTransition(sSelectReader, &StateSelectReader::fireRetry, sSelectReader); sConnectCard->addTransition(sConnectCard, &AbstractState::fireContinue, sUpdateRetryCounter); - sConnectCard->addTransition(sConnectCard, &AbstractState::fireAbort, sMaintainCardConnection); + sConnectCard->addTransition(sConnectCard, &AbstractState::fireAbort, sClearPacePasswords); sConnectCard->addTransition(sConnectCard, &StateConnectCard::fireRetry, sSelectReader); sUpdateRetryCounter->addTransition(sUpdateRetryCounter, &AbstractState::fireContinue, sVerifyRetryCounter); - sUpdateRetryCounter->addTransition(sUpdateRetryCounter, &AbstractState::fireAbort, sMaintainCardConnection); + sUpdateRetryCounter->addTransition(sUpdateRetryCounter, &AbstractState::fireAbort, sClearPacePasswords); sUpdateRetryCounter->addTransition(sUpdateRetryCounter, &StateUpdateRetryCounter::fireNoCardConnection, sMaintainCardConnection); sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &AbstractState::fireContinue, sPreparePace); - sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &AbstractState::fireAbort, sMaintainCardConnection); + sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &AbstractState::fireAbort, sClearPacePasswords); sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &StateVerifyRetryCounter::fireNoCardConnection, sMaintainCardConnection); + sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &StateVerifyRetryCounter::fireReaderOrCardChanged, sClearPacePasswords); - sPreparePace->addTransition(sPreparePace, &AbstractState::fireContinue, sMaintainCardConnection); - sPreparePace->addTransition(sPreparePace, &AbstractState::fireAbort, sMaintainCardConnection); + sPreparePace->addTransition(sPreparePace, &AbstractState::fireContinue, sEstablishPaceChannel); + sPreparePace->addTransition(sPreparePace, &AbstractState::fireAbort, sClearPacePasswords); sPreparePace->addTransition(sPreparePace, &StatePreparePace::fireNoCardConnection, sMaintainCardConnection); sPreparePace->addTransition(sPreparePace, &StatePreparePace::fireEnterPacePassword, sEnterPacePassword); - sPreparePace->addTransition(sPreparePace, &StatePreparePace::fireEstablishPaceChannel, sEstablishPaceChannel); sEnterPacePassword->addTransition(sEnterPacePassword, &AbstractState::fireContinue, sEstablishPaceChannel); - sEnterPacePassword->addTransition(sEnterPacePassword, &AbstractState::fireAbort, sMaintainCardConnection); - sEnterPacePassword->addTransition(sEnterPacePassword, &StateEnterPacePassword::firePropagateAbort, sMaintainCardConnection); + sEnterPacePassword->addTransition(sEnterPacePassword, &AbstractState::fireAbort, sClearPacePasswords); - sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &AbstractState::fireContinue, sMaintainCardConnection); + connect(sEstablishPaceChannel, &AbstractState::fireContinue, this, &CompositeStatePace::fireContinue); + sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::firePaceCanEstablished, sMaintainCardConnection); + sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::firePacePukEstablished, sResetRetryCounter); + sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &AbstractState::fireAbort, sClearPacePasswords); sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::fireNoCardConnection, sMaintainCardConnection); - sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &AbstractState::fireAbort, sMaintainCardConnection); sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::firePaceChannelFailed, sMaintainCardConnection); - connect(sEstablishPaceChannel, &StateEstablishPaceChannel::firePaceChannelEstablished, this, &CompositeStatePace::fireContinue); - sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::firePaceChannelInoperative, sClearPacePasswordsBeforeDestroy); + sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::fireWrongPassword, sClearPacePasswords); + sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::fireThirdPinAttemptFailed, sDestroyPace); sEstablishPaceChannel->addTransition(sEstablishPaceChannel, &StateEstablishPaceChannel::fireAbortAndUnfortunateCardPosition, sUnfortunateCardPosition); sUnfortunateCardPosition->addTransition(sUnfortunateCardPosition, &AbstractState::fireContinue, sMaintainCardConnection); - sUnfortunateCardPosition->addTransition(sUnfortunateCardPosition, &AbstractState::fireAbort, sMaintainCardConnection); + sUnfortunateCardPosition->addTransition(sUnfortunateCardPosition, &AbstractState::fireAbort, sClearPacePasswords); + + sResetRetryCounter->addTransition(sResetRetryCounter, &AbstractState::fireAbort, sDestroyPace); + sResetRetryCounter->addTransition(sResetRetryCounter, &AbstractState::fireContinue, sDestroyPace); + sResetRetryCounter->addTransition(sResetRetryCounter, &StateResetRetryCounter::fireNoCardConnection, sMaintainCardConnection); + + sDestroyPace->addTransition(sDestroyPace, &AbstractState::fireContinue, sClearPacePasswords); + sDestroyPace->addTransition(sDestroyPace, &AbstractState::fireAbort, sClearPacePasswords); + + sClearPacePasswords->addTransition(sClearPacePasswords, &AbstractState::fireContinue, sCheckError); + sClearPacePasswords->addTransition(sClearPacePasswords, &AbstractState::fireAbort, sCheckError); - sClearPacePasswordsBeforeDestroy->addTransition(sClearPacePasswordsBeforeDestroy, &AbstractState::fireContinue, sDestroyPace); - sClearPacePasswordsBeforeDestroy->addTransition(sClearPacePasswordsBeforeDestroy, &AbstractState::fireAbort, sDestroyPace); + sCheckError->addTransition(sCheckError, &AbstractState::fireContinue, sMaintainCardConnection); + connect(sCheckError, &AbstractState::fireAbort, this, &CompositeStatePace::fireAbort); + connect(sCheckError, &StateCheckError::firePropagateAbort, this, &CompositeStatePace::firePropagateAbort); - sDestroyPace->addTransition(sDestroyPace, &AbstractState::fireContinue, sMaintainCardConnection); - connect(sDestroyPace, &AbstractState::fireAbort, this, &CompositeStatePace::fireAbort); } diff --git a/src/workflows/base/states/CompositeStatePace.h b/src/workflows/base/states/CompositeStatePace.h index 5c972db03..fa6994a60 100644 --- a/src/workflows/base/states/CompositeStatePace.h +++ b/src/workflows/base/states/CompositeStatePace.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.cpp b/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.cpp index dffb31bcc..5fd60f38a 100644 --- a/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.cpp +++ b/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "CompositeStateProcessCvcsAndSetRights.h" @@ -20,11 +20,11 @@ CompositeStateProcessCvcsAndSetRights::CompositeStateProcessCvcsAndSetRights(con : QState() , mContext(pContext) { - auto sExtractCvcsFromEac1InputType = StateBuilder::createState(mContext); - auto sPreVerification = StateBuilder::createState(mContext); - auto sCertificateDescriptionCheck = StateBuilder::createState(mContext); - auto sCheckCertificates = StateBuilder::createState(mContext); - auto sEditAccessRights = StateBuilder::createState(mContext); + auto* sExtractCvcsFromEac1InputType = StateBuilder::createState(mContext); + auto* sPreVerification = StateBuilder::createState(mContext); + auto* sCertificateDescriptionCheck = StateBuilder::createState(mContext); + auto* sCheckCertificates = StateBuilder::createState(mContext); + auto* sEditAccessRights = StateBuilder::createState(mContext); sExtractCvcsFromEac1InputType->setParent(this); sPreVerification->setParent(this); diff --git a/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.h b/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.h index b608028d3..d4d05104a 100644 --- a/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.h +++ b/src/workflows/base/states/CompositeStateProcessCvcsAndSetRights.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/CompositeStateTrustedChannel.cpp b/src/workflows/base/states/CompositeStateTrustedChannel.cpp index 40f1035d0..45a6db855 100644 --- a/src/workflows/base/states/CompositeStateTrustedChannel.cpp +++ b/src/workflows/base/states/CompositeStateTrustedChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CompositeStateTrustedChannel.h" @@ -30,27 +30,27 @@ CompositeStateTrustedChannel::CompositeStateTrustedChannel(const QSharedPointer< : QState() , mContext(pContext) { - auto sGetTcToken = StateBuilder::createState(mContext); - auto sStartPaos = StateBuilder::createState(mContext); - auto sSendStartPaos = StateBuilder::createState(mContext); - auto sInitializeFramework = StateBuilder::createState(mContext); - auto sSendInitializeFrameworkResponse = StateBuilder::createState(mContext); - auto sProcessCvcsAndSetRights = new CompositeStateProcessCvcsAndSetRights(mContext); - auto sStatePace = new CompositeStatePace(mContext); - auto sDidAuthenticateEac1 = StateBuilder::createState(mContext); - auto sSendDidAuthenticateResponseEac1 = StateBuilder::createState(mContext); - auto sEacAdditionalInputType = StateBuilder::createState(mContext); - auto sSendDidAuthenticatResponseEacAdditionalInput = StateBuilder::createState(mContext); - auto sProcessCertificatesFromEac2 = StateBuilder::createState(mContext); - auto sDidAuthenticateEac2 = StateBuilder::createState(mContext); - auto sSendDidAuthenticateResponseEac2 = StateBuilder::createState(mContext); - auto sTransmit = StateBuilder::createState(mContext); - auto sSendTransmitResponse = StateBuilder::createState(mContext); - auto sDestroyPace = StateBuilder::createState(mContext); - auto sClearPacePasswords = StateBuilder::createState(mContext); - auto sUpdateRetryCounterFinal = StateBuilder::createState(mContext); - auto sCleanUpReaderManager = StateBuilder::createState(mContext); - auto sStartPaosResponse = StateBuilder::createState(mContext); + auto* sGetTcToken = StateBuilder::createState(mContext); + auto* sStartPaos = StateBuilder::createState(mContext); + auto* sSendStartPaos = StateBuilder::createState(mContext); + auto* sInitializeFramework = StateBuilder::createState(mContext); + auto* sSendInitializeFrameworkResponse = StateBuilder::createState(mContext); + auto* sProcessCvcsAndSetRights = new CompositeStateProcessCvcsAndSetRights(mContext); + auto* sStatePace = new CompositeStatePace(mContext); + auto* sDidAuthenticateEac1 = StateBuilder::createState(mContext); + auto* sSendDidAuthenticateResponseEac1 = StateBuilder::createState(mContext); + auto* sEacAdditionalInputType = StateBuilder::createState(mContext); + auto* sSendDidAuthenticatResponseEacAdditionalInput = StateBuilder::createState(mContext); + auto* sProcessCertificatesFromEac2 = StateBuilder::createState(mContext); + auto* sDidAuthenticateEac2 = StateBuilder::createState(mContext); + auto* sSendDidAuthenticateResponseEac2 = StateBuilder::createState(mContext); + auto* sTransmit = StateBuilder::createState(mContext); + auto* sSendTransmitResponse = StateBuilder::createState(mContext); + auto* sDestroyPace = StateBuilder::createState(mContext); + auto* sClearPacePasswords = StateBuilder::createState(mContext); + auto* sUpdateRetryCounterFinal = StateBuilder::createState(mContext); + auto* sCleanUpReaderManager = StateBuilder::createState(mContext); + auto* sStartPaosResponse = StateBuilder::createState(mContext); sGetTcToken->setParent(this); sStartPaos->setParent(this); diff --git a/src/workflows/base/states/CompositeStateTrustedChannel.h b/src/workflows/base/states/CompositeStateTrustedChannel.h index daeb6bbeb..e7bb1d16d 100644 --- a/src/workflows/base/states/CompositeStateTrustedChannel.h +++ b/src/workflows/base/states/CompositeStateTrustedChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/FinalState.cpp b/src/workflows/base/states/FinalState.cpp index cb462300e..f96114e55 100644 --- a/src/workflows/base/states/FinalState.cpp +++ b/src/workflows/base/states/FinalState.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "states/FinalState.h" @@ -21,7 +21,7 @@ void FinalState::run() addTransition(this, &AbstractState::fireAbort, sStopMachine); // Clear plugin types and disconnect all readers when the workflow has completed. - getContext()->setReaderPlugInTypes({}); + getContext()->setReaderPluginTypes({}); Q_EMIT fireContinue(); } diff --git a/src/workflows/base/states/FinalState.h b/src/workflows/base/states/FinalState.h index fe5e9fd3f..02480dd95 100644 --- a/src/workflows/base/states/FinalState.h +++ b/src/workflows/base/states/FinalState.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/GenericContextContainer.h b/src/workflows/base/states/GenericContextContainer.h index 379d9c465..8468ae573 100644 --- a/src/workflows/base/states/GenericContextContainer.h +++ b/src/workflows/base/states/GenericContextContainer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateActivateStoreFeedbackDialog.cpp b/src/workflows/base/states/StateActivateStoreFeedbackDialog.cpp index 60b7e53c8..c677e5ec1 100644 --- a/src/workflows/base/states/StateActivateStoreFeedbackDialog.cpp +++ b/src/workflows/base/states/StateActivateStoreFeedbackDialog.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "StateActivateStoreFeedbackDialog.h" diff --git a/src/workflows/base/states/StateActivateStoreFeedbackDialog.h b/src/workflows/base/states/StateActivateStoreFeedbackDialog.h index 68d20d24a..c26e11ff0 100644 --- a/src/workflows/base/states/StateActivateStoreFeedbackDialog.h +++ b/src/workflows/base/states/StateActivateStoreFeedbackDialog.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/workflows/base/states/StateBuilder.cpp b/src/workflows/base/states/StateBuilder.cpp index 397ce328e..9ef01340a 100644 --- a/src/workflows/base/states/StateBuilder.cpp +++ b/src/workflows/base/states/StateBuilder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateBuilder.h" diff --git a/src/workflows/base/states/StateBuilder.h b/src/workflows/base/states/StateBuilder.h index bd6199c06..e012062f1 100644 --- a/src/workflows/base/states/StateBuilder.h +++ b/src/workflows/base/states/StateBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -34,7 +34,7 @@ class StateBuilder template - static bool isState(const QString& pState) + [[nodiscard]] static bool isState(const QString& pState) { return pState == generateStateName(); } @@ -43,7 +43,7 @@ class StateBuilder template static T* createState(const QSharedPointer& pContext) { - auto state = new T(pContext); + auto* state = new T(pContext); state->setObjectName(getUnqualifiedClassName(state->metaObject()->className())); return state; } diff --git a/src/workflows/base/states/StateCertificateDescriptionCheck.cpp b/src/workflows/base/states/StateCertificateDescriptionCheck.cpp index ebe36e885..7ac32e05d 100644 --- a/src/workflows/base/states/StateCertificateDescriptionCheck.cpp +++ b/src/workflows/base/states/StateCertificateDescriptionCheck.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCertificateDescriptionCheck.h" @@ -46,7 +46,7 @@ void StateCertificateDescriptionCheck::run() QCryptographicHash hashCalculator(terminalCertificate->getBody().getHashAlgorithm()); hashCalculator.addData(getContext()->getDidAuthenticateEac1()->getCertificateDescriptionAsBinary()); - const QByteArray& hashOfDescription = terminalCertificate->getBody().getExtensions().value(KnownOid::ID_DESCRIPTION); + const QByteArray& hashOfDescription = terminalCertificate->getBody().getExtension(KnownOid::ID_DESCRIPTION); if (hashCalculator.result() != hashOfDescription) { auto certificateHashError = QStringLiteral("The certificate description does not match the certificate."); diff --git a/src/workflows/base/states/StateCertificateDescriptionCheck.h b/src/workflows/base/states/StateCertificateDescriptionCheck.h index 6dd56b0b6..9edbf02dc 100644 --- a/src/workflows/base/states/StateCertificateDescriptionCheck.h +++ b/src/workflows/base/states/StateCertificateDescriptionCheck.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateChangePin.cpp b/src/workflows/base/states/StateChangePin.cpp index b8ad509e1..2707b1e14 100644 --- a/src/workflows/base/states/StateChangePin.cpp +++ b/src/workflows/base/states/StateChangePin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateChangePin.h" @@ -45,9 +45,8 @@ void StateChangePin::onSetEidPinDone(QSharedPointer pCommand) } const auto& context = getContext(); - const CardReturnCode returnCode = command->getReturnCode(); - context->setLastPaceResult(returnCode); - switch (returnCode) + const auto cardReturnCode = command->getReturnCode(); + switch (cardReturnCode) { case CardReturnCode::OK: switch (command->getResponseApdu().getStatusCode()) @@ -94,17 +93,24 @@ void StateChangePin::onSetEidPinDone(QSharedPointer pCommand) return; case CardReturnCode::CANCELLATION_BY_USER: - updateStatus(CardReturnCodeUtil::toGlobalStatus(returnCode)); + updateStatus(CardReturnCodeUtil::toGlobalStatus(cardReturnCode)); Q_EMIT fireAbort(FailureCode::Reason::Change_Pin_Card_User_Cancelled); break; case CardReturnCode::NEW_PIN_MISMATCH: - updateStatus(CardReturnCodeUtil::toGlobalStatus(returnCode)); + updateStatus(CardReturnCodeUtil::toGlobalStatus(cardReturnCode)); Q_EMIT fireAbort(FailureCode::Reason::Change_Pin_Card_New_Pin_Mismatch); break; + case CardReturnCode::CARD_NOT_FOUND: + case CardReturnCode::RESPONSE_EMPTY: + context->resetCardConnection(); + Q_EMIT fireNoCardConnection(); + break; + default: - Q_EMIT fireRetry(); + updateStatus(CardReturnCodeUtil::toGlobalStatus(cardReturnCode)); + Q_EMIT fireAbort(FailureCode::Reason::Change_Pin_Unrecoverable); break; } } diff --git a/src/workflows/base/states/StateChangePin.h b/src/workflows/base/states/StateChangePin.h index 09864dad6..956029253 100644 --- a/src/workflows/base/states/StateChangePin.h +++ b/src/workflows/base/states/StateChangePin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -33,7 +33,7 @@ class StateChangePin void onSetEidPinDone(QSharedPointer pCommand); Q_SIGNALS: - void fireRetry(); + void fireNoCardConnection(); }; } // namespace governikus diff --git a/src/workflows/base/states/StateCheckCertificates.cpp b/src/workflows/base/states/StateCheckCertificates.cpp index ecdec4329..01a12aa9c 100644 --- a/src/workflows/base/states/StateCheckCertificates.cpp +++ b/src/workflows/base/states/StateCheckCertificates.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCheckCertificates.h" @@ -38,8 +38,10 @@ void StateCheckCertificates::run() else { qCritical() << certificateDescError; - const auto& issuerName = TlsChecker::getCertificateIssuerName(certificate); - updateStatus({GlobalStatus::Code::Workflow_TrustedChannel_Hash_Not_In_Description, {GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, issuerName} + updateStatus({GlobalStatus::Code::Workflow_TrustedChannel_Hash_Not_In_Description, + { + GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, certificate.issuerDisplayName() + } }); Q_EMIT fireAbort(FailureCode::Reason::Certificate_Check_Failed_Hash_Missing_In_Description); return; diff --git a/src/workflows/base/states/StateCheckCertificates.h b/src/workflows/base/states/StateCheckCertificates.h index d738e1358..30c987ba2 100644 --- a/src/workflows/base/states/StateCheckCertificates.h +++ b/src/workflows/base/states/StateCheckCertificates.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateCheckError.cpp b/src/workflows/base/states/StateCheckError.cpp index e651325e5..ece060acd 100644 --- a/src/workflows/base/states/StateCheckError.cpp +++ b/src/workflows/base/states/StateCheckError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateCheckError.h" @@ -15,7 +15,7 @@ StateCheckError::StateCheckError(const QSharedPointer& pContext void StateCheckError::run() { - if (getContext()->getStatus().isNoError() || getContext()->isErrorReportedToUser()) + if (getContext()->getStatus().isNoError()) { Q_EMIT fireContinue(); return; diff --git a/src/workflows/base/states/StateCheckError.h b/src/workflows/base/states/StateCheckError.h index d9f0e6dce..61949aaf3 100644 --- a/src/workflows/base/states/StateCheckError.h +++ b/src/workflows/base/states/StateCheckError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,14 +11,14 @@ #include "AbstractState.h" #include "GenericContextContainer.h" -#include "context/AuthContext.h" +#include "context/WorkflowContext.h" namespace governikus { class StateCheckError : public AbstractState - , public GenericContextContainer + , public GenericContextContainer { Q_OBJECT friend class StateBuilder; diff --git a/src/workflows/base/states/StateCheckRefreshAddress.cpp b/src/workflows/base/states/StateCheckRefreshAddress.cpp index c99dc9821..273084347 100644 --- a/src/workflows/base/states/StateCheckRefreshAddress.cpp +++ b/src/workflows/base/states/StateCheckRefreshAddress.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCheckRefreshAddress.h" @@ -8,7 +8,6 @@ #include "CertificateChecker.h" #include "LogHandler.h" #include "NetworkManager.h" -#include "StateRedirectBrowser.h" #include "TlsChecker.h" #include "UrlUtil.h" @@ -179,7 +178,7 @@ void StateCheckRefreshAddress::onSslErrors(const QList& pErrors) } -void StateCheckRefreshAddress::reportCommunicationError(const GlobalStatus& pStatus, FailureCode::Reason pFailure, const QString& pErrorString) +void StateCheckRefreshAddress::reportCommunicationError(const GlobalStatus& pStatus, const FailureCode& pFailure) { qCritical() << pStatus; updateStatus(pStatus); @@ -187,14 +186,7 @@ void StateCheckRefreshAddress::reportCommunicationError(const GlobalStatus& pSta clearConnections(); mReply->abort(); - if (pErrorString.isEmpty()) - { - Q_EMIT fireAbort(pFailure); - return; - } - - Q_EMIT fireAbort({pFailure, {FailureCode::Info::Network_Error, mReply->errorString()} - }); + Q_EMIT fireAbort(pFailure); } @@ -217,8 +209,9 @@ bool StateCheckRefreshAddress::checkSslConnectionAndSaveCertificate(const QSslCo if (!TlsChecker::hasValidEphemeralKeyLength(pSslConfiguration.ephemeralServerKey())) { + const auto& map = TlsChecker::getEphemeralKeyInfoMap(pSslConfiguration.ephemeralServerKey()); reportCommunicationError({GlobalStatus::Code::Workflow_Network_Ssl_Connection_Unsupported_Algorithm_Or_Length, infoMap}, - FailureCode::Reason::Check_Refresh_Address_Invalid_Ephemeral_Key_Length); + {FailureCode::Reason::Check_Refresh_Address_Invalid_Ephemeral_Key_Length, map}); return false; } @@ -229,7 +222,7 @@ bool StateCheckRefreshAddress::checkSslConnectionAndSaveCertificate(const QSslCo return true; } - infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, TlsChecker::getCertificateIssuerName(pSslConfiguration.peerCertificate())); + infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, pSslConfiguration.peerCertificate().issuerDisplayName()); switch (statusCode) { case CertificateChecker::CertificateStatus::Good: @@ -255,41 +248,45 @@ void StateCheckRefreshAddress::onNetworkReply() const auto statusCode = NetworkManager::getLoggedStatusCode(mReply, spawnMessageLogger(network)); if (mReply->error() != QNetworkReply::NoError) { + const FailureCode::FailureInfoMap infoMap { + {FailureCode::Info::Network_Error, mReply->errorString()} + }; + switch (NetworkManager::toNetworkError(mReply)) { case NetworkManager::NetworkError::ServiceUnavailable: reportCommunicationError({GlobalStatus::Code::Network_ServiceUnavailable, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Service_Unavailable, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Service_Unavailable, infoMap}); break; case NetworkManager::NetworkError::ServerError: reportCommunicationError({GlobalStatus::Code::Network_ServerError, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Server_Error, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Server_Error, infoMap}); break; case NetworkManager::NetworkError::ClientError: reportCommunicationError({GlobalStatus::Code::Network_ClientError, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Client_Error, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Client_Error, infoMap}); break; case NetworkManager::NetworkError::TimeOut: reportCommunicationError({GlobalStatus::Code::Network_TimeOut, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Service_Timeout, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Service_Timeout, infoMap}); break; case NetworkManager::NetworkError::ProxyError: reportCommunicationError({GlobalStatus::Code::Network_Proxy_Error, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Proxy_Error, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Proxy_Error, infoMap}); break; case NetworkManager::NetworkError::SecurityError: reportCommunicationError({GlobalStatus::Code::Network_Ssl_Establishment_Error, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Fatal_Tls_Error_After_Reply, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Fatal_Tls_Error_After_Reply, infoMap}); break; case NetworkManager::NetworkError::OtherError: reportCommunicationError({GlobalStatus::Code::Network_Other_Error, {GlobalStatus::ExternalInformation::LAST_URL, mUrl.toString()} - }, FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error, mReply->errorString()); + }, {FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error, infoMap}); break; } return; @@ -395,7 +392,7 @@ void StateCheckRefreshAddress::fetchServerCertificate() // // "...This means that you are only guaranteed to receive this signal for the first connection to a site in the lifespan of the QNetworkAccessManager." Env::getSingleton()->clearConnections(); - mReply = Env::getSingleton()->get(request); + mReply = Env::getSingleton()->head(request); *this << connect(mReply.data(), &QNetworkReply::encrypted, this, &StateCheckRefreshAddress::onSslHandshakeDoneFetchingServerCertificate); *this << connect(mReply.data(), &QNetworkReply::sslErrors, this, &StateCheckRefreshAddress::onSslErrors); diff --git a/src/workflows/base/states/StateCheckRefreshAddress.h b/src/workflows/base/states/StateCheckRefreshAddress.h index 469659d65..7aba98b8c 100644 --- a/src/workflows/base/states/StateCheckRefreshAddress.h +++ b/src/workflows/base/states/StateCheckRefreshAddress.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -37,7 +37,7 @@ class StateCheckRefreshAddress QUrl mUrl; QUrl mSubjectUrl; bool mCertificateFetched; - QVector mVerifiedRefreshUrlHosts; + QList mVerifiedRefreshUrlHosts; explicit StateCheckRefreshAddress(const QSharedPointer& pContext); @@ -50,7 +50,7 @@ class StateCheckRefreshAddress void fetchServerCertificate(); bool checkSslConnectionAndSaveCertificate(const QSslConfiguration& pSslConfiguration); void doneSuccess(); - void reportCommunicationError(const GlobalStatus& pStatus, FailureCode::Reason pFailure, const QString& pErrorString = QString()); + void reportCommunicationError(const GlobalStatus& pStatus, const FailureCode& pFailure); private Q_SLOTS: void onSslHandshakeDone(); diff --git a/src/workflows/base/states/StateCleanUpReaderManager.cpp b/src/workflows/base/states/StateCleanUpReaderManager.cpp index 039f85c00..a4149a77a 100644 --- a/src/workflows/base/states/StateCleanUpReaderManager.cpp +++ b/src/workflows/base/states/StateCleanUpReaderManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCleanUpReaderManager.h" @@ -38,12 +38,12 @@ void StateCleanUpReaderManager::run() context->rememberReader(); const auto& status = context->getStatus(); - const auto readerManager = Env::getSingleton(); - const auto volatileSettings = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); + const auto* volatileSettings = Env::getSingleton(); if (volatileSettings->isUsedAsSDK()) { #ifdef Q_OS_IOS - readerManager->stopScan(ReaderManagerPlugInType::NFC, status.isError() ? volatileSettings->getMessages().getSessionFailed() : QString()); + readerManager->stopScan(ReaderManagerPluginType::NFC, status.isError() ? volatileSettings->getMessages().getSessionFailed() : QString()); #endif readerManager->shelve(); } @@ -52,7 +52,7 @@ void StateCleanUpReaderManager::run() readerManager->stopScanAll(status.isError() ? status.toErrorDescription(true) : QString()); } #ifdef Q_OS_IOS - readerManager->reset(ReaderManagerPlugInType::NFC); + readerManager->reset(ReaderManagerPluginType::NFC); #endif Q_EMIT fireContinue(); diff --git a/src/workflows/base/states/StateCleanUpReaderManager.h b/src/workflows/base/states/StateCleanUpReaderManager.h index 6768bbcbc..90b80b45a 100644 --- a/src/workflows/base/states/StateCleanUpReaderManager.h +++ b/src/workflows/base/states/StateCleanUpReaderManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateClearPacePasswords.cpp b/src/workflows/base/states/StateClearPacePasswords.cpp index da49a8aa4..3c040c5df 100644 --- a/src/workflows/base/states/StateClearPacePasswords.cpp +++ b/src/workflows/base/states/StateClearPacePasswords.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateClearPacePasswords.h" diff --git a/src/workflows/base/states/StateClearPacePasswords.h b/src/workflows/base/states/StateClearPacePasswords.h index 03eda56ce..79b0a524c 100644 --- a/src/workflows/base/states/StateClearPacePasswords.h +++ b/src/workflows/base/states/StateClearPacePasswords.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateConnectCard.cpp b/src/workflows/base/states/StateConnectCard.cpp index 28f7f87f5..2c7feae6e 100644 --- a/src/workflows/base/states/StateConnectCard.cpp +++ b/src/workflows/base/states/StateConnectCard.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "StateConnectCard.h" #include "CardConnection.h" #include "ReaderManager.h" -#include "SurveyModel.h" +#include "Survey.h" #include "VolatileSettings.h" #include @@ -24,7 +24,7 @@ StateConnectCard::StateConnectCard(const QSharedPointer& pConte void StateConnectCard::run() { - const auto readerManager = Env::getSingleton(); + const auto* readerManager = Env::getSingleton(); *this << connect(readerManager, &ReaderManager::fireCardInserted, this, &StateConnectCard::onCardInserted); *this << connect(readerManager, &ReaderManager::fireCardRemoved, this, &StateConnectCard::onUnusableCardConnectionLost); *this << connect(readerManager, &ReaderManager::fireReaderRemoved, this, &StateConnectCard::onUnusableCardConnectionLost); @@ -34,9 +34,9 @@ void StateConnectCard::run() void StateConnectCard::onCardInserted() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); ReaderInfo readerInfo = readerManager->getReaderInfo(getContext()->getReaderName()); - Env::getSingleton()->setReaderInfo(readerInfo); + Env::getSingleton()->setReaderInfo(readerInfo); if (readerInfo.hasEid()) { @@ -64,17 +64,12 @@ void StateConnectCard::onCommandDone(QSharedPointer context->setCardConnection(cardConnection); const auto& readerInfo = cardConnection->getReaderInfo(); - if (readerInfo.insufficientApduLength()) - { - //: INFO IOS - context->getCardConnection()->setProgressMessage(tr("The used card reader does not meet the technical requirements (Extended Length not supported).")); - return; - } + Q_ASSERT(!readerInfo.insufficientApduLength()); if (context->eidTypeMismatch()) { //: INFO IOS - context->getCardConnection()->setProgressMessage(tr("The used ID card type is not accepted by the server.")); + context->getCardConnection()->setErrorMessage(tr("The used ID card type is not accepted by the server.")); return; } @@ -84,7 +79,7 @@ void StateConnectCard::onCommandDone(QSharedPointer const GlobalStatus status = GlobalStatus::Code::Card_Pin_Deactivated; if (Env::getSingleton()->isUsedAsSDK()) { - context->getCardConnection()->setProgressMessage(status.toErrorDescription()); + context->getCardConnection()->setErrorMessage(status.toErrorDescription()); } else { @@ -120,5 +115,5 @@ void StateConnectCard::onEntry(QEvent* pEvent) * Note: the plugin types to be used in this state must be already set in the workflow context before this state is entered. * Changing the plugin types in the context, e.g. from {NFC} to {REMOTE}, causes the state to be left with a fireRetry signal. */ - *this << connect(context, &WorkflowContext::fireReaderPlugInTypesChanged, this, &StateConnectCard::fireRetry); + *this << connect(context, &WorkflowContext::fireReaderPluginTypesChanged, this, &StateConnectCard::fireRetry); } diff --git a/src/workflows/base/states/StateConnectCard.h b/src/workflows/base/states/StateConnectCard.h index 0c6f06419..97d843bb0 100644 --- a/src/workflows/base/states/StateConnectCard.h +++ b/src/workflows/base/states/StateConnectCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateDestroyPace.cpp b/src/workflows/base/states/StateDestroyPace.cpp index 292cdd01d..2abcf0021 100644 --- a/src/workflows/base/states/StateDestroyPace.cpp +++ b/src/workflows/base/states/StateDestroyPace.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ diff --git a/src/workflows/base/states/StateDestroyPace.h b/src/workflows/base/states/StateDestroyPace.h index fbd75fb41..d6ad42c3e 100644 --- a/src/workflows/base/states/StateDestroyPace.h +++ b/src/workflows/base/states/StateDestroyPace.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateDidAuthenticateEac1.cpp b/src/workflows/base/states/StateDidAuthenticateEac1.cpp index 65a44eb31..d78b458d0 100644 --- a/src/workflows/base/states/StateDidAuthenticateEac1.cpp +++ b/src/workflows/base/states/StateDidAuthenticateEac1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateDidAuthenticateEac1.h" diff --git a/src/workflows/base/states/StateDidAuthenticateEac1.h b/src/workflows/base/states/StateDidAuthenticateEac1.h index 40a5e0dda..944edd281 100644 --- a/src/workflows/base/states/StateDidAuthenticateEac1.h +++ b/src/workflows/base/states/StateDidAuthenticateEac1.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateDidAuthenticateEac2.cpp b/src/workflows/base/states/StateDidAuthenticateEac2.cpp index 76cff0c3e..396b4bc88 100644 --- a/src/workflows/base/states/StateDidAuthenticateEac2.cpp +++ b/src/workflows/base/states/StateDidAuthenticateEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateDidAuthenticateEac2.h" diff --git a/src/workflows/base/states/StateDidAuthenticateEac2.h b/src/workflows/base/states/StateDidAuthenticateEac2.h index 8dc416043..679b4b97f 100644 --- a/src/workflows/base/states/StateDidAuthenticateEac2.h +++ b/src/workflows/base/states/StateDidAuthenticateEac2.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateEACAdditionalInputType.cpp b/src/workflows/base/states/StateEACAdditionalInputType.cpp index ae5baa80d..baa16ccb1 100644 --- a/src/workflows/base/states/StateEACAdditionalInputType.cpp +++ b/src/workflows/base/states/StateEACAdditionalInputType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateEACAdditionalInputType.h" diff --git a/src/workflows/base/states/StateEACAdditionalInputType.h b/src/workflows/base/states/StateEACAdditionalInputType.h index feb5b8494..02b3da618 100644 --- a/src/workflows/base/states/StateEACAdditionalInputType.h +++ b/src/workflows/base/states/StateEACAdditionalInputType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateEditAccessRights.cpp b/src/workflows/base/states/StateEditAccessRights.cpp index 055f6e133..92534ece5 100644 --- a/src/workflows/base/states/StateEditAccessRights.cpp +++ b/src/workflows/base/states/StateEditAccessRights.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEditAccessRights.h" diff --git a/src/workflows/base/states/StateEditAccessRights.h b/src/workflows/base/states/StateEditAccessRights.h index d92281ab6..b51acd3d9 100644 --- a/src/workflows/base/states/StateEditAccessRights.h +++ b/src/workflows/base/states/StateEditAccessRights.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateEnterNewPacePin.cpp b/src/workflows/base/states/StateEnterNewPacePin.cpp index c8660b793..21a926842 100644 --- a/src/workflows/base/states/StateEnterNewPacePin.cpp +++ b/src/workflows/base/states/StateEnterNewPacePin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEnterNewPacePin.h" @@ -13,6 +13,7 @@ StateEnterNewPacePin::StateEnterNewPacePin(const QSharedPointer , GenericContextContainer(pContext) { setKeepCardConnectionAlive(); + setHandleNfcStop(); } diff --git a/src/workflows/base/states/StateEnterNewPacePin.h b/src/workflows/base/states/StateEnterNewPacePin.h index 8be5c3973..584088f39 100644 --- a/src/workflows/base/states/StateEnterNewPacePin.h +++ b/src/workflows/base/states/StateEnterNewPacePin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateEnterPacePassword.cpp b/src/workflows/base/states/StateEnterPacePassword.cpp index 8811ae385..6ee9179fe 100644 --- a/src/workflows/base/states/StateEnterPacePassword.cpp +++ b/src/workflows/base/states/StateEnterPacePassword.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEnterPacePassword.h" @@ -15,20 +15,13 @@ StateEnterPacePassword::StateEnterPacePassword(const QSharedPointergetStatus().isError()) - { - Q_ASSERT(getContext()->getFailureCode().has_value()); - Q_EMIT firePropagateAbort(); - } - else - { - Q_EMIT fireContinue(); - } + Q_EMIT fireContinue(); } @@ -38,6 +31,7 @@ void StateEnterPacePassword::onEntry(QEvent* pEvent) { case CardReturnCode::OK: case CardReturnCode::OK_PUK: + case CardReturnCode::OK_CAN: stopNfcScanIfNecessary(); break; diff --git a/src/workflows/base/states/StateEnterPacePassword.h b/src/workflows/base/states/StateEnterPacePassword.h index f2743e14a..b97cc29d1 100644 --- a/src/workflows/base/states/StateEnterPacePassword.h +++ b/src/workflows/base/states/StateEnterPacePassword.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -27,9 +27,6 @@ class StateEnterPacePassword public: void onEntry(QEvent* pEvent) override; - - Q_SIGNALS: - void firePropagateAbort(); }; } // namespace governikus diff --git a/src/workflows/base/states/StateEstablishPaceChannel.cpp b/src/workflows/base/states/StateEstablishPaceChannel.cpp index acb2d2ffd..be3cac24a 100644 --- a/src/workflows/base/states/StateEstablishPaceChannel.cpp +++ b/src/workflows/base/states/StateEstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ @@ -127,7 +127,7 @@ void StateEstablishPaceChannel::onUserCancelled() void StateEstablishPaceChannel::handleNpaPosition(CardReturnCode pReturnCode) const { - if (pReturnCode == CardReturnCode::CARD_NOT_FOUND || pReturnCode == CardReturnCode::RETRY_ALLOWED) + if (pReturnCode == CardReturnCode::CARD_NOT_FOUND || pReturnCode == CardReturnCode::RESPONSE_EMPTY) { qCDebug(statemachine) << "Card vanished during PACE. Incrementing unfortunate-card-position panickiness."; getContext()->handleWrongNpaPosition(); @@ -142,52 +142,52 @@ void StateEstablishPaceChannel::handleNpaPosition(CardReturnCode pReturnCode) co void StateEstablishPaceChannel::onEstablishConnectionDone(QSharedPointer pCommand) { - if (mPasswordId != PacePasswordId::PACE_PUK) - { - auto paceCommand = pCommand.staticCast(); - getContext()->setPaceOutputData(paceCommand->getPaceOutput()); - } + getContext()->setInitialInputErrorShown(); + + auto paceCommand = pCommand.staticCast(); + getContext()->setPaceOutputData(paceCommand->getPaceOutput()); CardReturnCode returnCode = pCommand->getReturnCode(); getContext()->setLastPaceResult(returnCode); - handleNpaPosition(returnCode); - if (mPasswordId == PacePasswordId::PACE_PIN && returnCode == CardReturnCode::OK) - { - qCDebug(statemachine) << "PACE_PIN succeeded. Setting expected retry counter to:" << 3; - getContext()->setExpectedRetryCounter(3); - } - else if (mPasswordId == PacePasswordId::PACE_PUK && returnCode == CardReturnCode::OK) - { - qCDebug(statemachine) << "PACE_PUK succeeded. Resetting PACE passwords and setting expected retry counter to:" << -1; - getContext()->resetPacePasswords(); - getContext()->setExpectedRetryCounter(-1); - } - switch (returnCode) { case CardReturnCode::OK: - if (mPasswordId == PacePasswordId::PACE_PIN || - (mPasswordId == PacePasswordId::PACE_CAN && getContext()->isCanAllowedMode())) - { - Q_EMIT firePaceChannelEstablished(); - return; - } - else if (mPasswordId == PacePasswordId::PACE_PUK) + switch (mPasswordId) { - getContext()->setLastPaceResult(CardReturnCode::OK_PUK); + case PacePasswordId::PACE_PIN: + qCDebug(statemachine) << "PACE_PIN succeeded. Setting expected retry counter to:" << 3; + getContext()->setExpectedRetryCounter(3); + Q_EMIT fireContinue(); + break; - Q_EMIT firePaceChannelInoperative(); - return; - } + case PacePasswordId::PACE_CAN: + if (getContext()->isCanAllowedMode()) + { + qCDebug(statemachine) << "PACE_CAN (AUTH) succeeded"; + Q_EMIT fireContinue(); + break; + } + + qCDebug(statemachine) << "PACE_CAN (PIN) succeeded"; + getContext()->setLastPaceResult(CardReturnCode::OK_CAN); + Q_EMIT firePaceCanEstablished(); + break; - Q_EMIT fireContinue(); - return; + case PacePasswordId::PACE_PUK: + qCDebug(statemachine) << "PACE_PUK succeeded"; + getContext()->setLastPaceResult(CardReturnCode::OK_PUK); + Q_EMIT firePacePukEstablished(); + break; - case CardReturnCode::PUK_INOPERATIVE: - updateStatus(CardReturnCodeUtil::toGlobalStatus(returnCode)); - Q_EMIT fireAbort(FailureCode::Reason::Establish_Pace_Channel_Puk_Inoperative); + case PacePasswordId::PACE_MRZ: + case PacePasswordId::UNKNOWN: + qCritical() << "Cannot handle unknown PacePasswordId"; + updateStatus(GlobalStatus::Code::Card_Protocol_Error); + Q_EMIT fireAbort(FailureCode::Reason::Establish_Pace_Channel_Unknown_Password_Id); + break; + } return; case CardReturnCode::CANCELLATION_BY_USER: @@ -195,28 +195,16 @@ void StateEstablishPaceChannel::onEstablishConnectionDone(QSharedPointergetCardConnection()->getReaderInfo().getRetryCounter()) - { - case 2: - // Old retryCounter is 2: 2nd try failed - paceResult = CardReturnCode::INVALID_PIN_2; - break; - - case 1: - // Old retryCounter is 1: 3rd try failed - paceResult = CardReturnCode::INVALID_PIN_3; - break; + case CardReturnCode::INVALID_PIN_3: + Q_EMIT fireThirdPinAttemptFailed(); + return; - default: - paceResult = CardReturnCode::INVALID_PIN; - } - getContext()->setLastPaceResult(paceResult); - Q_EMIT firePaceChannelInoperative(); + case CardReturnCode::INVALID_PIN: + case CardReturnCode::INVALID_PIN_2: + case CardReturnCode::INVALID_CAN: + case CardReturnCode::INVALID_PUK: + Q_EMIT fireWrongPassword(); return; - } default: if (getContext()->isNpaRepositioningRequired()) diff --git a/src/workflows/base/states/StateEstablishPaceChannel.h b/src/workflows/base/states/StateEstablishPaceChannel.h index 6df5a46ea..f9ed6356c 100644 --- a/src/workflows/base/states/StateEstablishPaceChannel.h +++ b/src/workflows/base/states/StateEstablishPaceChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -41,10 +41,12 @@ class StateEstablishPaceChannel Q_SIGNALS: void fireNoCardConnection(); - void firePaceChannelEstablished(); - void firePaceChannelInoperative(); + void fireWrongPassword(); + void fireThirdPinAttemptFailed(); void fireAbortAndUnfortunateCardPosition(); void firePaceChannelFailed(); + void firePaceCanEstablished(); + void firePacePukEstablished(); }; } // namespace governikus diff --git a/src/workflows/base/states/StateExtractCvcsFromEac1InputType.cpp b/src/workflows/base/states/StateExtractCvcsFromEac1InputType.cpp index af6897d1f..7b5a22c88 100644 --- a/src/workflows/base/states/StateExtractCvcsFromEac1InputType.cpp +++ b/src/workflows/base/states/StateExtractCvcsFromEac1InputType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateExtractCvcsFromEac1InputType.h" diff --git a/src/workflows/base/states/StateExtractCvcsFromEac1InputType.h b/src/workflows/base/states/StateExtractCvcsFromEac1InputType.h index fa97c530e..2564ff032 100644 --- a/src/workflows/base/states/StateExtractCvcsFromEac1InputType.h +++ b/src/workflows/base/states/StateExtractCvcsFromEac1InputType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateGenericProviderCommunication.cpp b/src/workflows/base/states/StateGenericProviderCommunication.cpp index 2ee419e3c..0310e8f25 100644 --- a/src/workflows/base/states/StateGenericProviderCommunication.cpp +++ b/src/workflows/base/states/StateGenericProviderCommunication.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGenericProviderCommunication.h" @@ -82,9 +82,11 @@ void StateGenericProviderCommunication::checkSslConnectionAndSaveCertificate(con if (!TlsChecker::hasValidEphemeralKeyLength(pSslConfiguration.ephemeralServerKey())) { const GlobalStatus& status {GlobalStatus::Code::Workflow_Network_Ssl_Connection_Unsupported_Algorithm_Or_Length, infoMap}; - const FailureCode& failure {FailureCode::Reason::Generic_Provider_Communication_Invalid_Ephemeral_Key_Length, - {FailureCode::Info::State_Name, getStateName()} - }; + + auto map = TlsChecker::getEphemeralKeyInfoMap(pSslConfiguration.ephemeralServerKey()); + map.insert(FailureCode::Info::State_Name, getStateName()); + const FailureCode& failure {FailureCode::Reason::Generic_Provider_Communication_Invalid_Ephemeral_Key_Length, map}; + reportCommunicationError(status, failure); return; } @@ -92,7 +94,7 @@ void StateGenericProviderCommunication::checkSslConnectionAndSaveCertificate(con const auto statusCode = CertificateChecker::checkAndSaveCertificate(pSslConfiguration.peerCertificate(), context->getRefreshUrl(), context); if (statusCode != CertificateChecker::CertificateStatus::Good) { - infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, TlsChecker::getCertificateIssuerName(pSslConfiguration.peerCertificate())); + infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, pSslConfiguration.peerCertificate().issuerDisplayName()); const auto& status = GlobalStatus(CertificateChecker::getGlobalStatus(statusCode, false), infoMap); const FailureCode& failure {FailureCode::Reason::Generic_Provider_Communication_Certificate_Error, { diff --git a/src/workflows/base/states/StateGenericProviderCommunication.h b/src/workflows/base/states/StateGenericProviderCommunication.h index f5af4a5d6..29806e5e1 100644 --- a/src/workflows/base/states/StateGenericProviderCommunication.h +++ b/src/workflows/base/states/StateGenericProviderCommunication.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateGenericSendReceive.cpp b/src/workflows/base/states/StateGenericSendReceive.cpp index d2e993779..5484fb57a 100644 --- a/src/workflows/base/states/StateGenericSendReceive.cpp +++ b/src/workflows/base/states/StateGenericSendReceive.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGenericSendReceive.h" @@ -21,7 +21,7 @@ using namespace governikus; StateGenericSendReceive::StateGenericSendReceive( const QSharedPointer& pContext, PaosType pExpectedResponseType, - const QVector& pOtherResponseTypes, + const QList& pOtherResponseTypes, bool pPersonalization) : AbstractState(pContext) , GenericContextContainer(pContext) @@ -207,14 +207,16 @@ std::optional StateGenericSendReceive::checkSslConnectionAndSaveCer !TlsChecker::hasValidEphemeralKeyLength(pSslConfiguration.ephemeralServerKey())) { updateStatus({GlobalStatus::Code::Workflow_TrustedChannel_Ssl_Connection_Unsupported_Algorithm_Or_Length, infoMap}); - return FailureCode(FailureCode::Reason::Generic_Send_Receive_Invalid_Ephemeral_Key_Length, - {FailureCode::Info::State_Name, getStateName()}); + + auto map = TlsChecker::getEphemeralKeyInfoMap(pSslConfiguration.ephemeralServerKey()); + map.insert(FailureCode::Info::State_Name, getStateName()); + return FailureCode(FailureCode::Reason::Generic_Send_Receive_Invalid_Ephemeral_Key_Length, map); } const auto statusCode = CertificateChecker::checkAndSaveCertificate(pSslConfiguration.peerCertificate(), context->getTcToken()->getServerAddress(), context); if (statusCode != CertificateChecker::CertificateStatus::Good) { - infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, TlsChecker::getCertificateIssuerName(pSslConfiguration.peerCertificate())); + infoMap.insert(GlobalStatus::ExternalInformation::CERTIFICATE_ISSUER_NAME, pSslConfiguration.peerCertificate().issuerDisplayName()); updateStatus({CertificateChecker::getGlobalStatus(statusCode, true), infoMap}); const FailureCode::FailureInfoMap failureInfoMap { {FailureCode::Info::State_Name, getStateName()}, diff --git a/src/workflows/base/states/StateGenericSendReceive.h b/src/workflows/base/states/StateGenericSendReceive.h index 281459ba2..0163d75d7 100644 --- a/src/workflows/base/states/StateGenericSendReceive.h +++ b/src/workflows/base/states/StateGenericSendReceive.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -11,9 +11,9 @@ #include "paos/PaosType.h" #include "paos/invoke/PaosCreator.h" +#include #include #include -#include #include class test_StateGenericSendReceive; @@ -30,7 +30,7 @@ class StateGenericSendReceive private: const PaosType mExpectedResponseType; - const QVector mOtherResponseTypes; + const QList mOtherResponseTypes; const bool mPersonalization; QSharedPointer mReply; @@ -45,7 +45,7 @@ class StateGenericSendReceive explicit StateGenericSendReceive( const QSharedPointer& pContext, PaosType pExpectedResponseType, - const QVector& pOtherResponseTypes = {}, + const QList& pOtherResponseTypes = {}, bool pPersonalization = false); virtual QSharedPointer getAsResponse() = 0; diff --git a/src/workflows/base/states/StateGetTcToken.cpp b/src/workflows/base/states/StateGetTcToken.cpp index 5bcf5fe03..8345c3b3c 100644 --- a/src/workflows/base/states/StateGetTcToken.cpp +++ b/src/workflows/base/states/StateGetTcToken.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGetTcToken.h" @@ -140,7 +140,9 @@ void StateGetTcToken::onSslHandshakeDone() mReply->abort(); qCCritical(network) << "Error while connecting to the provider. The SSL connection uses an unsupported key algorithm or length."; updateStatus(status); - Q_EMIT fireAbort(FailureCode::Reason::Get_TcToken_Invalid_Ephemeral_Key_Length); + + const auto& map = TlsChecker::getEphemeralKeyInfoMap(cfg.ephemeralServerKey()); + Q_EMIT fireAbort({FailureCode::Reason::Get_TcToken_Invalid_Ephemeral_Key_Length, map}); return; } @@ -227,8 +229,7 @@ void StateGetTcToken::parseTcToken() { Q_ASSERT(getContext()->getTcToken().isNull()); - QByteArray data = mReply->readAll(); - if (data.isEmpty()) + if (mReply->bytesAvailable() == 0) { qCDebug(network) << "Received no data."; updateStatus({GlobalStatus::Code::Workflow_TrustedChannel_No_Data_Received, {GlobalStatus::ExternalInformation::LAST_URL, mReply->url().toString()} @@ -236,7 +237,7 @@ void StateGetTcToken::parseTcToken() Q_EMIT fireAbort(FailureCode::Reason::Get_TcToken_Empty_Data); return; } - const QSharedPointer& tcToken = QSharedPointer::create(data); + const auto& tcToken = QSharedPointer::create(mReply); getContext()->setTcToken(tcToken); getContext()->setTcTokenNotFound(!tcToken->isSchemaConform()); diff --git a/src/workflows/base/states/StateGetTcToken.h b/src/workflows/base/states/StateGetTcToken.h index 7a9cf8b9f..f1bb9fcff 100644 --- a/src/workflows/base/states/StateGetTcToken.h +++ b/src/workflows/base/states/StateGetTcToken.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateInitializeFramework.cpp b/src/workflows/base/states/StateInitializeFramework.cpp index 0e5285ecd..076a37984 100644 --- a/src/workflows/base/states/StateInitializeFramework.cpp +++ b/src/workflows/base/states/StateInitializeFramework.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "paos/invoke/InitializeFrameworkResponse.h" diff --git a/src/workflows/base/states/StateInitializeFramework.h b/src/workflows/base/states/StateInitializeFramework.h index fe3872852..a51511ea3 100644 --- a/src/workflows/base/states/StateInitializeFramework.h +++ b/src/workflows/base/states/StateInitializeFramework.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateMaintainCardConnection.cpp b/src/workflows/base/states/StateMaintainCardConnection.cpp index 5e3e365eb..f7dbea70b 100644 --- a/src/workflows/base/states/StateMaintainCardConnection.cpp +++ b/src/workflows/base/states/StateMaintainCardConnection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateMaintainCardConnection.h" @@ -16,9 +16,6 @@ void StateMaintainCardConnection::handleWrongPacePassword() { auto context = getContext(); - qCDebug(statemachine) << "Resetting all PACE passwords."; - context->resetPacePasswords(); - if (context->getCardConnection()) { qCDebug(statemachine) << "Trigger retry counter update."; @@ -42,13 +39,6 @@ StateMaintainCardConnection::StateMaintainCardConnection(const QSharedPointergetStatus().isError()) - { - Q_ASSERT(context->getFailureCode().has_value()); - Q_EMIT firePropagateAbort(); - return; - } - const CardReturnCode lastPaceResult = context->getLastPaceResult(); qCDebug(statemachine) << "Last PACE result:" << lastPaceResult; @@ -91,7 +81,7 @@ void StateMaintainCardConnection::run() return; } - case CardReturnCode::RETRY_ALLOWED: + case CardReturnCode::RESPONSE_EMPTY: case CardReturnCode::CARD_NOT_FOUND: { Q_ASSERT(!CardReturnCodeUtil::equalsWrongPacePassword(lastPaceResult)); @@ -104,13 +94,12 @@ void StateMaintainCardConnection::run() case CardReturnCode::OK: case CardReturnCode::OK_PUK: + case CardReturnCode::OK_CAN: { Q_ASSERT(!CardReturnCodeUtil::equalsWrongPacePassword(lastPaceResult)); - if (lastPaceResult == CardReturnCode::OK_PUK) + if (lastPaceResult == CardReturnCode::OK_PUK && context->getCardConnection()) { - getContext()->resetLastPaceResult(); - qCDebug(statemachine) << "PIN unblocked! Triggering retry counter update."; Q_EMIT fireForceUpdateRetryCounter(); return; diff --git a/src/workflows/base/states/StateMaintainCardConnection.h b/src/workflows/base/states/StateMaintainCardConnection.h index 6652a294b..0a6d7f85b 100644 --- a/src/workflows/base/states/StateMaintainCardConnection.h +++ b/src/workflows/base/states/StateMaintainCardConnection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -28,7 +28,6 @@ class StateMaintainCardConnection Q_SIGNALS: void fireNoCardConnection(); void fireForceUpdateRetryCounter(); - void firePropagateAbort(); }; } // namespace governikus diff --git a/src/workflows/base/states/StateParseTcTokenUrl.cpp b/src/workflows/base/states/StateParseTcTokenUrl.cpp index 1c31e72c9..4affdf7bb 100644 --- a/src/workflows/base/states/StateParseTcTokenUrl.cpp +++ b/src/workflows/base/states/StateParseTcTokenUrl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateParseTcTokenUrl.h b/src/workflows/base/states/StateParseTcTokenUrl.h index 432452083..3ce6c88c9 100644 --- a/src/workflows/base/states/StateParseTcTokenUrl.h +++ b/src/workflows/base/states/StateParseTcTokenUrl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StatePreVerification.cpp b/src/workflows/base/states/StatePreVerification.cpp index 82d1ff576..6eaadd7ac 100644 --- a/src/workflows/base/states/StatePreVerification.cpp +++ b/src/workflows/base/states/StatePreVerification.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePreVerification.h" @@ -9,7 +9,7 @@ #include "SecureStorage.h" #include "asn1/SignatureChecker.h" -#include +#include #include @@ -99,11 +99,11 @@ void StatePreVerification::run() } -bool StatePreVerification::isValid(const QVector>& pCertificates) const +bool StatePreVerification::isValid(const QList>& pCertificates) const { qDebug() << "Check certificate chain validity on" << mValidationDateTime.toString(Qt::ISODate); - QVectorIterator> i(pCertificates); + QListIterator> i(pCertificates); i.toBack(); while (i.hasPrevious()) { @@ -132,9 +132,9 @@ bool StatePreVerification::isValid(const QVector>& pCertificates) const +void StatePreVerification::saveCvcaLinkCertificates(const QList>& pCertificates) const { - const auto& contains = [](const QVector>& pStore, const CVCertificate& pCert) + const auto& contains = [](const QList>& pStore, const CVCertificate& pCert) { return std::any_of(pStore.constBegin(), pStore.constEnd(), [&pCert](const auto& pCertInStore) { diff --git a/src/workflows/base/states/StatePreVerification.h b/src/workflows/base/states/StatePreVerification.h index 677515858..fc558f9b7 100644 --- a/src/workflows/base/states/StatePreVerification.h +++ b/src/workflows/base/states/StatePreVerification.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /* @@ -27,14 +27,14 @@ class StatePreVerification friend class ::test_StatePreVerification; private: - const QVector> mTrustedCvcas; + const QList> mTrustedCvcas; const QDateTime mValidationDateTime; explicit StatePreVerification(const QSharedPointer& pContext); void run() override; - bool isValid(const QVector>& pCertificates) const; - void saveCvcaLinkCertificates(const QVector>& pCertificates) const; + bool isValid(const QList>& pCertificates) const; + void saveCvcaLinkCertificates(const QList>& pCertificates) const; }; } // namespace governikus diff --git a/src/workflows/base/states/StatePrepareChangePin.cpp b/src/workflows/base/states/StatePrepareChangePin.cpp index 506e05774..49e0948ca 100644 --- a/src/workflows/base/states/StatePrepareChangePin.cpp +++ b/src/workflows/base/states/StatePrepareChangePin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePrepareChangePin.h" diff --git a/src/workflows/base/states/StatePrepareChangePin.h b/src/workflows/base/states/StatePrepareChangePin.h index 87d779c87..6f9b91db8 100644 --- a/src/workflows/base/states/StatePrepareChangePin.h +++ b/src/workflows/base/states/StatePrepareChangePin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StatePreparePace.cpp b/src/workflows/base/states/StatePreparePace.cpp index a7957c79e..364931736 100644 --- a/src/workflows/base/states/StatePreparePace.cpp +++ b/src/workflows/base/states/StatePreparePace.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePreparePace.h" @@ -34,7 +34,7 @@ void StatePreparePace::handleRetryCounter(int pRetryCounter) return; } - Q_EMIT fireEstablishPaceChannel(); + Q_EMIT fireContinue(); return; } @@ -63,7 +63,7 @@ void StatePreparePace::handleRetryCounter(int pRetryCounter) return; } - Q_EMIT fireEstablishPaceChannel(); + Q_EMIT fireContinue(); return; } @@ -106,7 +106,7 @@ void StatePreparePace::run() return; } - Q_EMIT fireEstablishPaceChannel(); + Q_EMIT fireContinue(); return; } @@ -141,7 +141,7 @@ bool StatePreparePace::requestPaceCanIfStillRequired() return true; } - Q_EMIT fireEstablishPaceChannel(); + Q_EMIT fireContinue(); return true; } diff --git a/src/workflows/base/states/StatePreparePace.h b/src/workflows/base/states/StatePreparePace.h index c13833e55..55b01c831 100644 --- a/src/workflows/base/states/StatePreparePace.h +++ b/src/workflows/base/states/StatePreparePace.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -33,7 +33,6 @@ class StatePreparePace Q_SIGNALS: void fireNoCardConnection(); void fireEnterPacePassword(); - void fireEstablishPaceChannel(); }; } // namespace governikus diff --git a/src/workflows/base/states/StateProcessCertificatesFromEac2.cpp b/src/workflows/base/states/StateProcessCertificatesFromEac2.cpp index e6f2266bf..25f7fbc87 100644 --- a/src/workflows/base/states/StateProcessCertificatesFromEac2.cpp +++ b/src/workflows/base/states/StateProcessCertificatesFromEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateProcessCertificatesFromEac2.h" @@ -27,7 +27,7 @@ void StateProcessCertificatesFromEac2::run() return; } - QVector> cvcs; + QList> cvcs; for (const auto& cvc : getContext()->getDidAuthenticateEac2()->getCvCertificates()) { // according to TR-03112-7, paragraph 3.6.4.2, AT certs must be ignored diff --git a/src/workflows/base/states/StateProcessCertificatesFromEac2.h b/src/workflows/base/states/StateProcessCertificatesFromEac2.h index 3c2e54756..c3dd14af1 100644 --- a/src/workflows/base/states/StateProcessCertificatesFromEac2.h +++ b/src/workflows/base/states/StateProcessCertificatesFromEac2.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateRedirectBrowser.cpp b/src/workflows/base/states/StateRedirectBrowser.cpp index 9674783d1..82831b4cb 100644 --- a/src/workflows/base/states/StateRedirectBrowser.cpp +++ b/src/workflows/base/states/StateRedirectBrowser.cpp @@ -1,14 +1,34 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateRedirectBrowser.h" +#include "ECardApiResult.h" + #include + using namespace governikus; +namespace +{ +inline QString removePrefix(QString pStr) +{ + return pStr.replace(QRegularExpression(QStringLiteral("(.*)#")), QLatin1String("")); +} + + +inline QString getSuffix(ECardApiResult::Minor pMinor) +{ + return removePrefix(ECardApiResult::getMinorString(pMinor)); +} + + +} // namespace + + StateRedirectBrowser::StateRedirectBrowser(const QSharedPointer& pContext) : AbstractState(pContext) , GenericContextContainer(pContext) @@ -18,11 +38,38 @@ StateRedirectBrowser::StateRedirectBrowser(const QSharedPointer void StateRedirectBrowser::run() { - if (const auto& handler = getContext()->getBrowserHandler(); handler) + const auto& context = getContext(); + if (const auto& url = context->getRefreshUrl(); url.isValid()) + { + const auto& result = context->getStartPaosResult().isOk() ? ECardApiResult(context->getStatus()) : context->getStartPaosResult(); + context->setRefreshUrl(addMajorMinor(url, GlobalStatus(result))); + } + else { - if (const auto& error = handler(getContext()); !error.isEmpty()) + qDebug() << "Refresh URL is not valid:" << url; + if (const auto& tcToken = context->getTcToken(); tcToken) + { + if (const auto& address = context->getTcToken()->getCommunicationErrorAddress(); address.isValid()) + { + context->setRefreshUrl(addMajorMinor(address, GlobalStatus::Code::Workflow_Communication_Missing_Redirect_Url)); + } + else + { + qDebug() << "CommunicationErrorAddress is not valid:" << address; + } + } + else + { + qDebug() << "TcToken is missing"; + } + } + + if (const auto& handler = context->getBrowserHandler(); handler) + { + if (const auto& error = handler(context); !error.isEmpty()) { qCritical() << "Cannot send page to caller:" << error; + context->setReceivedBrowserSendFailed(true); updateStatus({GlobalStatus::Code::Workflow_Browser_Transmission_Error, {GlobalStatus::ExternalInformation::ACTIVATION_ERROR, error} }); Q_EMIT fireAbort(FailureCode::Reason::Browser_Send_Failed); @@ -32,3 +79,50 @@ void StateRedirectBrowser::run() Q_EMIT fireContinue(); } + + +QUrl StateRedirectBrowser::addMajorMinor(const QUrl& pOriginUrl, const GlobalStatus& pStatus) +{ + QUrlQuery q; + q.setQuery(pOriginUrl.query()); + + const ECardApiResult::Major majorEnumVal = pStatus.isError() ? ECardApiResult::Major::Error : ECardApiResult::Major::Ok; + QString major = removePrefix(ECardApiResult::getMajorString(majorEnumVal)); + q.addQueryItem(QStringLiteral("ResultMajor"), major); + + if (pStatus.isError()) + { + QString minor; + + switch (pStatus.getStatusCode()) + { + case GlobalStatus::Code::Paos_Error_AL_Communication_Error: + minor = getSuffix(ECardApiResult::Minor::AL_Communication_Error); + break; + + case GlobalStatus::Code::Paos_Error_DP_Trusted_Channel_Establishment_Failed: + minor = getSuffix(ECardApiResult::Minor::DP_Trusted_Channel_Establishment_Failed); + break; + + case GlobalStatus::Code::Paos_Error_SAL_Cancellation_by_User: + minor = getSuffix(ECardApiResult::Minor::SAL_Cancellation_by_User); + break; + + default: + if (pStatus.isOriginServer()) + { + minor = QStringLiteral("serverError"); + } + else + { + minor = QStringLiteral("clientError"); + } + break; + } + q.addQueryItem(QStringLiteral("ResultMinor"), minor); + } + + QUrl adaptedUrl(pOriginUrl); + adaptedUrl.setQuery(q); + return adaptedUrl; +} diff --git a/src/workflows/base/states/StateRedirectBrowser.h b/src/workflows/base/states/StateRedirectBrowser.h index 58c4590be..92d733777 100644 --- a/src/workflows/base/states/StateRedirectBrowser.h +++ b/src/workflows/base/states/StateRedirectBrowser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include "GenericContextContainer.h" #include "context/AuthContext.h" + class test_StateRedirectBrowser; @@ -31,6 +32,7 @@ class StateRedirectBrowser void run() override; + static QUrl addMajorMinor(const QUrl& pUrl, const GlobalStatus& pStatus); }; } // namespace governikus diff --git a/src/workflows/base/states/StateResetRetryCounter.cpp b/src/workflows/base/states/StateResetRetryCounter.cpp new file mode 100644 index 000000000..a3381b56b --- /dev/null +++ b/src/workflows/base/states/StateResetRetryCounter.cpp @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "states/StateResetRetryCounter.h" + +#include + + +Q_DECLARE_LOGGING_CATEGORY(statemachine) + + +using namespace governikus; + +StateResetRetryCounter::StateResetRetryCounter(const QSharedPointer& pContext) + : AbstractState(pContext) + , GenericContextContainer(pContext) +{ +} + + +void StateResetRetryCounter::run() +{ + const auto& context = getContext(); + Q_ASSERT(context); + + auto cardConnection = getContext()->getCardConnection(); + if (!cardConnection) + { + qCDebug(statemachine) << "No card connection available."; + Q_EMIT fireNoCardConnection(); + return; + } + + Q_ASSERT(cardConnection != nullptr); + *this << cardConnection->callResetRetryCounterCommand(this, &StateResetRetryCounter::onResetRetryCounterDone); +} + + +void StateResetRetryCounter::onResetRetryCounterDone(QSharedPointer pCommand) +{ + const auto& returnCode = pCommand->getReturnCode(); + switch (returnCode) + { + case CardReturnCode::OK: + getContext()->setExpectedRetryCounter(-1); + Q_EMIT fireContinue(); + return; + + case CardReturnCode::PUK_INOPERATIVE: + updateStatus(CardReturnCodeUtil::toGlobalStatus(returnCode)); + Q_EMIT fireAbort(FailureCode::Reason::Establish_Pace_Channel_Puk_Inoperative); + return; + + default: + qCCritical(statemachine).nospace() << "An error (" << returnCode << ") occurred while communicating with the card reader, cannot reset retry counter, abort state"; + getContext()->resetCardConnection(); + Q_EMIT fireNoCardConnection(); + return; + + } + + Q_UNREACHABLE(); +} diff --git a/src/workflows/base/states/StateResetRetryCounter.h b/src/workflows/base/states/StateResetRetryCounter.h new file mode 100644 index 000000000..0bd3482b0 --- /dev/null +++ b/src/workflows/base/states/StateResetRetryCounter.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + + +#pragma once + +#include "AbstractState.h" +#include "GenericContextContainer.h" +#include "context/WorkflowContext.h" + +class test_StateResetRetryCounter; + +namespace governikus +{ + +class StateResetRetryCounter + : public AbstractState + , public GenericContextContainer +{ + Q_OBJECT + friend class StateBuilder; + friend class ::test_StateResetRetryCounter; + + private: + explicit StateResetRetryCounter(const QSharedPointer& pContext); + void run() override; + + private Q_SLOTS: + void onResetRetryCounterDone(QSharedPointer pCommand); + + Q_SIGNALS: + void fireNoCardConnection(); + +}; + +} // namespace governikus diff --git a/src/workflows/base/states/StateSelectReader.cpp b/src/workflows/base/states/StateSelectReader.cpp index 51322b4cb..f8d2e6aaf 100644 --- a/src/workflows/base/states/StateSelectReader.cpp +++ b/src/workflows/base/states/StateSelectReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "StateSelectReader.h" @@ -20,26 +20,26 @@ StateSelectReader::StateSelectReader(const QSharedPointer& pCon : AbstractState(pContext) , GenericContextContainer(pContext) { + setHandleNfcStop(); } void StateSelectReader::run() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); *this << connect(readerManager, &ReaderManager::fireReaderAdded, this, &StateSelectReader::onReaderInfoChanged); *this << connect(readerManager, &ReaderManager::fireReaderRemoved, this, &StateSelectReader::onReaderInfoChanged); *this << connect(readerManager, &ReaderManager::fireCardInserted, this, &StateSelectReader::onReaderInfoChanged); *this << connect(readerManager, &ReaderManager::fireCardRemoved, this, &StateSelectReader::onReaderInfoChanged); - *this << connect(readerManager, &ReaderManager::fireStatusChanged, this, &StateSelectReader::onReaderStatusChanged); onReaderInfoChanged(); const auto& context = getContext(); - const auto& readerPlugInTypes = Enum::getList(); - const auto& enabledPlugInTypes = context->getReaderPlugInTypes(); - for (const auto t : readerPlugInTypes) + const auto& readerPluginTypes = Enum::getList(); + const auto& enabledPluginTypes = context->getReaderPluginTypes(); + for (const auto t : readerPluginTypes) { - enabledPlugInTypes.contains(t) && !context->skipStartScan() ? readerManager->startScan(t) : readerManager->stopScan(t); + enabledPluginTypes.contains(t) && !context->skipStartScan() ? readerManager->startScan(t) : readerManager->stopScan(t); } context->setSkipStartScan(false); } @@ -51,9 +51,9 @@ void StateSelectReader::onReaderInfoChanged() Q_ASSERT(context); bool currentReaderHasEidCardButInsufficientApduLength = false; - const QVector& plugInTypes = context->getReaderPlugInTypes(); - const auto allReaders = Env::getSingleton()->getReaderInfos(ReaderFilter(plugInTypes)); - QVector selectableReaders; + const QList& pluginTypes = context->getReaderPluginTypes(); + const auto allReaders = Env::getSingleton()->getReaderInfos(ReaderFilter(pluginTypes)); + QList selectableReaders; for (const auto& info : allReaders) { @@ -68,7 +68,7 @@ void StateSelectReader::onReaderInfoChanged() selectableReaders.append(info); } else if (!Env::getSingleton()->isUsedAsSDK() - && info.getPlugInType() == ReaderManagerPlugInType::REMOTE_IFD + && info.getPluginType() == ReaderManagerPluginType::REMOTE_IFD && info.isInsertable()) { Env::getSingleton()->insert(info); @@ -89,30 +89,12 @@ void StateSelectReader::onReaderInfoChanged() const QString readerName = readerInfo.getName(); context->setReaderName(readerName); qCDebug(statemachine) << "Select first found reader:" << readerName; - qCDebug(statemachine) << "Type:" << readerInfo.getPlugInType() << "BasicReader:" << readerInfo.isBasicReader(); + qCDebug(statemachine) << "Type:" << readerInfo.getPluginType() << "BasicReader:" << readerInfo.isBasicReader(); Q_EMIT fireContinue(); } -void StateSelectReader::onReaderStatusChanged(const ReaderManagerPlugInInfo& pInfo) const -{ -#if defined(Q_OS_IOS) - if (!Env::getSingleton()->isUsedAsSDK() || pInfo.getPlugInType() != ReaderManagerPlugInType::NFC) - { - return; - } - - if (!pInfo.isScanRunning()) - { - Q_EMIT getContext()->fireCancelWorkflow(); - } -#else - Q_UNUSED(pInfo) -#endif -} - - void StateSelectReader::onEntry(QEvent* pEvent) { AbstractState::onEntry(pEvent); @@ -124,6 +106,6 @@ void StateSelectReader::onEntry(QEvent* pEvent) * Note: the plugin types to be used in this state must be already set in the workflow context before this state is entered. * Changing the plugin types in the context, e.g. from {NFC} to {REMOTE}, causes the state to be left with a fireRetry signal. */ - *this << connect(context, &WorkflowContext::fireReaderPlugInTypesChanged, this, &StateSelectReader::fireRetry); + *this << connect(context, &WorkflowContext::fireReaderPluginTypesChanged, this, &StateSelectReader::fireRetry); } diff --git a/src/workflows/base/states/StateSelectReader.h b/src/workflows/base/states/StateSelectReader.h index 1a2446333..74027f65e 100644 --- a/src/workflows/base/states/StateSelectReader.h +++ b/src/workflows/base/states/StateSelectReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -24,7 +24,6 @@ class StateSelectReader private Q_SLOTS: void onReaderInfoChanged(); - void onReaderStatusChanged(const ReaderManagerPlugInInfo& pInfo) const; public: void onEntry(QEvent* pEvent) override; diff --git a/src/workflows/base/states/StateSendWhitelistSurvey.cpp b/src/workflows/base/states/StateSendWhitelistSurvey.cpp index 79ffaa24b..c04caf946 100644 --- a/src/workflows/base/states/StateSendWhitelistSurvey.cpp +++ b/src/workflows/base/states/StateSendWhitelistSurvey.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateSendWhitelistSurvey.h" #include "AppSettings.h" #include "ReaderManager.h" -#include "SurveyModel.h" +#include "Survey.h" #include "VolatileSettings.h" Q_DECLARE_LOGGING_CATEGORY(statemachine) @@ -31,16 +31,16 @@ void StateSendWhitelistSurvey::run() return; } - const auto& surveyModel = Env::getSingleton(); - if (!surveyModel->isDeviceSurveyPending()) + auto* survey = Env::getSingleton(); + if (!survey->isDeviceSurveyPending()) { qCDebug(statemachine) << "No survey pending."; Q_EMIT fireContinue(); return; } - surveyModel->setDeviceSurveyPending(false); - surveyModel->transmitSurvey(); + survey->setDeviceSurveyPending(false); + survey->transmitSurvey(); #endif Q_EMIT fireContinue(); diff --git a/src/workflows/base/states/StateSendWhitelistSurvey.h b/src/workflows/base/states/StateSendWhitelistSurvey.h index 6c93f4717..1691092a6 100644 --- a/src/workflows/base/states/StateSendWhitelistSurvey.h +++ b/src/workflows/base/states/StateSendWhitelistSurvey.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /* diff --git a/src/workflows/base/states/StateShowResult.cpp b/src/workflows/base/states/StateShowResult.cpp index 6ec308bc0..c10551dc6 100644 --- a/src/workflows/base/states/StateShowResult.cpp +++ b/src/workflows/base/states/StateShowResult.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateShowResult.h" diff --git a/src/workflows/base/states/StateShowResult.h b/src/workflows/base/states/StateShowResult.h index bfb12f704..736dd7ec5 100644 --- a/src/workflows/base/states/StateShowResult.h +++ b/src/workflows/base/states/StateShowResult.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateStartPaos.cpp b/src/workflows/base/states/StateStartPaos.cpp index c8c67246a..e84d1cab5 100644 --- a/src/workflows/base/states/StateStartPaos.cpp +++ b/src/workflows/base/states/StateStartPaos.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStartPaos.h" diff --git a/src/workflows/base/states/StateStartPaos.h b/src/workflows/base/states/StateStartPaos.h index 9445cd77c..db99f124e 100644 --- a/src/workflows/base/states/StateStartPaos.h +++ b/src/workflows/base/states/StateStartPaos.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateStartPaosResponse.cpp b/src/workflows/base/states/StateStartPaosResponse.cpp index e48bcee56..a64b184c7 100644 --- a/src/workflows/base/states/StateStartPaosResponse.cpp +++ b/src/workflows/base/states/StateStartPaosResponse.cpp @@ -1,10 +1,10 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStartPaosResponse.h" -#include "SurveyModel.h" +#include "Survey.h" using namespace governikus; @@ -31,7 +31,7 @@ void StateStartPaosResponse::run() } const ECardApiResult& result = startPaosResponse->getResult(); - Env::getSingleton()->setAuthWasSuccessful(result.isOk()); + Env::getSingleton()->setAuthWasSuccessful(result.isOk()); if (result.isOk()) { Q_EMIT fireContinue(); diff --git a/src/workflows/base/states/StateStartPaosResponse.h b/src/workflows/base/states/StateStartPaosResponse.h index d6cb10a72..a0962fd33 100644 --- a/src/workflows/base/states/StateStartPaosResponse.h +++ b/src/workflows/base/states/StateStartPaosResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateTransmit.cpp b/src/workflows/base/states/StateTransmit.cpp index 0a9cbc88a..1f612ca64 100644 --- a/src/workflows/base/states/StateTransmit.cpp +++ b/src/workflows/base/states/StateTransmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardConnection.h" diff --git a/src/workflows/base/states/StateTransmit.h b/src/workflows/base/states/StateTransmit.h index cb1528c7a..73cfe2f2b 100644 --- a/src/workflows/base/states/StateTransmit.h +++ b/src/workflows/base/states/StateTransmit.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,7 +10,6 @@ #include "AbstractState.h" #include "GenericContextContainer.h" -#include "command/TransmitCommand.h" #include "context/AuthContext.h" class test_StateTransmit; diff --git a/src/workflows/base/states/StateUnfortunateCardPosition.cpp b/src/workflows/base/states/StateUnfortunateCardPosition.cpp index b3efb7aaf..d4f3b1c9b 100644 --- a/src/workflows/base/states/StateUnfortunateCardPosition.cpp +++ b/src/workflows/base/states/StateUnfortunateCardPosition.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateUnfortunateCardPosition.h" @@ -7,6 +7,10 @@ #include "AbstractState.h" #include "GenericContextContainer.h" +#if defined(Q_OS_IOS) + #include "ReaderManager.h" +#endif + using namespace governikus; @@ -26,8 +30,14 @@ void StateUnfortunateCardPosition::run() void StateUnfortunateCardPosition::onEntry(QEvent* pEvent) { - //: INFO The NFC signal is weak or unstable. The scan is stopped with this information in the iOS dialog. - stopNfcScanIfNecessary(tr("Weak NFC signal. Please\n- change the card position\n- remove the mobile phone case (if present)\n- connect the smartphone with a charging cable")); +#if defined(Q_OS_IOS) + if (getContext()->getReaderPluginTypes().contains(ReaderManagerPluginType::NFC)) + { + //: INFO The NFC signal is weak or unstable. The scan is stopped with this information in the iOS dialog. + const auto& errorMessage = tr("Weak NFC signal. Please\n- change the card position\n- remove the mobile phone case (if present)\n- connect the smartphone with a charging cable"); + Env::getSingleton()->stopScan(ReaderManagerPluginType::NFC, errorMessage); + } +#endif AbstractState::onEntry(pEvent); } diff --git a/src/workflows/base/states/StateUnfortunateCardPosition.h b/src/workflows/base/states/StateUnfortunateCardPosition.h index 411854b57..73c4f0321 100644 --- a/src/workflows/base/states/StateUnfortunateCardPosition.h +++ b/src/workflows/base/states/StateUnfortunateCardPosition.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/base/states/StateUpdateRetryCounter.cpp b/src/workflows/base/states/StateUpdateRetryCounter.cpp index bd8a05d38..30a64f223 100644 --- a/src/workflows/base/states/StateUpdateRetryCounter.cpp +++ b/src/workflows/base/states/StateUpdateRetryCounter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateUpdateRetryCounter.h" diff --git a/src/workflows/base/states/StateUpdateRetryCounter.h b/src/workflows/base/states/StateUpdateRetryCounter.h index 988b1510f..4eee5b028 100644 --- a/src/workflows/base/states/StateUpdateRetryCounter.h +++ b/src/workflows/base/states/StateUpdateRetryCounter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/base/states/StateVerifyRetryCounter.cpp b/src/workflows/base/states/StateVerifyRetryCounter.cpp index b670df15a..49a2e43fb 100644 --- a/src/workflows/base/states/StateVerifyRetryCounter.cpp +++ b/src/workflows/base/states/StateVerifyRetryCounter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateVerifyRetryCounter.h" @@ -32,22 +32,24 @@ void StateVerifyRetryCounter::run() const int expectedRetryCounter = context->getExpectedRetryCounter(); qCDebug(statemachine) << "Retry counter | actual:" << currentRetryCounter << "/ expected:" << expectedRetryCounter; - if (context->remembersReader()) - { - if (!context->isExpectedReader() || expectedRetryCounter != currentRetryCounter) - { - qCDebug(statemachine) << "The reader changed or the connected card has an unexpected retry counter. Clearing PACE passwords."; - context->resetPacePasswords(); - context->rememberReader(); - } - } - else + if (!context->remembersReader()) { Q_ASSERT(currentRetryCounter != -1); - qCDebug(statemachine) << "Remembering the selected reader and initializing the expected retry counter:" << currentRetryCounter; + qCDebug(statemachine) << "Initially remembering the selected reader including the card with retry counter" << currentRetryCounter; context->rememberReader(); + Q_EMIT fireContinue(); + return; + } + + if (context->isExpectedReader() && expectedRetryCounter == currentRetryCounter) + { + qCDebug(statemachine) << "Found expected reader and retry counter matches"; + Q_EMIT fireContinue(); + return; } - Q_EMIT fireContinue(); + qCDebug(statemachine) << "The reader changed or the connected card has an unexpected retry counter. Remembering the new reader including the card with retry counter" << currentRetryCounter; + context->rememberReader(); + Q_EMIT fireReaderOrCardChanged(); } diff --git a/src/workflows/base/states/StateVerifyRetryCounter.h b/src/workflows/base/states/StateVerifyRetryCounter.h index 674ac3f07..be4bc6a7f 100644 --- a/src/workflows/base/states/StateVerifyRetryCounter.h +++ b/src/workflows/base/states/StateVerifyRetryCounter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -29,6 +29,7 @@ class StateVerifyRetryCounter Q_SIGNALS: void fireNoCardConnection(); + void fireReaderOrCardChanged(); }; } // namespace governikus diff --git a/src/workflows/ifd/context/IfdServiceContext.cpp b/src/workflows/ifd/context/IfdServiceContext.cpp index 2ca9745eb..4dc316d10 100644 --- a/src/workflows/ifd/context/IfdServiceContext.cpp +++ b/src/workflows/ifd/context/IfdServiceContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdServiceContext.h" @@ -104,9 +104,9 @@ bool IfdServiceContext::isCanAllowedMode() const } -void IfdServiceContext::cancelPasswordRequest() +void IfdServiceContext::userError(StatusCode pStatusCode) { - Q_EMIT fireCancelPasswordRequest(); + Q_EMIT fireUserError(pStatusCode); } @@ -228,6 +228,7 @@ void IfdServiceContext::setModifyPinMessage(const QSharedPointer IfdServiceContext::getAcceptedEidTypes() const +[[nodiscard]] QList IfdServiceContext::getAcceptedEidTypes() const { return {AcceptedEidType::CARD_CERTIFIED, AcceptedEidType::SE_CERTIFIED, AcceptedEidType::SE_ENDORSED, AcceptedEidType::HW_KEYSTORE}; } diff --git a/src/workflows/ifd/context/IfdServiceContext.h b/src/workflows/ifd/context/IfdServiceContext.h index a8a5a5de9..498b7fc0f 100644 --- a/src/workflows/ifd/context/IfdServiceContext.h +++ b/src/workflows/ifd/context/IfdServiceContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -53,7 +53,7 @@ class IfdServiceContext void fireCardConnected(const QSharedPointer& pConnection); void fireDisplayTextChanged(); void fireCardDisconnected(const QSharedPointer& pConnection); - void fireCancelPasswordRequest(); + void fireUserError(StatusCode pStatusCode); void fireEstablishPaceChannelUpdated(); void fireIsRunningChanged(); void fireAccessRightManagerCreated(QSharedPointer pAccessRightManager); @@ -72,7 +72,7 @@ class IfdServiceContext [[nodiscard]] bool isPinAuthentication() const; [[nodiscard]] bool isCanAllowedMode() const override; - void cancelPasswordRequest(); + void userError(StatusCode pStatusCode); void setEstablishPaceChannel(const QSharedPointer& pMessage); [[nodiscard]] const QString& getSlotHandle() const; @@ -99,7 +99,7 @@ class IfdServiceContext void resetPacePasswords() override; Q_INVOKABLE void reset(); - [[nodiscard]] QVector getAcceptedEidTypes() const override; + [[nodiscard]] QList getAcceptedEidTypes() const override; }; diff --git a/src/workflows/ifd/controller/IfdServiceController.cpp b/src/workflows/ifd/controller/IfdServiceController.cpp index 08ace1b4e..0ee517211 100644 --- a/src/workflows/ifd/controller/IfdServiceController.cpp +++ b/src/workflows/ifd/controller/IfdServiceController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdServiceController.h" @@ -22,7 +22,6 @@ #include "states/StateVerifyRetryCounter.h" #include -#include using namespace governikus; @@ -31,12 +30,11 @@ using namespace governikus; IfdServiceController::IfdServiceController(QSharedPointer pContext) : WorkflowController(pContext) { - forceStartStopScan(); - auto sStartIfdService = addInitialState(); auto sProcessIfdMessages = addState(); auto sUpdateRetryCounter = addState(); auto sVerifyRetryCounter = addState(); + auto sClearPacePasswordsOnNewCard = addState(); auto sPreparePaceIfd = addState(); auto sEnterPacePasswordIfd = addState(); auto sEstablishPaceChannelIfd = addState(); @@ -46,14 +44,15 @@ IfdServiceController::IfdServiceController(QSharedPointer pCo auto sChangePinIfd = addState(); auto sChangePinResponse = addState(); auto sClearPacePasswords = addState(); + auto sClearPacePasswordsBeforeStop = addState(); auto sStopIfdService = addState(); auto sFinal = addState(); sStartIfdService->addTransition(sStartIfdService, &AbstractState::fireContinue, sProcessIfdMessages); sStartIfdService->addTransition(sStartIfdService, &AbstractState::fireAbort, sStopIfdService); - sProcessIfdMessages->addTransition(sProcessIfdMessages, &AbstractState::fireContinue, sStopIfdService); - sProcessIfdMessages->addTransition(sProcessIfdMessages, &AbstractState::fireAbort, sStopIfdService); + sProcessIfdMessages->addTransition(sProcessIfdMessages, &AbstractState::fireContinue, sClearPacePasswordsBeforeStop); + sProcessIfdMessages->addTransition(sProcessIfdMessages, &AbstractState::fireAbort, sClearPacePasswordsBeforeStop); sProcessIfdMessages->addTransition(sProcessIfdMessages, &StateProcessIfdMessages::fireEstablishPaceChannel, sUpdateRetryCounter); sProcessIfdMessages->addTransition(sProcessIfdMessages, &StateProcessIfdMessages::fireModifyPin, sPrepareChangePinIfd); sProcessIfdMessages->addTransition(sProcessIfdMessages, &StateProcessIfdMessages::fireSecureMessagingStopped, sClearPacePasswords); @@ -65,6 +64,10 @@ IfdServiceController::IfdServiceController(QSharedPointer pCo sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &AbstractState::fireContinue, sPreparePaceIfd); sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &AbstractState::fireAbort, sEstablishPaceChannelResponse); sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &StateVerifyRetryCounter::fireNoCardConnection, sEstablishPaceChannelResponse); + sVerifyRetryCounter->addTransition(sVerifyRetryCounter, &StateVerifyRetryCounter::fireReaderOrCardChanged, sClearPacePasswordsOnNewCard); + + sClearPacePasswordsOnNewCard->addTransition(sClearPacePasswordsOnNewCard, &AbstractState::fireContinue, sPreparePaceIfd); + sClearPacePasswordsOnNewCard->addTransition(sClearPacePasswordsOnNewCard, &AbstractState::fireAbort, sPreparePaceIfd); sPreparePaceIfd->addTransition(sPreparePaceIfd, &AbstractState::fireContinue, sEstablishPaceChannelIfd); sPreparePaceIfd->addTransition(sPreparePaceIfd, &AbstractState::fireAbort, sEstablishPaceChannelResponse); @@ -97,6 +100,9 @@ IfdServiceController::IfdServiceController(QSharedPointer pCo sClearPacePasswords->addTransition(sClearPacePasswords, &AbstractState::fireContinue, sProcessIfdMessages); sClearPacePasswords->addTransition(sClearPacePasswords, &AbstractState::fireAbort, sProcessIfdMessages); + sClearPacePasswordsBeforeStop->addTransition(sClearPacePasswordsBeforeStop, &AbstractState::fireContinue, sStopIfdService); + sClearPacePasswordsBeforeStop->addTransition(sClearPacePasswordsBeforeStop, &AbstractState::fireAbort, sStopIfdService); + sStopIfdService->addTransition(sStopIfdService, &AbstractState::fireContinue, sFinal); sStopIfdService->addTransition(sStopIfdService, &AbstractState::fireAbort, sFinal); } diff --git a/src/workflows/ifd/controller/IfdServiceController.h b/src/workflows/ifd/controller/IfdServiceController.h index 720b69cb5..b4b5ae6ce 100644 --- a/src/workflows/ifd/controller/IfdServiceController.h +++ b/src/workflows/ifd/controller/IfdServiceController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StateChangePinIfd.cpp b/src/workflows/ifd/states/StateChangePinIfd.cpp index 904c5f2dc..89474cb11 100644 --- a/src/workflows/ifd/states/StateChangePinIfd.cpp +++ b/src/workflows/ifd/states/StateChangePinIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateChangePinIfd.h" diff --git a/src/workflows/ifd/states/StateChangePinIfd.h b/src/workflows/ifd/states/StateChangePinIfd.h index 5eff270ac..7b377d327 100644 --- a/src/workflows/ifd/states/StateChangePinIfd.h +++ b/src/workflows/ifd/states/StateChangePinIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StateChangePinResponse.cpp b/src/workflows/ifd/states/StateChangePinResponse.cpp index 249078e82..500358c90 100644 --- a/src/workflows/ifd/states/StateChangePinResponse.cpp +++ b/src/workflows/ifd/states/StateChangePinResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateChangePinResponse.h" diff --git a/src/workflows/ifd/states/StateChangePinResponse.h b/src/workflows/ifd/states/StateChangePinResponse.h index 2fadcaf4c..a2a5cab35 100644 --- a/src/workflows/ifd/states/StateChangePinResponse.h +++ b/src/workflows/ifd/states/StateChangePinResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StateEnterNewPacePinIfd.cpp b/src/workflows/ifd/states/StateEnterNewPacePinIfd.cpp index 69db574d6..8ada2d4cf 100644 --- a/src/workflows/ifd/states/StateEnterNewPacePinIfd.cpp +++ b/src/workflows/ifd/states/StateEnterNewPacePinIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEnterNewPacePinIfd.h" @@ -22,11 +22,11 @@ void StateEnterNewPacePinIfd::run() } -void StateEnterNewPacePinIfd::onCancelChangePin() +void StateEnterNewPacePinIfd::onUserError(StatusCode pStatusCode) { if (getContext() && getContext()->getIfdServer() && getContext()->getIfdServer()->getMessageHandler()) { - getContext()->setModifyPinMessageResponseApdu(ResponseApdu(StatusCode::INPUT_CANCELLED)); + getContext()->setModifyPinMessageResponseApdu(ResponseApdu(pStatusCode)); } Q_EMIT fireAbort(FailureCode::Reason::Enter_New_Pace_Pin_Ifd_User_Cancelled); } @@ -41,8 +41,10 @@ void StateEnterNewPacePinIfd::onEntry(QEvent* pEvent) if (getContext() && getContext()->getIfdServer() && getContext()->getIfdServer()->getMessageHandler()) { const auto& handler = getContext()->getIfdServer()->getMessageHandler(); - *this << connect(handler.data(), &ServerMessageHandler::destroyed, this, &StateEnterNewPacePinIfd::onCancelChangePin); + *this << connect(handler.data(), &ServerMessageHandler::destroyed, this, [this]{ + onUserError(StatusCode::INPUT_CANCELLED); + }); } - *this << connect(getContext().data(), &IfdServiceContext::fireCancelPasswordRequest, this, &StateEnterNewPacePinIfd::onCancelChangePin); + *this << connect(getContext().data(), &IfdServiceContext::fireUserError, this, &StateEnterNewPacePinIfd::onUserError); } diff --git a/src/workflows/ifd/states/StateEnterNewPacePinIfd.h b/src/workflows/ifd/states/StateEnterNewPacePinIfd.h index d5b239982..4a05c5ea3 100644 --- a/src/workflows/ifd/states/StateEnterNewPacePinIfd.h +++ b/src/workflows/ifd/states/StateEnterNewPacePinIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -23,7 +23,7 @@ class StateEnterNewPacePinIfd void run() override; private Q_SLOTS: - void onCancelChangePin(); + void onUserError(StatusCode pStatusCode); public: void onEntry(QEvent* pEvent) override; diff --git a/src/workflows/ifd/states/StateEnterPacePasswordIfd.cpp b/src/workflows/ifd/states/StateEnterPacePasswordIfd.cpp index 971ca45e0..a420db01e 100644 --- a/src/workflows/ifd/states/StateEnterPacePasswordIfd.cpp +++ b/src/workflows/ifd/states/StateEnterPacePasswordIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEnterPacePasswordIfd.h" @@ -22,7 +22,7 @@ void StateEnterPacePasswordIfd::run() } -void StateEnterPacePasswordIfd::onCancelEstablishPaceChannel() +void StateEnterPacePasswordIfd::onUserError() { if (getContext() && getContext()->getIfdServer() && getContext()->getIfdServer()->getMessageHandler()) { @@ -43,8 +43,8 @@ void StateEnterPacePasswordIfd::onEntry(QEvent* pEvent) if (getContext() && getContext()->getIfdServer() && getContext()->getIfdServer()->getMessageHandler()) { const auto& handler = getContext()->getIfdServer()->getMessageHandler(); - *this << connect(handler.data(), &ServerMessageHandler::destroyed, this, &StateEnterPacePasswordIfd::onCancelEstablishPaceChannel); + *this << connect(handler.data(), &ServerMessageHandler::destroyed, this, &StateEnterPacePasswordIfd::onUserError); } - *this << connect(getContext().data(), &IfdServiceContext::fireCancelPasswordRequest, this, &StateEnterPacePasswordIfd::onCancelEstablishPaceChannel); + *this << connect(getContext().data(), &IfdServiceContext::fireUserError, this, &StateEnterPacePasswordIfd::onUserError); } diff --git a/src/workflows/ifd/states/StateEnterPacePasswordIfd.h b/src/workflows/ifd/states/StateEnterPacePasswordIfd.h index cbf6fc9b2..808ddca31 100644 --- a/src/workflows/ifd/states/StateEnterPacePasswordIfd.h +++ b/src/workflows/ifd/states/StateEnterPacePasswordIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -8,6 +8,10 @@ #include "states/AbstractState.h" #include "states/GenericContextContainer.h" + +class test_StateEnterPacePasswordIfd; + + namespace governikus { @@ -17,13 +21,14 @@ class StateEnterPacePasswordIfd { Q_OBJECT friend class StateBuilder; + friend class ::test_StateEnterPacePasswordIfd; private: explicit StateEnterPacePasswordIfd(const QSharedPointer& pContext); void run() override; private Q_SLOTS: - void onCancelEstablishPaceChannel(); + void onUserError(); public: void onEntry(QEvent* pEvent) override; diff --git a/src/workflows/ifd/states/StateEstablishPaceChannelIfd.cpp b/src/workflows/ifd/states/StateEstablishPaceChannelIfd.cpp index eeb34a820..9e9bf3720 100644 --- a/src/workflows/ifd/states/StateEstablishPaceChannelIfd.cpp +++ b/src/workflows/ifd/states/StateEstablishPaceChannelIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEstablishPaceChannelIfd.h" diff --git a/src/workflows/ifd/states/StateEstablishPaceChannelIfd.h b/src/workflows/ifd/states/StateEstablishPaceChannelIfd.h index 70cf3c38c..eefefc794 100644 --- a/src/workflows/ifd/states/StateEstablishPaceChannelIfd.h +++ b/src/workflows/ifd/states/StateEstablishPaceChannelIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StateEstablishPaceChannelResponse.cpp b/src/workflows/ifd/states/StateEstablishPaceChannelResponse.cpp index 000155863..5f287b075 100644 --- a/src/workflows/ifd/states/StateEstablishPaceChannelResponse.cpp +++ b/src/workflows/ifd/states/StateEstablishPaceChannelResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateEstablishPaceChannelResponse.h" diff --git a/src/workflows/ifd/states/StateEstablishPaceChannelResponse.h b/src/workflows/ifd/states/StateEstablishPaceChannelResponse.h index c3d50aa02..e4c77ea3c 100644 --- a/src/workflows/ifd/states/StateEstablishPaceChannelResponse.h +++ b/src/workflows/ifd/states/StateEstablishPaceChannelResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StatePrepareChangePinIfd.cpp b/src/workflows/ifd/states/StatePrepareChangePinIfd.cpp index 78222662b..00c41b11c 100644 --- a/src/workflows/ifd/states/StatePrepareChangePinIfd.cpp +++ b/src/workflows/ifd/states/StatePrepareChangePinIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePrepareChangePinIfd.h" diff --git a/src/workflows/ifd/states/StatePrepareChangePinIfd.h b/src/workflows/ifd/states/StatePrepareChangePinIfd.h index a7cb2f048..129a65bc3 100644 --- a/src/workflows/ifd/states/StatePrepareChangePinIfd.h +++ b/src/workflows/ifd/states/StatePrepareChangePinIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/ifd/states/StatePreparePaceIfd.cpp b/src/workflows/ifd/states/StatePreparePaceIfd.cpp index 77dad393a..681cb3a84 100644 --- a/src/workflows/ifd/states/StatePreparePaceIfd.cpp +++ b/src/workflows/ifd/states/StatePreparePaceIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePreparePaceIfd.h" diff --git a/src/workflows/ifd/states/StatePreparePaceIfd.h b/src/workflows/ifd/states/StatePreparePaceIfd.h index 7f736274c..177f7423f 100644 --- a/src/workflows/ifd/states/StatePreparePaceIfd.h +++ b/src/workflows/ifd/states/StatePreparePaceIfd.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/ifd/states/StateProcessIfdMessages.cpp b/src/workflows/ifd/states/StateProcessIfdMessages.cpp index 68e721bc0..ad51260ff 100644 --- a/src/workflows/ifd/states/StateProcessIfdMessages.cpp +++ b/src/workflows/ifd/states/StateProcessIfdMessages.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateProcessIfdMessages.h" @@ -52,13 +52,13 @@ void StateProcessIfdMessages::onMessageHandlerAdded(const QSharedPointergetIfdServer()->isPairingConnection()) { - Env::getSingleton()->startScan(ReaderManagerPlugInType::SMART); + Env::getSingleton()->startScan(ReaderManagerPluginType::SMART); } else { - Env::getSingleton()->stopScan(ReaderManagerPlugInType::SMART); + Env::getSingleton()->stopScan(ReaderManagerPluginType::SMART); } } diff --git a/src/workflows/ifd/states/StateProcessIfdMessages.h b/src/workflows/ifd/states/StateProcessIfdMessages.h index d1671f0fd..3e60d3765 100644 --- a/src/workflows/ifd/states/StateProcessIfdMessages.h +++ b/src/workflows/ifd/states/StateProcessIfdMessages.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -30,7 +30,7 @@ class StateProcessIfdMessages private: bool mResetContextOnDisconnect; - QVector mMessageConnections; + QList mMessageConnections; explicit StateProcessIfdMessages(const QSharedPointer& pContext); void run() override; diff --git a/src/workflows/ifd/states/StateStartIfdService.cpp b/src/workflows/ifd/states/StateStartIfdService.cpp index 169ebcac6..fc50e9fd1 100644 --- a/src/workflows/ifd/states/StateStartIfdService.cpp +++ b/src/workflows/ifd/states/StateStartIfdService.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStartIfdService.h" @@ -25,7 +25,7 @@ void StateStartIfdService::run() QSharedPointer server = context->getIfdServer(); Q_ASSERT(server); - const auto& serverName = Env::getSingleton()->getRemoteServiceSettings().getServerName(); + const auto& serverName = Env::getSingleton()->getRemoteServiceSettings().getDeviceName(); if (!server->isRunning() && !server->start(serverName)) { qCCritical(statemachine) << "Cannot start IfdServer."; diff --git a/src/workflows/ifd/states/StateStartIfdService.h b/src/workflows/ifd/states/StateStartIfdService.h index 22d6efd38..90ebd1ff3 100644 --- a/src/workflows/ifd/states/StateStartIfdService.h +++ b/src/workflows/ifd/states/StateStartIfdService.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/ifd/states/StateStopIfdService.cpp b/src/workflows/ifd/states/StateStopIfdService.cpp index a27165588..aa7ba78c0 100644 --- a/src/workflows/ifd/states/StateStopIfdService.cpp +++ b/src/workflows/ifd/states/StateStopIfdService.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStopIfdService.h" @@ -33,7 +33,7 @@ void StateStopIfdService::onExit(QEvent* pEvent) server->stop(); stopNfcScanIfNecessary(); - Env::getSingleton()->stopScan(ReaderManagerPlugInType::SMART); + Env::getSingleton()->stopScan(ReaderManagerPluginType::SMART); AbstractState::onExit(pEvent); } diff --git a/src/workflows/ifd/states/StateStopIfdService.h b/src/workflows/ifd/states/StateStopIfdService.h index a40912aa8..be39d70b8 100644 --- a/src/workflows/ifd/states/StateStopIfdService.h +++ b/src/workflows/ifd/states/StateStopIfdService.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/context/PersonalizationContext.cpp b/src/workflows/personalization/context/PersonalizationContext.cpp index f7946d650..af1446ed7 100644 --- a/src/workflows/personalization/context/PersonalizationContext.cpp +++ b/src/workflows/personalization/context/PersonalizationContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -189,7 +189,7 @@ QUrl PersonalizationContext::getAppletServiceUrl(const QString& pArg) const } -QVector PersonalizationContext::getAcceptedEidTypes() const +QList PersonalizationContext::getAcceptedEidTypes() const { if (!getDidAuthenticateEac1()) { diff --git a/src/workflows/personalization/context/PersonalizationContext.h b/src/workflows/personalization/context/PersonalizationContext.h index 3c77a869f..a6daac4c4 100644 --- a/src/workflows/personalization/context/PersonalizationContext.h +++ b/src/workflows/personalization/context/PersonalizationContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -79,7 +79,7 @@ class PersonalizationContext [[nodiscard]] QUrl getAppletServiceUrl(const QString& pArg) const; - [[nodiscard]] QVector getAcceptedEidTypes() const override; + [[nodiscard]] QList getAcceptedEidTypes() const override; using WorkflowContext::setProgress; void setProgress(int pProgress, const QString& pMessage, int pInitialValue, int pMaxValue = 100); diff --git a/src/workflows/personalization/controller/PersonalizationController.cpp b/src/workflows/personalization/controller/PersonalizationController.cpp index df5e2ea93..e400a4d3b 100644 --- a/src/workflows/personalization/controller/PersonalizationController.cpp +++ b/src/workflows/personalization/controller/PersonalizationController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/PersonalizationController.h" diff --git a/src/workflows/personalization/controller/PersonalizationController.h b/src/workflows/personalization/controller/PersonalizationController.h index e52bc0aeb..fe371e564 100644 --- a/src/workflows/personalization/controller/PersonalizationController.h +++ b/src/workflows/personalization/controller/PersonalizationController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/CompositeStatePrepareApplet.cpp b/src/workflows/personalization/states/CompositeStatePrepareApplet.cpp index 5081eb653..6a6b06891 100644 --- a/src/workflows/personalization/states/CompositeStatePrepareApplet.cpp +++ b/src/workflows/personalization/states/CompositeStatePrepareApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ #include "CompositeStatePrepareApplet.h" @@ -19,11 +19,11 @@ CompositeStatePrepareApplet::CompositeStatePrepareApplet(const QSharedPointer(mContext); - auto sInstallApplet = StateBuilder::createState(mContext); - auto sDeletePersonalization = StateBuilder::createState(mContext); - auto sDeleteApplet = StateBuilder::createState(mContext); - auto sUpdateSupportInfo = StateBuilder::createState(mContext); + auto* sCheckApplet = StateBuilder::createState(mContext); + auto* sInstallApplet = StateBuilder::createState(mContext); + auto* sDeletePersonalization = StateBuilder::createState(mContext); + auto* sDeleteApplet = StateBuilder::createState(mContext); + auto* sUpdateSupportInfo = StateBuilder::createState(mContext); sCheckApplet->setParent(this); sInstallApplet->setParent(this); diff --git a/src/workflows/personalization/states/CompositeStatePrepareApplet.h b/src/workflows/personalization/states/CompositeStatePrepareApplet.h index 1eb90183c..7158d3194 100644 --- a/src/workflows/personalization/states/CompositeStatePrepareApplet.h +++ b/src/workflows/personalization/states/CompositeStatePrepareApplet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/personalization/states/StateChangeSmartPin.cpp b/src/workflows/personalization/states/StateChangeSmartPin.cpp index 8a4c2f63f..1670cb396 100644 --- a/src/workflows/personalization/states/StateChangeSmartPin.cpp +++ b/src/workflows/personalization/states/StateChangeSmartPin.cpp @@ -1,11 +1,11 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateChangeSmartPin.h" #include "AppSettings.h" -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include "VolatileSettings.h" @@ -60,7 +60,7 @@ void StateChangeSmartPin::onSetEidPinDone(QSharedPointer pComma context->setProgress(100, context->getProgressMessage()); GeneralSettings& settings = Env::getSingleton()->getGeneralSettings(); - settings.setLastReaderPluginType(getEnumName(ReaderManagerPlugInType::SMART)); + settings.setLastReaderPluginType(getEnumName(ReaderManagerPluginType::SMART)); Q_EMIT fireContinue(); break; diff --git a/src/workflows/personalization/states/StateChangeSmartPin.h b/src/workflows/personalization/states/StateChangeSmartPin.h index d3b078dec..90cd1a625 100644 --- a/src/workflows/personalization/states/StateChangeSmartPin.h +++ b/src/workflows/personalization/states/StateChangeSmartPin.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateCheckApplet.cpp b/src/workflows/personalization/states/StateCheckApplet.cpp index 28b338369..781218708 100644 --- a/src/workflows/personalization/states/StateCheckApplet.cpp +++ b/src/workflows/personalization/states/StateCheckApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCheckApplet.h" diff --git a/src/workflows/personalization/states/StateCheckApplet.h b/src/workflows/personalization/states/StateCheckApplet.h index 45aaab78f..a663cf31e 100644 --- a/src/workflows/personalization/states/StateCheckApplet.h +++ b/src/workflows/personalization/states/StateCheckApplet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateCheckStatus.cpp b/src/workflows/personalization/states/StateCheckStatus.cpp index cda42d0e8..161d20ea4 100644 --- a/src/workflows/personalization/states/StateCheckStatus.cpp +++ b/src/workflows/personalization/states/StateCheckStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateCheckStatus.h" @@ -18,7 +18,7 @@ StateCheckStatus::StateCheckStatus(const QSharedPointer& pConte void StateCheckStatus::run() { - const auto smartInfo = Env::getSingleton()->getPlugInInfo(ReaderManagerPlugInType::SMART); + const auto smartInfo = Env::getSingleton()->getPluginInfo(ReaderManagerPluginType::SMART); if (smartInfo.isAvailable()) { Q_EMIT fireContinue(); diff --git a/src/workflows/personalization/states/StateCheckStatus.h b/src/workflows/personalization/states/StateCheckStatus.h index ac35fd7cc..50d75ea5c 100644 --- a/src/workflows/personalization/states/StateCheckStatus.h +++ b/src/workflows/personalization/states/StateCheckStatus.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateDeleteApplet.cpp b/src/workflows/personalization/states/StateDeleteApplet.cpp index 94db27214..1800aa7dc 100644 --- a/src/workflows/personalization/states/StateDeleteApplet.cpp +++ b/src/workflows/personalization/states/StateDeleteApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateDeleteApplet.h" diff --git a/src/workflows/personalization/states/StateDeleteApplet.h b/src/workflows/personalization/states/StateDeleteApplet.h index a8e423df8..0d278005f 100644 --- a/src/workflows/personalization/states/StateDeleteApplet.h +++ b/src/workflows/personalization/states/StateDeleteApplet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateDeletePersonalization.cpp b/src/workflows/personalization/states/StateDeletePersonalization.cpp index f43aed230..2d2a2431f 100644 --- a/src/workflows/personalization/states/StateDeletePersonalization.cpp +++ b/src/workflows/personalization/states/StateDeletePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateDeletePersonalization.h" diff --git a/src/workflows/personalization/states/StateDeletePersonalization.h b/src/workflows/personalization/states/StateDeletePersonalization.h index 4670f345b..a1e2adecc 100644 --- a/src/workflows/personalization/states/StateDeletePersonalization.h +++ b/src/workflows/personalization/states/StateDeletePersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateFinalizePersonalization.cpp b/src/workflows/personalization/states/StateFinalizePersonalization.cpp index 78a081af4..8ce53c917 100644 --- a/src/workflows/personalization/states/StateFinalizePersonalization.cpp +++ b/src/workflows/personalization/states/StateFinalizePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateFinalizePersonalization.h" diff --git a/src/workflows/personalization/states/StateFinalizePersonalization.h b/src/workflows/personalization/states/StateFinalizePersonalization.h index 474f5f85d..31e5adfe3 100644 --- a/src/workflows/personalization/states/StateFinalizePersonalization.h +++ b/src/workflows/personalization/states/StateFinalizePersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateGetChallenge.cpp b/src/workflows/personalization/states/StateGetChallenge.cpp index ab4664073..c5f94be68 100644 --- a/src/workflows/personalization/states/StateGetChallenge.cpp +++ b/src/workflows/personalization/states/StateGetChallenge.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGetChallenge.h" diff --git a/src/workflows/personalization/states/StateGetChallenge.h b/src/workflows/personalization/states/StateGetChallenge.h index dbd2c3fa8..45889bc39 100644 --- a/src/workflows/personalization/states/StateGetChallenge.h +++ b/src/workflows/personalization/states/StateGetChallenge.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateGetServiceInformation.cpp b/src/workflows/personalization/states/StateGetServiceInformation.cpp index da65c4031..ba602f8d3 100644 --- a/src/workflows/personalization/states/StateGetServiceInformation.cpp +++ b/src/workflows/personalization/states/StateGetServiceInformation.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGetServiceInformation.h" diff --git a/src/workflows/personalization/states/StateGetServiceInformation.h b/src/workflows/personalization/states/StateGetServiceInformation.h index 77e356a9d..750966f13 100644 --- a/src/workflows/personalization/states/StateGetServiceInformation.h +++ b/src/workflows/personalization/states/StateGetServiceInformation.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateGetSessionId.cpp b/src/workflows/personalization/states/StateGetSessionId.cpp index 183200ae5..28835e079 100644 --- a/src/workflows/personalization/states/StateGetSessionId.cpp +++ b/src/workflows/personalization/states/StateGetSessionId.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGetSessionId.h" diff --git a/src/workflows/personalization/states/StateGetSessionId.h b/src/workflows/personalization/states/StateGetSessionId.h index 65315e009..d093587e5 100644 --- a/src/workflows/personalization/states/StateGetSessionId.h +++ b/src/workflows/personalization/states/StateGetSessionId.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateInitializePersonalization.cpp b/src/workflows/personalization/states/StateInitializePersonalization.cpp index a18bd3fda..5d1ddb952 100644 --- a/src/workflows/personalization/states/StateInitializePersonalization.cpp +++ b/src/workflows/personalization/states/StateInitializePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateInitializePersonalization.h" diff --git a/src/workflows/personalization/states/StateInitializePersonalization.h b/src/workflows/personalization/states/StateInitializePersonalization.h index a30fd8d5d..db239df68 100644 --- a/src/workflows/personalization/states/StateInitializePersonalization.h +++ b/src/workflows/personalization/states/StateInitializePersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateInsertCard.cpp b/src/workflows/personalization/states/StateInsertCard.cpp index a80e243c4..c178a7896 100644 --- a/src/workflows/personalization/states/StateInsertCard.cpp +++ b/src/workflows/personalization/states/StateInsertCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateInsertCard.h" @@ -30,7 +30,7 @@ void StateInsertCard::run() { auto* readerManager = Env::getSingleton(); - const auto& readerInfos = readerManager->getReaderInfos(ReaderFilter({ReaderManagerPlugInType::SMART})); + const auto& readerInfos = readerManager->getReaderInfos(ReaderFilter({ReaderManagerPluginType::SMART})); if (readerInfos.isEmpty()) { qCWarning(statemachine) << "No Smart reader present"; @@ -46,10 +46,10 @@ void StateInsertCard::run() return; } - getContext()->setReaderPlugInTypes({ReaderManagerPlugInType::SMART}); + getContext()->setReaderPluginTypes({ReaderManagerPluginType::SMART}); *this << connect(readerManager, &ReaderManager::fireCardInfoChanged, this, &StateInsertCard::onCardInfoChanged); *this << connect(readerManager, &ReaderManager::fireStatusChanged, this, &StateInsertCard::onStatusChanged); - readerManager->startScan(ReaderManagerPlugInType::SMART); + readerManager->startScan(ReaderManagerPluginType::SMART); return; } #endif @@ -60,7 +60,7 @@ void StateInsertCard::run() void StateInsertCard::onCardInfoChanged(const ReaderInfo& pInfo) { - if (pInfo.getPlugInType() != ReaderManagerPlugInType::SMART) + if (pInfo.getPluginType() != ReaderManagerPluginType::SMART) { return; } @@ -96,9 +96,9 @@ void StateInsertCard::onCardInfoChanged(const ReaderInfo& pInfo) } -void StateInsertCard::onStatusChanged(const ReaderManagerPlugInInfo& pInfo) +void StateInsertCard::onStatusChanged(const ReaderManagerPluginInfo& pInfo) { - if (pInfo.getPlugInType() != ReaderManagerPlugInType::SMART) + if (pInfo.getPluginType() != ReaderManagerPluginType::SMART) { return; } diff --git a/src/workflows/personalization/states/StateInsertCard.h b/src/workflows/personalization/states/StateInsertCard.h index bb9f86bab..0e9457d1d 100644 --- a/src/workflows/personalization/states/StateInsertCard.h +++ b/src/workflows/personalization/states/StateInsertCard.h @@ -1,10 +1,10 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once -#include "ReaderManagerPlugInInfo.h" +#include "ReaderManagerPluginInfo.h" #include "context/PersonalizationContext.h" #include "states/AbstractState.h" #include "states/GenericContextContainer.h" @@ -28,7 +28,7 @@ class StateInsertCard private Q_SLOTS: void onCardInfoChanged(const ReaderInfo& pInfo); - void onStatusChanged(const ReaderManagerPlugInInfo& pInfo); + void onStatusChanged(const ReaderManagerPluginInfo& pInfo); Q_SIGNALS: void fireSkipPinChange(); diff --git a/src/workflows/personalization/states/StateInstallApplet.cpp b/src/workflows/personalization/states/StateInstallApplet.cpp index 50c965e2c..2ae6f0c6a 100644 --- a/src/workflows/personalization/states/StateInstallApplet.cpp +++ b/src/workflows/personalization/states/StateInstallApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateInstallApplet.h" diff --git a/src/workflows/personalization/states/StateInstallApplet.h b/src/workflows/personalization/states/StateInstallApplet.h index c3729dff8..d4dda27eb 100644 --- a/src/workflows/personalization/states/StateInstallApplet.h +++ b/src/workflows/personalization/states/StateInstallApplet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.cpp b/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.cpp index fa05cb891..2858afeeb 100644 --- a/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.cpp +++ b/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateLoadSmartTcTokenUrl.h" diff --git a/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.h b/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.h index 69678e829..82775ebea 100644 --- a/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.h +++ b/src/workflows/personalization/states/StateLoadSmartTcTokenUrl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StatePreparePersonalization.cpp b/src/workflows/personalization/states/StatePreparePersonalization.cpp index d3eb2c8c1..2f10dcffe 100644 --- a/src/workflows/personalization/states/StatePreparePersonalization.cpp +++ b/src/workflows/personalization/states/StatePreparePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StatePreparePersonalization.h" diff --git a/src/workflows/personalization/states/StatePreparePersonalization.h b/src/workflows/personalization/states/StatePreparePersonalization.h index 102e57077..6f48f73ae 100644 --- a/src/workflows/personalization/states/StatePreparePersonalization.h +++ b/src/workflows/personalization/states/StatePreparePersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateSendStartPaosPersonalization.cpp b/src/workflows/personalization/states/StateSendStartPaosPersonalization.cpp index 27af1fef8..606ccb186 100644 --- a/src/workflows/personalization/states/StateSendStartPaosPersonalization.cpp +++ b/src/workflows/personalization/states/StateSendStartPaosPersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ diff --git a/src/workflows/personalization/states/StateSendStartPaosPersonalization.h b/src/workflows/personalization/states/StateSendStartPaosPersonalization.h index 4a857c95f..44c0c73cc 100644 --- a/src/workflows/personalization/states/StateSendStartPaosPersonalization.h +++ b/src/workflows/personalization/states/StateSendStartPaosPersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.cpp b/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.cpp index 6a28a55c2..20019615e 100644 --- a/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.cpp +++ b/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ diff --git a/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.h b/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.h index d16192ba6..66c98ad88 100644 --- a/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.h +++ b/src/workflows/personalization/states/StateSendTransmitResponsePersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/personalization/states/StateStartPaosPersonalization.cpp b/src/workflows/personalization/states/StateStartPaosPersonalization.cpp index 3a3131acb..fbb3b52d3 100644 --- a/src/workflows/personalization/states/StateStartPaosPersonalization.cpp +++ b/src/workflows/personalization/states/StateStartPaosPersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStartPaosPersonalization.h" diff --git a/src/workflows/personalization/states/StateStartPaosPersonalization.h b/src/workflows/personalization/states/StateStartPaosPersonalization.h index de2c23e98..5d151ed09 100644 --- a/src/workflows/personalization/states/StateStartPaosPersonalization.h +++ b/src/workflows/personalization/states/StateStartPaosPersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.cpp b/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.cpp index 36682365c..ce4de680d 100644 --- a/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.cpp +++ b/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateStartPaosPersonalizationResponse.h" diff --git a/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.h b/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.h index 707b67c04..b83f31b71 100644 --- a/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.h +++ b/src/workflows/personalization/states/StateStartPaosPersonalizationResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateTransmitPersonalization.cpp b/src/workflows/personalization/states/StateTransmitPersonalization.cpp index 2cda55d78..b82da27fe 100644 --- a/src/workflows/personalization/states/StateTransmitPersonalization.cpp +++ b/src/workflows/personalization/states/StateTransmitPersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateTransmitPersonalization.h" diff --git a/src/workflows/personalization/states/StateTransmitPersonalization.h b/src/workflows/personalization/states/StateTransmitPersonalization.h index 1cc6f51f0..b1646730b 100644 --- a/src/workflows/personalization/states/StateTransmitPersonalization.h +++ b/src/workflows/personalization/states/StateTransmitPersonalization.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/personalization/states/StateUpdateSupportInfo.cpp b/src/workflows/personalization/states/StateUpdateSupportInfo.cpp index f93728a3a..35b8e9caa 100644 --- a/src/workflows/personalization/states/StateUpdateSupportInfo.cpp +++ b/src/workflows/personalization/states/StateUpdateSupportInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "StateUpdateSupportInfo.h" diff --git a/src/workflows/personalization/states/StateUpdateSupportInfo.h b/src/workflows/personalization/states/StateUpdateSupportInfo.h index ed1754765..3abb6d2fa 100644 --- a/src/workflows/personalization/states/StateUpdateSupportInfo.h +++ b/src/workflows/personalization/states/StateUpdateSupportInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/selfauth/SelfAuthenticationData.cpp b/src/workflows/selfauth/SelfAuthenticationData.cpp index 9d6b930c0..9b7b091a8 100644 --- a/src/workflows/selfauth/SelfAuthenticationData.cpp +++ b/src/workflows/selfauth/SelfAuthenticationData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "SelfAuthenticationData.h" @@ -11,6 +11,7 @@ Q_DECLARE_LOGGING_CATEGORY(secure) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -236,7 +237,7 @@ void SelfAuthenticationData::SelfData::addAddress(OrderedSelfData& pSelfData) co if (!getValue(SelfAuthData::PlaceOfResidenceZipCode).isNull() || !getValue(SelfAuthData::PlaceOfResidenceCity).isNull()) { //: LABEL ALL_PLATFORMS - add(pSelfData, getValue(SelfAuthData::PlaceOfResidenceStreet).isNull() ? tr("Address") : QString(), getValue(SelfAuthData::PlaceOfResidenceZipCode) + QLatin1Char(' ') + getValue(SelfAuthData::PlaceOfResidenceCity)); + add(pSelfData, getValue(SelfAuthData::PlaceOfResidenceStreet).isNull() ? tr("Address") : QString(), getValue(SelfAuthData::PlaceOfResidenceZipCode) + ' '_L1 + getValue(SelfAuthData::PlaceOfResidenceCity)); } if (!getValue(SelfAuthData::PlaceOfResidenceCountry).isNull()) { @@ -247,21 +248,23 @@ void SelfAuthenticationData::SelfData::addAddress(OrderedSelfData& pSelfData) co QString SelfAuthenticationData::SelfData::formatDate(const QString& pDate) { - static const QVector> formattingPattern({ + static const QList> formattingPattern({ //: LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString qMakePair(QStringLiteral("yyyy-MM-dd+hh:mm"), QLatin1String(QT_TR_NOOP("dd.MM.yyyy"))), //: LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day qMakePair(QStringLiteral("yyyy-MM"), QLatin1String(QT_TR_NOOP("xx.MM.yyyy"))), + //: LABEL ALL_PLATFORMS Additional date format with unknown day + qMakePair(QStringLiteral("yyyyMM"), QLatin1String(QT_TR_NOOP("xx.MM.yyyy"))), //: LABEL ALL_PLATFORMS Date format according to https://doc.qt.io/qt/qdate.html#toString with unknown day and month qMakePair(QStringLiteral("yyyy"), QLatin1String(QT_TR_NOOP("xx.xx.yyyy"))), }); - for (const auto& entry : formattingPattern) + for (const auto& [key, value] : formattingPattern) { - const QDateTime dateTime = QDateTime::fromString(pDate, entry.first); + const QDateTime dateTime = QDateTime::fromString(pDate, key); if (dateTime.isValid()) { - return LanguageLoader::getInstance().getUsedLocale().toString(dateTime, tr(entry.second.data())); + return LanguageLoader::getInstance().getUsedLocale().toString(dateTime, tr(value.data())); } } diff --git a/src/workflows/selfauth/SelfAuthenticationData.h b/src/workflows/selfauth/SelfAuthenticationData.h index 3b32640c9..2aa25f8f7 100644 --- a/src/workflows/selfauth/SelfAuthenticationData.h +++ b/src/workflows/selfauth/SelfAuthenticationData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include #include -#include namespace governikus { @@ -60,7 +60,7 @@ defineEnumType(SelfAuthData, class SelfAuthenticationData { public: - using OrderedSelfData = QVector>; + using OrderedSelfData = QList>; private: class SelfData diff --git a/src/workflows/selfauth/context/SelfAuthContext.cpp b/src/workflows/selfauth/context/SelfAuthContext.cpp index 959f5a7cd..d6728f8b7 100644 --- a/src/workflows/selfauth/context/SelfAuthContext.cpp +++ b/src/workflows/selfauth/context/SelfAuthContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "SelfAuthContext.h" diff --git a/src/workflows/selfauth/context/SelfAuthContext.h b/src/workflows/selfauth/context/SelfAuthContext.h index 5be846226..f143c17bd 100644 --- a/src/workflows/selfauth/context/SelfAuthContext.h +++ b/src/workflows/selfauth/context/SelfAuthContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/selfauth/controller/SelfAuthController.cpp b/src/workflows/selfauth/controller/SelfAuthController.cpp index b7f085be0..6599bc917 100644 --- a/src/workflows/selfauth/controller/SelfAuthController.cpp +++ b/src/workflows/selfauth/controller/SelfAuthController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/SelfAuthController.h" diff --git a/src/workflows/selfauth/controller/SelfAuthController.h b/src/workflows/selfauth/controller/SelfAuthController.h index be0f0503b..3cbb3db4f 100644 --- a/src/workflows/selfauth/controller/SelfAuthController.h +++ b/src/workflows/selfauth/controller/SelfAuthController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/selfauth/states/StateGetSelfAuthenticationData.cpp b/src/workflows/selfauth/states/StateGetSelfAuthenticationData.cpp index fddd0e6f6..0c521a354 100644 --- a/src/workflows/selfauth/states/StateGetSelfAuthenticationData.cpp +++ b/src/workflows/selfauth/states/StateGetSelfAuthenticationData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateGetSelfAuthenticationData.h" diff --git a/src/workflows/selfauth/states/StateGetSelfAuthenticationData.h b/src/workflows/selfauth/states/StateGetSelfAuthenticationData.h index 62e4fae7b..2fb0c2d93 100644 --- a/src/workflows/selfauth/states/StateGetSelfAuthenticationData.h +++ b/src/workflows/selfauth/states/StateGetSelfAuthenticationData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/src/workflows/selfauth/states/StateLoadTcTokenUrl.cpp b/src/workflows/selfauth/states/StateLoadTcTokenUrl.cpp index 5c5303330..8dfaa880b 100644 --- a/src/workflows/selfauth/states/StateLoadTcTokenUrl.cpp +++ b/src/workflows/selfauth/states/StateLoadTcTokenUrl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "StateLoadTcTokenUrl.h" diff --git a/src/workflows/selfauth/states/StateLoadTcTokenUrl.h b/src/workflows/selfauth/states/StateLoadTcTokenUrl.h index 433158a8c..5b207705e 100644 --- a/src/workflows/selfauth/states/StateLoadTcTokenUrl.h +++ b/src/workflows/selfauth/states/StateLoadTcTokenUrl.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 29018e85b..5a0514a06 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,33 +4,25 @@ function(EXTRACT_TESTNAME result filepath) string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" testname ${testname}) string(REPLACE "/" "_" testname ${testname}) string(REPLACE "+" "" testname ${testname}) - string(REPLACE "_test_" "_" testname ${testname}) + string(REPLACE "test_" "" testname ${testname}) set(${result} "Test_${testname}" PARENT_SCOPE) endfunction() function(GET_TEST_CMDLINE cmdline testname) - cmake_parse_arguments(_PARAM "" "" "SELECTORS" ${ARGN}) - - foreach(SELECTOR ${_PARAM_SELECTORS}) - set(testname "${testname}_${SELECTOR}") - endforeach() - set(${cmdline} ${PLATFORM} -v2 -o ${CMAKE_CURRENT_BINARY_DIR}/results.${testname}.log.xml,xml -o -,txt PARENT_SCOPE) endfunction() function(GET_TEST_ENV testenv testname) - set(IS_QML_TEST "${testname}" MATCHES "qml") - set(IS_GUI_TEST IS_QML_TEST) + set(IS_GUI_TEST "${testname}" MATCHES "qml") if(NOT WIN32 AND IS_GUI_TEST) list(APPEND ENV "QT_QPA_PLATFORM=offscreen") list(APPEND ENV "QT_QPA_OFFSCREEN_NO_GLX=1") endif() - set(IS_FLAKY_QT5_TEST "${testname}" MATCHES "UIPlugInWebSocket") # Emasculate ASAN since Qt causes problems - if(IS_GUI_TEST OR (QT5 AND IS_FLAKY_QT5_TEST)) + if(IS_GUI_TEST) list(APPEND ENV "ASAN_OPTIONS=detect_leaks=0") endif() @@ -42,28 +34,28 @@ function(GET_TEST_ENV testenv testname) if((LINUX OR BSD) AND "${testname}" MATCHES "card_pcsc_PcscReader") list(APPEND ENV "ASAN_OPTIONS=verify_asan_link_order=0") - list(APPEND ENV "LD_PRELOAD=${PROJECT_BINARY_DIR}/test/helper/pcsc/libPcsc.so") + list(APPEND ENV "LD_PRELOAD=${PROJECT_BINARY_DIR}/test/helper/pcsc/libAusweisAppTestHelperPcsc.so") endif() set(${testenv} "${ENV}" PARENT_SCOPE) endfunction() -function(ADD_QML_TEST _sourcefile) - cmake_parse_arguments(_PARAM "" "" "SELECTORS" ${ARGN}) - +function(ADD_QML_TEST _sourcefile _platform) EXTRACT_TESTNAME(TESTNAME ${_sourcefile}) - GET_TEST_CMDLINE(CMD_PARAMS ${TESTNAME} SELECTORS ${_PARAM_SELECTORS}) - set(CMD $ ${CMD_PARAMS} -input ${sourcefile} -import "qrc:///qml/") - - if(_PARAM_SELECTORS) - foreach(_PARAM_SELECTOR_LIST_ENTRY ${_PARAM_SELECTORS}) - set(TESTNAME ${TESTNAME}_${_PARAM_SELECTOR_LIST_ENTRY}) - set(CMD ${CMD} -file-selector ${_PARAM_SELECTOR_LIST_ENTRY}) - endforeach() + if(NOT _platform STREQUAL "") + set(TESTNAME ${TESTNAME}_${_platform}) + endif() + + GET_TEST_CMDLINE(CMD_PARAMS ${TESTNAME}) + if(QT_VERSION VERSION_LESS "6.5") + set(CMD_PARAMS ${CMD_PARAMS} -import "qrc:/qt/qml") endif() + set(CMD_PARAMS ${CMD_PARAMS} -import "qrc:/qml") + set(CMD $ ${CMD_PARAMS} -input ${sourcefile}) GET_TEST_ENV(TESTENV ${TESTNAME}) + list(APPEND TESTENV "OVERRIDE_PLATFORM=${_platform}") add_test(NAME ${TESTNAME} COMMAND ${CMD}) set_tests_properties(${TESTNAME} PROPERTIES ENVIRONMENT "${TESTENV}") @@ -77,43 +69,46 @@ function(ADD_QML_TEST_FILES) return() endif() - set(qt_selector qt6) file(GLOB_RECURSE TEST_SUBFILES "${CMAKE_CURRENT_SOURCE_DIR}/test_*.qml") foreach(sourcefile ${TEST_SUBFILES}) string(REGEX MATCHALL "\\+[a-z]+" PLATFORM_FILTER ${sourcefile}) if(NOT "+mobile" IN_LIST PLATFORM_FILTER) - if(NOT "+mac" IN_LIST PLATFORM_FILTER) - ADD_QML_TEST(${sourcefile} SELECTORS "${qt_selector};desktop;win") - endif() - if(NOT "+win" IN_LIST PLATFORM_FILTER) - ADD_QML_TEST(${sourcefile} SELECTORS "${qt_selector};desktop;mac") - endif() + ADD_QML_TEST(${sourcefile} "") endif() if(NOT "+desktop" IN_LIST PLATFORM_FILTER) if(NOT "+ios" IN_LIST PLATFORM_FILTER) - ADD_QML_TEST(${sourcefile} SELECTORS "${qt_selector};mobile;android") + ADD_QML_TEST(${sourcefile} "android") endif() if(NOT "+android" IN_LIST PLATFORM_FILTER) - ADD_QML_TEST(${sourcefile} SELECTORS "${qt_selector};mobile;ios") + ADD_QML_TEST(${sourcefile} "ios") endif() endif() endforeach() endfunction() +add_subdirectory(tools) + +if(NOT TARGET ${Qt}::Test + OR IOS + OR ANDROID + OR NOT CMAKE_BUILD_TYPE STREQUAL DEBUG) + return() +endif() + qt_add_resources(QRC_FIXTURE "fixture/fixture.qrc" OPTIONS -compress-algo zlib) ADD_OBJECT_LIBRARY(QRC_FIXTURE_OBJ ${QRC_FIXTURE} ${Qt}::Core) add_subdirectory(helper) +add_subdirectory(qt) + if(TARGET ${Qt}::Qml AND TARGET ${Qt}::QuickTest) add_subdirectory(qml) endif() -add_subdirectory(qt) -add_subdirectory(json) -if(NOT INTEGRATED_SDK AND NOT IOS AND NOT ANDROID) +if(NOT INTEGRATED_SDK) add_subdirectory(integration) endif() -if(INTEGRATED_SDK AND NOT CONTAINER_SDK AND NOT ANDROID) +if(INTEGRATED_SDK AND NOT CONTAINER_SDK) add_subdirectory(integrated) endif() diff --git a/test/fixture/card/cvat-DEDEMODEV00038.hex b/test/fixture/card/cvat-DEDEMODEV00038.hex index b81a7f952..916ab386d 100644 --- a/test/fixture/card/cvat-DEDEMODEV00038.hex +++ b/test/fixture/card/cvat-DEDEMODEV00038.hex @@ -1 +1 @@ -7F218201487F4E8201005F2901004210444544566549444450535430303033357F494F060A04007F0007020202020386410400C7DEDB2117E45ACF998E9D3ED34883E0617D1614B60430CA1DF1D2ECC96BC214D97451588EF706DEAF7F68163F7C8EAADF9EA028F0F8BF5D0DD67B650907175F200E444544454D4F44455630303033387F4C12060904007F0007030102025305000513FF875F25060104000301035F2406010400040101655E732D060904007F000703010301802012CA9D0A51DF9297EABA7EBE9AB49DF2F4CF83E0DBB02772EFAD89C8AD75FCCD732D060904007F0007030103028020CB1E1940159F11DC96845B87C23B86F9BAA755A789A914BBD5B8FA9784019D1C5F37407AB2B3C8DE4B3F7136F7DA91CCAC25B26AEC5BC35AD0B603FA2FFE50CEA49F785614AD3FB2EFF1719971FBCABC95F95A9F601F9017BD73952B45E645B90B774F \ No newline at end of file +7f218201487f4e8201005f2901004210444544566549444450535430303033357f494f060a04007f0007020202020386410400c7dedb2117e45acf998e9d3ed34883e0617d1614b60430ca1df1d2ecc96bc214d97451588ef706deaf7f68163f7c8eaadf9ea028f0f8bf5d0dd67b650907175f200e444544454d4f44455630303033387f4c12060904007f0007030102025305000513ff875f25060104000301035f2406010400040101655e732d060904007f000703010301802012ca9d0a51df9297eaba7ebe9ab49df2f4cf83e0dbb02772efad89c8ad75fccd732d060904007f0007030103028020cb1e1940159f11dc96845b87c23b86f9baa755a789a914bbd5b8fa9784019d1c5f37407ab2b3c8de4b3f7136f7da91ccac25b26aec5bc35ad0b603fa2ffe50cea49f785614ad3fb2eff1719971fbcabc95f95a9f601f9017bd73952b45e645b90b774f diff --git a/test/fixture/card/cvdv-DEDVtIDGVK300029.hex b/test/fixture/card/cvdv-DEDVtIDGVK300029.hex new file mode 100644 index 000000000..9b63751a9 --- /dev/null +++ b/test/fixture/card/cvdv-DEDVtIDGVK300029.hex @@ -0,0 +1 @@ +7f2182017f7f4e8201375f29010042104445445674494447564b3330303032397f494f060a04007f00070202020203864104327560563d276d3f5e190196e264d0d391ac134aeb27e07250fa562096b14a8a169a298dc80285cb6e3133e0ffccde7964747d754dd356b4401df2cca7d43dc95f201044454250524c4f43414c3330303033377f4c12060904007f0007030102025305000713ff075f25060204000200015f2406020400030002658192732d060904007f0007030103018020315a1da468ae12c839f8ab386e5cab88c9ffac2033c9910e202e2004bde07fe6732d060904007f000703010302802039d51f1942520ae8ec7f5cc654e78a521d8c09f607cd9adf7bb9fdc5bffb90d77332060904007f000703010303a02580010d81205f2513575dd25b7c4b60d2aa66f489f26055dd90d4b6f5997e4e6ee75a89473a5f37406ae52f47b70da13b1114db0879d504aef804f8c353ffff253c65254897c3bf000f2bcc37a6550b921e9554185f6fa2e3d14658541b467fb480338faad2422e67 diff --git a/test/fixture/fixture.qrc b/test/fixture/fixture.qrc index edafb8f23..c773d86d1 100644 --- a/test/fixture/fixture.qrc +++ b/test/fixture/fixture.qrc @@ -61,6 +61,7 @@ card/cvdv-DEDVeIDDPST00035.hex card/cvdv-DEDVeIDDPST00039.hex card/cvdv-DEDVeIDDTR101415.hex + card/cvdv-DEDVtIDGVK300029.hex card/cvdv-DEDVtIDGVNK00005.hex card/efCardAccess.hex card/efCardSecurity.hex @@ -68,9 +69,6 @@ card/smartEfCardAccess.hex core/network/CERT_TLS_ESERVICE_1.der updatable-files/reader/img_ACS_ACR1252U.png - tctoken/ok.xml - tctoken/broken.xml - tctoken/withoutCommunicationErrorAddress.xml paos/DIDAuthenticateEAC1.xml paos/DIDAuthenticateEAC1_ordered_certificates.xml paos/DIDAuthenticateEAC1_template.xml @@ -80,6 +78,7 @@ paos/DIDAuthenticateEAC1_accessRightsEmpty.xml paos/DIDAuthenticateEAC1_accessRightsMissing.xml paos/DIDAuthenticateEAC1_TS_TA_2.1.1.xml + paos/DIDAuthenticateEAC1_htmlTransactionInfo.xml paos/DIDAuthenticateEAC2.xml paos/DIDAuthenticateEAC2_template.xml paos/DIDAuthenticateEAC2_template2.xml diff --git a/test/fixture/logfiles/auth.txt b/test/fixture/logfiles/auth.txt index 0208f4146..d5d044220 100644 --- a/test/fixture/logfiles/auth.txt +++ b/test/fixture/logfiles/auth.txt @@ -43,20 +43,20 @@ securestorage 2022.07.26 09:59:20.759 53857 I SecureStorage::load(secure_storage securestorage 2022.07.26 09:59:20.761 53857 I SecureStorage::load(secure_storage/SecureStorage.cpp:270) : SecureStorage successfully loaded default 2022.07.26 09:59:20.761 53857 AppController::clearCacheFolders(core/controller/AppController.cpp:504) : Try to find and clear cache folder default 2022.07.26 09:59:20.763 53857 AppController::clearCacheFolders(core/controller/AppController.cpp:531) : Cleared cache folder: "/home/BOSKG/schmertmann/.cache/Governikus GmbH & Co. KG/AusweisApp2" -default 2022.07.26 09:59:20.763 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::UILoader -gui 2022.07.26 09:59:20.763 53857 UILoader::load(ui/base/UILoader.cpp:89) : Try to load UI plugin: UIPlugInQml -gui 2022.07.26 09:59:20.763 53857 UILoader::load(ui/base/UILoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UIPlugIn","MetaData":{"default":true,"dependencies":[],"name":"UIPlugInQml"},"archlevel":1,"className":"UIPlugInQml","debug":true,"version":393984}) -default 2022.07.26 09:59:20.780 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UIPlugInQml -gui 2022.07.26 09:59:20.780 53857 UILoader::load(ui/base/UILoader.cpp:89) : Try to load UI plugin: UIPlugInWebSocket -gui 2022.07.26 09:59:20.780 53857 UILoader::load(ui/base/UILoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UIPlugIn","MetaData":{"default":true,"dependencies":["UIPlugInJsonApi"],"name":"UIPlugInWebSocket"},"archlevel":1,"className":"UIPlugInWebSocket","debug":true,"version":393984}) -gui 2022.07.26 09:59:20.780 53857 UILoader::load(ui/base/UILoader.cpp:89) : Try to load UI plugin: UIPlugInJson -gui 2022.07.26 09:59:20.781 53857 UILoader::load(ui/base/UILoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UIPlugIn","MetaData":{"dependencies":[],"name":"UIPlugInJson"},"archlevel":1,"className":"UIPlugInJson","debug":true,"version":393984}) -default 2022.07.26 09:59:20.781 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UIPlugInJson +default 2022.07.26 09:59:20.763 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::UiLoader +gui 2022.07.26 09:59:20.763 53857 UiLoader::load(ui/base/UiLoader.cpp:89) : Try to load UI plugin: UiPluginQml +gui 2022.07.26 09:59:20.763 53857 UiLoader::load(ui/base/UiLoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UiPlugin","MetaData":{"default":true,"dependencies":[],"name":"UiPluginQml"},"archlevel":1,"className":"UiPluginQml","debug":true,"version":393984}) +default 2022.07.26 09:59:20.780 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UiPluginQml +gui 2022.07.26 09:59:20.780 53857 UiLoader::load(ui/base/UiLoader.cpp:89) : Try to load UI plugin: UiPluginWebSocket +gui 2022.07.26 09:59:20.780 53857 UiLoader::load(ui/base/UiLoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UiPlugin","MetaData":{"default":true,"dependencies":["UiPluginJsonApi"],"name":"UiPluginWebSocket"},"archlevel":1,"className":"UiPluginWebSocket","debug":true,"version":393984}) +gui 2022.07.26 09:59:20.780 53857 UiLoader::load(ui/base/UiLoader.cpp:89) : Try to load UI plugin: UiPluginJson +gui 2022.07.26 09:59:20.781 53857 UiLoader::load(ui/base/UiLoader.cpp:97) : Load plugin: QJsonObject({"IID":"governikus.UiPlugin","MetaData":{"dependencies":[],"name":"UiPluginJson"},"archlevel":1,"className":"UiPluginJson","debug":true,"version":393984}) +default 2022.07.26 09:59:20.781 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UiPluginJson default 2022.07.26 09:59:20.781 53857 Env::getShared(global/Env.h:338) : Spawn shared instance: governikus::HttpServer network 2022.07.26 09:59:20.781 53857 HttpServer::HttpServer(network/HttpServer.cpp:43) : Listening on port: 24727 | QHostAddress("127.0.0.1") network 2022.07.26 09:59:20.781 53857 HttpServer::HttpServer(network/HttpServer.cpp:43) : Listening on port: 24727 | QHostAddress("::1") -websocket 2022.07.26 09:59:20.781 53857 ...ugInWebSocket::UIPlugInWebSocket(ui/websocket/UIPlugInWebSocket.cpp:48) : Enable WebSocket... -default 2022.07.26 09:59:20.781 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UIPlugInWebSocket +websocket 2022.07.26 09:59:20.781 53857 ...ugInWebSocket::UiPluginWebSocket(ui/websocket/UiPluginWebSocket.cpp:48) : Enable WebSocket... +default 2022.07.26 09:59:20.781 53857 AppController::onUiPlugin(core/controller/AppController.cpp:417) : Register UI: governikus::UiPluginWebSocket default 2022.07.26 09:59:20.781 53857 AppController::start(core/controller/AppController.cpp:147) : Successfully started activation handler: governikus::WebserviceActivationHandler default 2022.07.26 09:59:20.781 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::ReaderManager default 2022.07.26 09:59:20.781 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::RemoteIfdClient @@ -65,14 +65,14 @@ default 2022.07.26 09:59:20.781 53857 Env::createSingleton(global/Env.h: card 2022.07.26 09:59:20.781 53860 ReaderManagerWorker::onThreadStarted(card/base/ReaderManagerWorker.cpp:69) : Thread started default 2022.07.26 09:59:20.781 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::ApplicationModel network 2022.07.26 09:59:20.782 53857 WifiInfo::WifiInfo(network/WifiInfo_generic.cpp:21) : NOT IMPLEMENTED -card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugIns(card/base/ReaderManagerWorker.cpp:78) : Try to register plugins +card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugins(card/base/ReaderManagerWorker.cpp:78) : Try to register plugins default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::SelfAuthModel -card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugIns(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugIn","MetaData":{"dependencies":[],"name":"SimulatorReaderManagerPlugIn"},"archlevel":1,"className":"SimulatorReaderManagerPlugIn","debug":true,"version":393984}) +card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugins(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugin","MetaData":{"dependencies":[],"name":"SimulatorReaderManagerPlugin"},"archlevel":1,"className":"SimulatorReaderManagerPlugin","debug":true,"version":393984}) default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::RemoteServiceModel -card 2022.07.26 09:59:20.782 53860 ...::onSettingsChanged(card/simulator/SimulatorReaderManagerPlugIn.cpp:90) : SimulatorStateChanged: true -card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugIns(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugIn","MetaData":{"dependencies":[],"name":"RemoteIfdReaderManagerPlugIn"},"archlevel":1,"className":"RemoteIfdReaderManagerPlugIn","debug":true,"version":393984}) +card 2022.07.26 09:59:20.782 53860 ...::onSettingsChanged(card/simulator/SimulatorReaderManagerPlugin.cpp:90) : SimulatorStateChanged: true +card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugins(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugin","MetaData":{"dependencies":[],"name":"RemoteIfdReaderManagerPlugin"},"archlevel":1,"className":"RemoteIfdReaderManagerPlugin","debug":true,"version":393984}) default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::PersonalizationModel -card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugIns(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugIn","MetaData":{"dependencies":[],"name":"PcscReaderManagerPlugIn"},"archlevel":1,"className":"PcscReaderManagerPlugIn","debug":true,"version":393984}) +card 2022.07.26 09:59:20.782 53860 ReaderManagerWorker::registerPlugins(card/base/ReaderManagerWorker.cpp:84) : Register and initialize plugin: QJsonObject({"IID":"governikus.ReaderManagerPlugin","MetaData":{"dependencies":[],"name":"PcscReaderManagerPlugin"},"archlevel":1,"className":"PcscReaderManagerPlugin","debug":true,"version":393984}) default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::SettingsModel default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::AppUpdateDataModel default 2022.07.26 09:59:20.782 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::AppUpdater @@ -96,12 +96,12 @@ qt.scen... 2022.07.26 09:59:21.343 53857 (unknown:0) qt.scen... 2022.07.26 09:59:21.343 53857 (unknown:0) : Using sg animation driver qt.scen... 2022.07.26 09:59:21.343 53857 (unknown:0) : Animation Driver: using vsync: 33.33 ms default 2022.07.26 09:59:21.355 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::NotificationModel -qml 2022.07.26 09:59:21.390 53857 UIPlugInQml::init(ui/qml/UIPlugInQml.cpp:303) : Using renderer interface: 3 +qml 2022.07.26 09:59:21.390 53857 UiPluginQml::init(ui/qml/UiPluginQml.cpp:303) : Using renderer interface: 3 card 2022.07.26 09:59:21.390 53857 ReaderManager::doUpdatePluginCache(card/base/ReaderManager.cpp:290) : Update cache entry: SIMULATOR card 2022.07.26 09:59:21.391 53857 ReaderManager::doUpdatePluginCache(card/base/ReaderManager.cpp:290) : Update cache entry: SIMULATOR card 2022.07.26 09:59:21.391 53857 ReaderManager::doUpdatePluginCache(card/base/ReaderManager.cpp:290) : Update cache entry: REMOTE_IFD card 2022.07.26 09:59:21.391 53857 ReaderManager::doUpdatePluginCache(card/base/ReaderManager.cpp:290) : Update cache entry: PCSC -qml 2022.07.26 09:59:21.391 53857 UIPlugInQml::onQmlObjectCreated(ui/qml/UIPlugInQml.cpp:760) : QML engine initialization finished with 0 warnings. +qml 2022.07.26 09:59:21.391 53857 UiPluginQml::onQmlObjectCreated(ui/qml/UiPluginQml.cpp:760) : QML engine initialization finished with 0 warnings. feedback 2022.07.26 09:59:21.397 53857 I ApplicationModel::showFeedback(ui/qml/ApplicationModel.cpp:314) : Die Anwendung wurde gestartet. qml 2022.07.26 09:59:21.397 53857 W ApplicationModel::isScreenReaderRunning(ui/qml/ApplicationModel.cpp:285) : NOT IMPLEMENTED fileprovider 2022.07.26 09:59:23.123 53857 UpdatableFile::update(file_provider/UpdatableFile.cpp:346) : Update Triggered for Name: "supported-providers.json" with URL: QUrl("https://updates.autentapp.de/updatable-files/supported-providers.json") @@ -496,7 +496,7 @@ card 2022.07.26 09:59:27.431 53857 W ...ertificateChainBuilder(card/bas default 2022.07.26 09:59:27.432 53857 AppController::onWorkflowRequested(core/controller/AppController.cpp:225) : New workflow requested: SELF support 2022.07.26 09:59:27.433 53857 I AppController::startNewWorkflow(core/controller/AppController.cpp:453) : Started new workflow SELF default 2022.07.26 09:59:27.434 53857 AppController::startNewWorkflow(core/controller/AppController.cpp:457) : Start governikus::SelfAuthController -default 2022.07.26 09:59:27.434 53857 WorkflowContext::claim(workflows/base/context/WorkflowContext.cpp:76) : Claim workflow by "governikus::UIPlugInQml" +default 2022.07.26 09:59:27.434 53857 WorkflowContext::claim(workflows/base/context/WorkflowContext.cpp:76) : Claim workflow by "governikus::UiPluginQml" qml 2022.07.26 09:59:27.434 53857 W ApplicationModel::keepScreenOn(ui/qml/ApplicationModel.cpp:382) : NOT IMPLEMENTED: true default 2022.07.26 09:59:27.434 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::NumberModel default 2022.07.26 09:59:27.455 53857 Env::createSingleton(global/Env.h:129) : Create singleton: governikus::AuthModel @@ -797,12 +797,12 @@ statemachine 2022.07.26 09:59:29.843 53857 AbstractState::onEntry(workflows/b qml 2022.07.26 09:59:29.847 53857 W (/qml/Governikus/View/BaseController.qml:48) : No focus item found using TitleBar statemachine 2022.07.26 09:59:29.848 53857 ...ate::onStateApprovedChanged(workflows/base/states/AbstractState.cpp:73) : Running state "StateSelectReader" statemachine 2022.07.26 09:59:29.848 53857 ...er::onReaderInfoChanged(workflows/base/states/StateSelectReader.cpp:73) : No selectable reader detected -card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::PcscReaderManagerPlugIn -card_pcsc 2022.07.26 09:59:29.849 53860 ...eaderManagerPlugIn::startScan(card/pcsc/PcscReaderManagerPlugIn.cpp:55) : SCardEstablishContext: "Scard_E_No_Service" -card_pcsc 2022.07.26 09:59:29.849 53860 W ...eaderManagerPlugIn::startScan(card/pcsc/PcscReaderManagerPlugIn.cpp:58) : Not started: Cannot establish context -card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::RemoteIfdReaderManagerPlugIn -card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::SimulatorReaderManagerPlugIn -card 2022.07.26 09:59:29.849 53860 ...erPlugIn::startScan(card/simulator/SimulatorReaderManagerPlugIn.cpp:49) : fireReaderAdded "Simulator" +card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::PcscReaderManagerPlugin +card_pcsc 2022.07.26 09:59:29.849 53860 ...eaderManagerPlugin::startScan(card/pcsc/PcscReaderManagerPlugin.cpp:55) : SCardEstablishContext: "Scard_E_No_Service" +card_pcsc 2022.07.26 09:59:29.849 53860 W ...eaderManagerPlugin::startScan(card/pcsc/PcscReaderManagerPlugin.cpp:58) : Not started: Cannot establish context +card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::RemoteIfdReaderManagerPlugin +card 2022.07.26 09:59:29.849 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Start scan on plugin: governikus::SimulatorReaderManagerPlugin +card 2022.07.26 09:59:29.849 53860 ...erPlugin::startScan(card/simulator/SimulatorReaderManagerPlugin.cpp:49) : fireReaderAdded "Simulator" card 2022.07.26 09:59:29.849 53860 SimulatorReader::connectReader(card/simulator/SimulatorReader.cpp:47) : targetDetected, type: Simulator card 2022.07.26 09:59:29.849 53860 Reader::shelveCard(card/base/Reader.cpp:120) : Card shelved network 2022.07.26 09:59:29.850 53857 DatagramHandlerImpl::resetSocket(network/DatagramHandlerImpl.cpp:90) : Bound on port: 24727 @@ -1461,12 +1461,12 @@ statemachine 2022.07.26 09:59:32.675 53857 AbstractState::onExit(workflows/ba statemachine 2022.07.26 09:59:32.675 53857 AbstractState::onEntry(workflows/base/states/AbstractState.cpp:95) : Next state is "StateCleanUpReaderManager" statemachine 2022.07.26 09:59:32.675 53857 ...ate::onStateApprovedChanged(workflows/base/states/AbstractState.cpp:73) : Running state "StateCleanUpReaderManager" default 2022.07.26 09:59:32.676 53857 ...derManager::run(workflows/base/states/StateCleanUpReaderManager.cpp:38) : Going to disconnect card connection -card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::PcscReaderManagerPlugIn +card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::PcscReaderManagerPlugin statemachine 2022.07.26 09:59:32.677 53857 AbstractState::onExit(workflows/base/states/AbstractState.cpp:115) : Leaving state "StateCleanUpReaderManager" with status: [ OK + No_Error | "Es ist kein Fehler aufgetreten." ] statemachine 2022.07.26 09:59:32.677 53857 AbstractState::onEntry(workflows/base/states/AbstractState.cpp:95) : Next state is "StateStartPaosResponse" -card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::RemoteIfdReaderManagerPlugIn +card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::RemoteIfdReaderManagerPlugin statemachine 2022.07.26 09:59:32.677 53857 ...ate::onStateApprovedChanged(workflows/base/states/AbstractState.cpp:73) : Running state "StateStartPaosResponse" -card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugIn(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::SimulatorReaderManagerPlugIn +card 2022.07.26 09:59:32.677 53860 ReaderManagerWorker::callOnPlugin(card/base/ReaderManagerWorker.cpp:131) : Stop scan on plugin: governikus::SimulatorReaderManagerPlugin statemachine 2022.07.26 09:59:32.677 53857 AbstractState::onExit(workflows/base/states/AbstractState.cpp:115) : Leaving state "StateStartPaosResponse" with status: [ OK + No_Error | "Es ist kein Fehler aufgetreten." ] statemachine 2022.07.26 09:59:32.677 53857 AbstractState::onEntry(workflows/base/states/AbstractState.cpp:95) : Next state is "StateCheckError" card 2022.07.26 09:59:32.677 53860 SimulatorReader::disconnectReader(card/simulator/SimulatorReader.cpp:67) : targetLost, type: Simulator diff --git a/test/fixture/paos/DIDAuthenticateEAC1_htmlTransactionInfo.xml b/test/fixture/paos/DIDAuthenticateEAC1_htmlTransactionInfo.xml new file mode 100644 index 000000000..31a1d2f41 --- /dev/null +++ b/test/fixture/paos/DIDAuthenticateEAC1_htmlTransactionInfo.xml @@ -0,0 +1,31 @@ + + + + + + + +4549445F4946445F434F4E544558545F42415345 +REINER SCT cyberJack RFID komfort USB 52 +0 +4549445F49534F5F32343732375F42415345 +37343139303333612D616163352D343331352D386464392D656166393664636661653361 + + +PIN + +7f218201487f4e8201005f29010042104445445674494447564e4b30303033357f494f060a04007f0007020202020386410400200547c179a38fc0c9602fae4a3ebaef6702b59d171fdb83b242a098b257253fe8f479095518b1a5fbed45d0c0efce178b1ca6cb059ea56d7f9cc0a9ba18b05f200e444544454d4f43414e30303037367f4c12060904007f0007030102025305000513ff175f25060200000502015f2406020000060200655e732d060904007f00070301030180206349cf9eebd2da97dfde6d5f94c467b6dec4c65336e61f2a19114f71eff57077732d060904007f0007030103028020bc09df81284968da37eacb8539977f63181e03b4b2788192befffc54c4c2cba25f3740a792b69f2811d066aa1deeaaf2cb321ac950f33512ee7cd9615bc945cfdca48c3bcbea73a388539aa31b59ac7cddb8e9678c7b1acea263cf6435fbdf3b436ed0 +7f218201b67f4e82016e5f290100420e44455445535465494430303030317f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7864104096eb58bfd86252238ec2652185c43c3a56c320681a21e37a8e69ddc387c0c5f5513856efe2fdc656e604893212e29449b365e304605ac5413e75be31e641f128701015f200e44455445535465494430303030327f4c12060904007f0007030102025305fe0f01ffff5f25060100000902015f24060103000902015f3740141120a0fdfc011a52f3f72b387a3dc7aca88b4868d5ae9741780b6ff8a0b49e5f55169a2d298ef5cf95935dca0c3df3e9d42dc45f74f2066317154961e6c746 +7f218201b67f4e82016e5f290100420e44455445535465494430303030327f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a786410474ff63ab838c73c303ac003dfee95cf8bf55f91e8febcb7395d942036e47cf1845ec786ec95bb453aac288ad023b6067913cf9b63f908f49304e5cfc8b3050dd8701015f200e44455445535465494430303030347f4c12060904007f0007030102025305fc0f13ffff5f25060102000501015f24060105000501015f37405c035a0611b6c58f0b5261fdd009decab7dc7a79482d5248cca119059b7d82b2157cf0c4a499bcf441efdd35e294a58c0af19a34a0762159533285acf170a505 +7f218201b67f4e82016e5f290100420e44455445535465494430303030347f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641049bfeba8dc7faab6e3bdeb3ff794dbb800848fe4f6940a4cc7eecb5159c87da5395505892026d420a22596cd014ed1fd872dada597db0f8d64441041198f62d448701015f200e44455445535465494430303030357f4c12060904007f0007030102025305fc0f13ffff5f25060105000500045f24060108000500045f37402d2468416d66bcbe259b9b907a73395bc1ef94ed75f9c17615210246e9efb06e6753e9055ce76623b7699b9efb1a7d3a9dd83f6e6e09e55a33ea0a5f62a1c719 +7f218201b67f4e82016e5f290100420e44455445535465494430303030357f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a786410425ab80f9c7bca0ab1759d8e469f911cc006d02131552aa5f248b2a38d7c72cfb3317ea6881fd24d8b31a2e75fbeda87964b60787095f75c753cd8bc5264d3c9a8701015f200e44455445535465494430303030367f4c12060904007f0007030102025305fc0f13ffff5f25060108000200055f24060201000200055f37402e55923ed687cb104d609dd183402e8292db03c3effe5ef3fac597d2a8db27370269eaad7341d72447c9184cd817ae0e2bd4df6fcf89dc52f455d490f077e5e9 +7f2181e77f4e81a05f290100420e44455445535465494430303030367f494f060a04007f00070202020203864104451a9e4d7bc410319112cb43f1aee75e29e74183543e8fa91ccfe5b85c5408c867d45f6f7a3f9c251f52082c7fd1a56bbde2fd93e846a6615b4b0164d0f54cdf5f20104445445674494447564e4b30303033357f4c12060904007f0007030102025305400513ff975f25060200000500085f24060200000800065f374009bee15c4b629dc7a2a34986892d46c4ddaebdc738c49f9956473852d168882f7e4dfc0e3d8ef871bbc59cdcbc37e0347a8c1c95f56edfa3b5f747709a8932b1 +3082013b060a04007f00070301030101a1160c14476f7665726e696b757320546573742044564341a21a1318687474703a2f2f7777772e676f7665726e696b75732e6465a31a0c18476f7665726e696b757320476d6248202620436f2e204b47a420131e68747470733a2f2f746573742e676f7665726e696b75732d6569642e6465a581940c81914e616d652c20416e7363687269667420756e6420452d4d61696c2d4164726573736520646573204469656e737465616e626965746572733a0d0a476f7665726e696b757320476d6248202620436f2e204b470d0a486f6368736368756c72696e6720340d0a3238333539204272656d656e0d0a452d4d61696c3a206b6f6e74616b7440676f7665726e696b75732e646509a72431220420ccb65ac1d48e9cd43876ca82cfe83c43d711294d4a40f68811acb715aaa6c8ab +7F4C12060904007F00070301020253050001137C05 +7F4C12060904007F00070301020253050004008302 +67447315060904007F000703010401530831393932313230367315060904007F000703010402530832303133313230367314060904007F000703010403530702760400110000 +this is a <a>test</a> for TransactionInfo + + + + diff --git a/test/fixture/tctoken/broken.xml b/test/fixture/tctoken/broken.xml deleted file mode 100644 index dbed3500e..000000000 --- a/test/fixture/tctoken/broken.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - https://eid-server.example.de/entrypoint - 1meters> - 4BC1A0B5 - - diff --git a/test/fixture/tctoken/ok.xml b/test/fixture/tctoken/ok.xml deleted file mode 100644 index b451cb275..000000000 --- a/test/fixture/tctoken/ok.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - https://eid-server.example.de/entrypoint - 1A2BB129 - https://service.example.de/loggedin?7eb39f62 - https://service.example.de/ComError?7eb39f62 - urn:liberty:paos:2006-08 - urn:ietf:rfc:4279 - - 4BC1A0B5 - - diff --git a/test/fixture/tctoken/withoutCommunicationErrorAddress.xml b/test/fixture/tctoken/withoutCommunicationErrorAddress.xml deleted file mode 100644 index 34fefcce2..000000000 --- a/test/fixture/tctoken/withoutCommunicationErrorAddress.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - https://eid-server.example.de/entrypoint - 1A2BB129 - https://service.example.de/loggedin?7eb39f62 - urn:liberty:paos:2006-08 - urn:ietf:rfc:4279 - - 4BC1A0B5 - - diff --git a/test/helper/CMakeLists.txt b/test/helper/CMakeLists.txt index 00eefcc57..a985878bb 100644 --- a/test/helper/CMakeLists.txt +++ b/test/helper/CMakeLists.txt @@ -3,6 +3,10 @@ add_library(AusweisAppTestHelper INTERFACE) add_subdirectory(common) target_link_libraries(AusweisAppTestHelper INTERFACE AusweisAppTestHelperCommon) +if(LINUX OR BSD) + target_link_libraries(AusweisAppTestHelper INTERFACE AusweisAppTestHelperPcsc) +endif() + if(TARGET AusweisAppIfd) add_subdirectory(ifd) diff --git a/test/helper/common/CertificateHelper.cpp b/test/helper/common/CertificateHelper.cpp new file mode 100644 index 000000000..4500ff8ea --- /dev/null +++ b/test/helper/common/CertificateHelper.cpp @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "CertificateHelper.h" + +using namespace governikus; + +QSharedPointer CertificateHelper::fromHex(const QByteArray& pBytes) +{ + return CVCertificate::fromRaw(QByteArray::fromHex(pBytes)); +} diff --git a/test/helper/common/CertificateHelper.h b/test/helper/common/CertificateHelper.h new file mode 100644 index 000000000..a066fcd39 --- /dev/null +++ b/test/helper/common/CertificateHelper.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#include "asn1/CVCertificate.h" + +namespace governikus +{ + +namespace CertificateHelper +{ +QSharedPointer fromHex(const QByteArray& pBytes); + + +} // namespace CertificateHelper + +} // namespace governikus diff --git a/test/helper/common/MockCard.cpp b/test/helper/common/MockCard.cpp index 3c4921243..6f14d73d2 100644 --- a/test/helper/common/MockCard.cpp +++ b/test/helper/common/MockCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MockCard.h" diff --git a/test/helper/common/MockCard.h b/test/helper/common/MockCard.h index 8b84d36c7..1331c290a 100644 --- a/test/helper/common/MockCard.h +++ b/test/helper/common/MockCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,8 +11,8 @@ #include "Card.h" #include +#include #include -#include namespace governikus { @@ -23,11 +23,11 @@ using TransmitConfig = QPair; class MockCardConfig { public: - QVector mTransmits; + QList mTransmits; CardReturnCode mConnect = CardReturnCode::OK; CardReturnCode mDisconnect = CardReturnCode::OK; - MockCardConfig(const QVector& pTransmits = QVector()) + MockCardConfig(const QList& pTransmits = QList()) : mTransmits(pTransmits) { } diff --git a/test/helper/common/MockCardConnection.cpp b/test/helper/common/MockCardConnection.cpp index 2a2cbaefb..3d06661c7 100644 --- a/test/helper/common/MockCardConnection.cpp +++ b/test/helper/common/MockCardConnection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "MockCardConnection.h" diff --git a/test/helper/common/MockCardConnection.h b/test/helper/common/MockCardConnection.h index b0daf54c4..e356f1e08 100644 --- a/test/helper/common/MockCardConnection.h +++ b/test/helper/common/MockCardConnection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/test/helper/common/MockCardConnectionWorker.cpp b/test/helper/common/MockCardConnectionWorker.cpp index afb9ffb89..b5276a4c1 100644 --- a/test/helper/common/MockCardConnectionWorker.cpp +++ b/test/helper/common/MockCardConnectionWorker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "MockCardConnectionWorker.h" diff --git a/test/helper/common/MockCardConnectionWorker.h b/test/helper/common/MockCardConnectionWorker.h index 7a6bf93c9..5b671fb37 100644 --- a/test/helper/common/MockCardConnectionWorker.h +++ b/test/helper/common/MockCardConnectionWorker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockDownloader.cpp b/test/helper/common/MockDownloader.cpp index e1263850a..b8d6da4cb 100644 --- a/test/helper/common/MockDownloader.cpp +++ b/test/helper/common/MockDownloader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "MockDownloader.h" diff --git a/test/helper/common/MockDownloader.h b/test/helper/common/MockDownloader.h index 2d7b56dda..7154a9da4 100644 --- a/test/helper/common/MockDownloader.h +++ b/test/helper/common/MockDownloader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockHttpServer.cpp b/test/helper/common/MockHttpServer.cpp index a604c6241..5f598ef64 100644 --- a/test/helper/common/MockHttpServer.cpp +++ b/test/helper/common/MockHttpServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MockHttpServer.h" diff --git a/test/helper/common/MockHttpServer.h b/test/helper/common/MockHttpServer.h index 561aaa1d8..f15286b17 100644 --- a/test/helper/common/MockHttpServer.h +++ b/test/helper/common/MockHttpServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockNetworkManager.cpp b/test/helper/common/MockNetworkManager.cpp index ae637540f..e0863a9b0 100644 --- a/test/helper/common/MockNetworkManager.cpp +++ b/test/helper/common/MockNetworkManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "MockNetworkManager.h" diff --git a/test/helper/common/MockNetworkManager.h b/test/helper/common/MockNetworkManager.h index 701590d03..10d09b5a3 100644 --- a/test/helper/common/MockNetworkManager.h +++ b/test/helper/common/MockNetworkManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockNetworkReply.cpp b/test/helper/common/MockNetworkReply.cpp index 2cfcf6303..d65569dd0 100644 --- a/test/helper/common/MockNetworkReply.cpp +++ b/test/helper/common/MockNetworkReply.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "MockNetworkReply.h" @@ -22,6 +22,12 @@ MockNetworkReply::~MockNetworkReply() } +qint64 MockNetworkReply::bytesAvailable() const +{ + return mSocket.bytesAvailable(); +} + + qint64 MockNetworkReply::readData(char* pDst, qint64 pMaxSize) { return mSocket.readData(pDst, pMaxSize); diff --git a/test/helper/common/MockNetworkReply.h b/test/helper/common/MockNetworkReply.h index fed925ec2..8acb04a77 100644 --- a/test/helper/common/MockNetworkReply.h +++ b/test/helper/common/MockNetworkReply.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -60,6 +60,7 @@ class MockNetworkReply } + [[nodiscard]] qint64 bytesAvailable() const override; qint64 readData(char* pDst, qint64 pMaxSize) override; void fireFinished(); diff --git a/test/helper/common/MockReader.cpp b/test/helper/common/MockReader.cpp index 7ed7cef2f..e9de55f08 100644 --- a/test/helper/common/MockReader.cpp +++ b/test/helper/common/MockReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MockReader.h" @@ -9,9 +9,9 @@ using namespace governikus; -ReaderManagerPlugInType MockReader::cMOCKED_READERMANAGER_TYPE = ReaderManagerPlugInType::MOCK; +ReaderManagerPluginType MockReader::cMOCKED_READERMANAGER_TYPE = ReaderManagerPluginType::MOCK; -MockReader* MockReader::createMockReader(const QVector& pTransmitConfig, const QByteArray& pEfCardAccess) +MockReader* MockReader::createMockReader(const QList& pTransmitConfig, const QByteArray& pEfCardAccess) { if (pEfCardAccess.isNull()) { @@ -24,7 +24,7 @@ MockReader* MockReader::createMockReader(const QVector& pTransmi } -MockReader* MockReader::createMockReader(const QVector& pTransmitConfig, const QSharedPointer& pEfCardAccess) +MockReader* MockReader::createMockReader(const QList& pTransmitConfig, const QSharedPointer& pEfCardAccess) { MockCardConfig cardConfig(pTransmitConfig); MockReader* reader = new MockReader(); @@ -33,7 +33,7 @@ MockReader* MockReader::createMockReader(const QVector& pTransmi } -MockReader::MockReader(const QString& pReaderName, ReaderManagerPlugInType pType) +MockReader::MockReader(const QString& pReaderName, ReaderManagerPluginType pType) : Reader(pType, pReaderName) , mCard(nullptr) { @@ -67,14 +67,14 @@ MockCard* MockReader::setCard(const MockCardConfig& pCardConfig, const QByteArra } -MockCard* MockReader::setCard(const MockCardConfig& pCardConfig, const QSharedPointer& pEfCardAccess, CardType pType) +MockCard* MockReader::setCard(const MockCardConfig& pCardConfig, const QSharedPointer& pEfCardAccess, CardType pType, const FileRef& pApplication) { // some unit tests uses MockReader without ReaderManager. So avoid a deadlock here. Qt::ConnectionType type = QThread::currentThread() == QObject::thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection; - QMetaObject::invokeMethod(this, [this, pCardConfig, pEfCardAccess, pType] { + QMetaObject::invokeMethod(this, [this, pCardConfig, pEfCardAccess, pType, pApplication] { mCard.reset(new MockCard(pCardConfig)); - setInfoCardInfo(CardInfo(pType, pEfCardAccess)); + setInfoCardInfo(CardInfo(pType, pApplication, pEfCardAccess)); Q_EMIT fireReaderPropertiesUpdated(getReaderInfo()); }, type); diff --git a/test/helper/common/MockReader.h b/test/helper/common/MockReader.h index 5e7d6d32e..de50b492d 100644 --- a/test/helper/common/MockReader.h +++ b/test/helper/common/MockReader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -25,12 +25,12 @@ class MockReader QScopedPointer mCard; public: - static ReaderManagerPlugInType cMOCKED_READERMANAGER_TYPE; + static ReaderManagerPluginType cMOCKED_READERMANAGER_TYPE; - static MockReader* createMockReader(const QVector& pTransmitConfig = QVector(), const QByteArray& pEfCardAccess = QByteArray()); - static MockReader* createMockReader(const QVector& pTransmitConfig, const QSharedPointer& pEfCardAccess); + static MockReader* createMockReader(const QList& pTransmitConfig = QList(), const QByteArray& pEfCardAccess = QByteArray()); + static MockReader* createMockReader(const QList& pTransmitConfig, const QSharedPointer& pEfCardAccess); - MockReader(const QString& pReaderName = QStringLiteral("MockReader"), ReaderManagerPlugInType pType = cMOCKED_READERMANAGER_TYPE); + MockReader(const QString& pReaderName = QStringLiteral("MockReader"), ReaderManagerPluginType pType = cMOCKED_READERMANAGER_TYPE); ~MockReader() override; @@ -43,7 +43,7 @@ class MockReader void removeCard(); MockCard* setCard(const MockCardConfig& pCardConfig, const QByteArray& pEfCardAccess, CardType pType = CardType::EID_CARD); - MockCard* setCard(const MockCardConfig& pCardConfig, const QSharedPointer& pEfCardAccess = QSharedPointer(), CardType pType = CardType::EID_CARD); + MockCard* setCard(const MockCardConfig& pCardConfig, const QSharedPointer& pEfCardAccess = QSharedPointer(), CardType pType = CardType::EID_CARD, const FileRef& pApplication = FileRef()); void setReaderInfo(const ReaderInfo& pReaderInfo); void setInfoBasicReader(bool pBasicReader); diff --git a/test/helper/common/MockReaderConfiguration.cpp b/test/helper/common/MockReaderConfiguration.cpp index 7bf0d278f..4fdc0c20e 100644 --- a/test/helper/common/MockReaderConfiguration.cpp +++ b/test/helper/common/MockReaderConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "MockReaderConfiguration.h" diff --git a/test/helper/common/MockReaderConfiguration.h b/test/helper/common/MockReaderConfiguration.h index 0f2e4340e..2bfc68597 100644 --- a/test/helper/common/MockReaderConfiguration.h +++ b/test/helper/common/MockReaderConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockReaderDetector.cpp b/test/helper/common/MockReaderDetector.cpp index 7e6783353..2d23bbe81 100644 --- a/test/helper/common/MockReaderDetector.cpp +++ b/test/helper/common/MockReaderDetector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "MockReaderDetector.h" @@ -8,16 +8,16 @@ using namespace governikus; #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) -QVector ReaderDetector::attachedDevIds() const +QList ReaderDetector::attachedDevIds() const { - return QVector(); + return QList(); } #endif -MockReaderDetector::MockReaderDetector(const QVector& pDevIds) +MockReaderDetector::MockReaderDetector(const QList& pDevIds) : ReaderDetector() , mDevIds(pDevIds) { @@ -29,7 +29,7 @@ MockReaderDetector::~MockReaderDetector() } -QVector MockReaderDetector::attachedDevIds() const +QList MockReaderDetector::attachedDevIds() const { return mDevIds; } diff --git a/test/helper/common/MockReaderDetector.h b/test/helper/common/MockReaderDetector.h index c9f0b63ac..cc442fac6 100644 --- a/test/helper/common/MockReaderDetector.h +++ b/test/helper/common/MockReaderDetector.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,7 +18,7 @@ namespace governikus class ReaderDetector : public QObject { - virtual QVector attachedDevIds() const; + virtual QList attachedDevIds() const; }; } // namespace governikus #else @@ -34,14 +34,14 @@ class MockReaderDetector Q_OBJECT public: - MockReaderDetector(const QVector& pDevIds); + MockReaderDetector(const QList& pDevIds); ~MockReaderDetector() override; - [[nodiscard]] QVector attachedDevIds() const override; + [[nodiscard]] QList attachedDevIds() const override; private: - const QVector& mDevIds; + const QList& mDevIds; }; } // namespace governikus diff --git a/test/helper/common/MockReaderManagerPlugIn.h b/test/helper/common/MockReaderManagerPlugIn.h deleted file mode 100644 index 11794795d..000000000 --- a/test/helper/common/MockReaderManagerPlugIn.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Mock implementation of ReaderManagerPlugIn - */ - -#pragma once - -#include "MockReader.h" -#include "ReaderManagerPlugIn.h" - -#include -#include - - -namespace governikus -{ - -class MockReaderManagerPlugIn - : public ReaderManagerPlugIn -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugIn" FILE "MockReaderManagerPlugIn.metadata.json") - Q_INTERFACES(governikus::ReaderManagerPlugIn) - - private: - static MockReaderManagerPlugIn* mInstance; - QMap mReaders; - - public: - MockReaderManagerPlugIn(); - ~MockReaderManagerPlugIn() override = default; - - static MockReaderManagerPlugIn& getInstance(); - - void insert(const QString& pReaderName, const QVariant& pData) override; - [[nodiscard]] QList getReaders() const override; - void startScan(bool pAutoConnect) override; - MockReader* addReader(const QString& pReaderName = QStringLiteral("MockReader"), ReaderManagerPlugInType pType = MockReader::cMOCKED_READERMANAGER_TYPE); - void removeReader(const QString& pReaderName); - void removeAllReader(); - - using ReaderManagerPlugIn::setPlugInAvailable; -}; - - -} // namespace governikus diff --git a/test/helper/common/MockReaderManagerPlugIn.metadata.json b/test/helper/common/MockReaderManagerPlugIn.metadata.json deleted file mode 100644 index ab263025a..000000000 --- a/test/helper/common/MockReaderManagerPlugIn.metadata.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name" : "MockReaderManagerPlugIn", - "dependencies" : [] -} diff --git a/test/helper/common/MockReaderManagerPlugIn.cpp b/test/helper/common/MockReaderManagerPlugin.cpp similarity index 66% rename from test/helper/common/MockReaderManagerPlugIn.cpp rename to test/helper/common/MockReaderManagerPlugin.cpp index 3cfb27656..8c580d8f4 100644 --- a/test/helper/common/MockReaderManagerPlugIn.cpp +++ b/test/helper/common/MockReaderManagerPlugin.cpp @@ -1,36 +1,36 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include using namespace governikus; -MockReaderManagerPlugIn* MockReaderManagerPlugIn::mInstance = nullptr; +MockReaderManagerPlugin* MockReaderManagerPlugin::mInstance = nullptr; -MockReaderManagerPlugIn::MockReaderManagerPlugIn() - : ReaderManagerPlugIn(MockReader::cMOCKED_READERMANAGER_TYPE, true) +MockReaderManagerPlugin::MockReaderManagerPlugin() + : ReaderManagerPlugin(MockReader::cMOCKED_READERMANAGER_TYPE, true) , mReaders() { mInstance = this; } -MockReaderManagerPlugIn& MockReaderManagerPlugIn::getInstance() +MockReaderManagerPlugin& MockReaderManagerPlugin::getInstance() { if (!mInstance) { - qFatal("MockReaderManagerPlugIn not yet instantiated"); + qFatal("MockReaderManagerPlugin not yet instantiated"); } return *mInstance; } -QList MockReaderManagerPlugIn::getReaders() const +QList MockReaderManagerPlugin::getReaders() const { QList readers; readers.reserve(mReaders.size()); @@ -42,9 +42,9 @@ QList MockReaderManagerPlugIn::getReaders() const } -void MockReaderManagerPlugIn::startScan(bool pAutoConnect) +void MockReaderManagerPlugin::startScan(bool pAutoConnect) { - ReaderManagerPlugIn::startScan(pAutoConnect); + ReaderManagerPlugin::startScan(pAutoConnect); for (MockReader* reader : std::as_const(mReaders)) { const auto& readerInfo = reader->getReaderInfo(); @@ -59,7 +59,7 @@ void MockReaderManagerPlugIn::startScan(bool pAutoConnect) } -MockReader* MockReaderManagerPlugIn::addReader(const QString& pReaderName, ReaderManagerPlugInType pType) +MockReader* MockReaderManagerPlugin::addReader(const QString& pReaderName, ReaderManagerPluginType pType) { MockReader* mockReader = nullptr; @@ -67,10 +67,10 @@ MockReader* MockReaderManagerPlugIn::addReader(const QString& pReaderName, Reade auto* reader = new MockReader(pReaderName, pType); reader->setParent(this); - connect(reader, &Reader::fireCardInserted, this, &ReaderManagerPlugIn::fireCardInserted); - connect(reader, &Reader::fireCardRemoved, this, &ReaderManagerPlugIn::fireCardRemoved); - connect(reader, &Reader::fireCardInfoChanged, this, &ReaderManagerPlugIn::fireCardInfoChanged); - connect(reader, &Reader::fireReaderPropertiesUpdated, this, &ReaderManagerPlugIn::fireReaderPropertiesUpdated); + connect(reader, &Reader::fireCardInserted, this, &ReaderManagerPlugin::fireCardInserted); + connect(reader, &Reader::fireCardRemoved, this, &ReaderManagerPlugin::fireCardRemoved); + connect(reader, &Reader::fireCardInfoChanged, this, &ReaderManagerPlugin::fireCardInfoChanged); + connect(reader, &Reader::fireReaderPropertiesUpdated, this, &ReaderManagerPlugin::fireReaderPropertiesUpdated); mReaders.insert(pReaderName, reader); Q_EMIT fireReaderAdded(reader->getReaderInfo()); @@ -83,7 +83,7 @@ MockReader* MockReaderManagerPlugIn::addReader(const QString& pReaderName, Reade } -void MockReaderManagerPlugIn::removeReader(const QString& pReaderName) +void MockReaderManagerPlugin::removeReader(const QString& pReaderName) { QMetaObject::invokeMethod(this, [this, pReaderName] { if (auto reader = mReaders.take(pReaderName)) @@ -96,7 +96,7 @@ void MockReaderManagerPlugIn::removeReader(const QString& pReaderName) } -void MockReaderManagerPlugIn::removeAllReader() +void MockReaderManagerPlugin::removeAllReader() { QList readerList; @@ -112,7 +112,7 @@ void MockReaderManagerPlugIn::removeAllReader() } -void MockReaderManagerPlugIn::insert(const QString& pReaderName, const QVariant& pData) +void MockReaderManagerPlugin::insert(const QString& pReaderName, const QVariant& pData) { for (MockReader* reader : std::as_const(mReaders)) { diff --git a/test/helper/common/MockReaderManagerPlugin.h b/test/helper/common/MockReaderManagerPlugin.h new file mode 100644 index 000000000..09dbb192d --- /dev/null +++ b/test/helper/common/MockReaderManagerPlugin.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany + */ + +/*! + * \brief Mock implementation of ReaderManagerPlugin + */ + +#pragma once + +#include "MockReader.h" +#include "ReaderManagerPlugin.h" + +#include +#include + + +namespace governikus +{ + +class MockReaderManagerPlugin + : public ReaderManagerPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "governikus.ReaderManagerPlugin" FILE "MockReaderManagerPlugin.metadata.json") + Q_INTERFACES(governikus::ReaderManagerPlugin) + + private: + static MockReaderManagerPlugin* mInstance; + QMap mReaders; + + public: + MockReaderManagerPlugin(); + ~MockReaderManagerPlugin() override = default; + + static MockReaderManagerPlugin& getInstance(); + + void insert(const QString& pReaderName, const QVariant& pData) override; + [[nodiscard]] QList getReaders() const override; + void startScan(bool pAutoConnect) override; + MockReader* addReader(const QString& pReaderName = QStringLiteral("MockReader"), ReaderManagerPluginType pType = MockReader::cMOCKED_READERMANAGER_TYPE); + void removeReader(const QString& pReaderName); + void removeAllReader(); + + using ReaderManagerPlugin::setPluginAvailable; +}; + + +} // namespace governikus diff --git a/test/helper/common/MockReaderManagerPlugin.metadata.json b/test/helper/common/MockReaderManagerPlugin.metadata.json new file mode 100644 index 000000000..e57bd25d2 --- /dev/null +++ b/test/helper/common/MockReaderManagerPlugin.metadata.json @@ -0,0 +1,4 @@ +{ + "name" : "MockReaderManagerPlugin", + "dependencies" : [] +} diff --git a/test/helper/common/MockReleaseInformation.cpp b/test/helper/common/MockReleaseInformation.cpp index f6da15938..c19ac9e19 100644 --- a/test/helper/common/MockReleaseInformation.cpp +++ b/test/helper/common/MockReleaseInformation.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "MockReleaseInformation.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; QSharedPointer MockReleaseInformation::createDummyContent(const QStringList& pContent) @@ -14,7 +15,7 @@ QSharedPointer MockReleaseInformation::createDummyContent(const if (tmpFile->open()) { QTextStream ts(tmpFile.data()); - const auto newLine(QLatin1Char('\n')); + const auto newLine('\n'_L1); for (const auto& line : pContent) { ts << line << newLine; @@ -39,11 +40,11 @@ void MockReleaseInformation::update() mCallcountUpdate++; if (!mWasUpdated) { - mAnnounce = createDummyContent({"Dummy announcements"}); - mIssues = createDummyContent({"Dummy issues"}); + mAnnounce = createDummyContent({"Dummy announcements"_L1}); + mIssues = createDummyContent({"Dummy issues"_L1}); - mNotes << createDummyContent({"Dummy notes 0.1", "", "These are the updated notes."}); - mNotes << createDummyContent({"Dummy notes 0.0", "", "These are the initial notes."}); + mNotes << createDummyContent({"Dummy notes 0.1"_L1, ""_L1, "These are the updated notes."_L1}); + mNotes << createDummyContent({"Dummy notes 0.0"_L1, ""_L1, "These are the initial notes."_L1}); mWasUpdated = true; Q_EMIT fireInformationChanged(); diff --git a/test/helper/common/MockReleaseInformation.h b/test/helper/common/MockReleaseInformation.h index fd15f7820..5c671c599 100644 --- a/test/helper/common/MockReleaseInformation.h +++ b/test/helper/common/MockReleaseInformation.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,8 +11,8 @@ #include "ReleaseInformation.h" +#include #include -#include namespace governikus { @@ -28,7 +28,7 @@ class MockReleaseInformation QSharedPointer mAnnounce; QSharedPointer mIssues; - QVector> mNotes; + QList> mNotes; static QSharedPointer createDummyContent(const QStringList& pContent); diff --git a/test/helper/common/MockSocket.cpp b/test/helper/common/MockSocket.cpp index 605d44709..57b367b0e 100644 --- a/test/helper/common/MockSocket.cpp +++ b/test/helper/common/MockSocket.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "MockSocket.h" diff --git a/test/helper/common/MockSocket.h b/test/helper/common/MockSocket.h index 7dd607dfb..62b9f030a 100644 --- a/test/helper/common/MockSocket.h +++ b/test/helper/common/MockSocket.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockWorkflowAuthenticateUi.h b/test/helper/common/MockWorkflowAuthenticateUi.h index 4e553a02f..1a13e668a 100644 --- a/test/helper/common/MockWorkflowAuthenticateUi.h +++ b/test/helper/common/MockWorkflowAuthenticateUi.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/MockWorkflowChangePinUi.h b/test/helper/common/MockWorkflowChangePinUi.h index 8211ccf01..0c8a8fb8b 100644 --- a/test/helper/common/MockWorkflowChangePinUi.h +++ b/test/helper/common/MockWorkflowChangePinUi.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/QtHooks.cpp b/test/helper/common/QtHooks.cpp index be62cd32f..37deba032 100644 --- a/test/helper/common/QtHooks.cpp +++ b/test/helper/common/QtHooks.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "QtHooks.h" diff --git a/test/helper/common/QtHooks.h b/test/helper/common/QtHooks.h index caa674f29..7397ad2c9 100644 --- a/test/helper/common/QtHooks.h +++ b/test/helper/common/QtHooks.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/test/helper/common/TestAuthContext.cpp b/test/helper/common/TestAuthContext.cpp index ccebc8508..dc030b868 100644 --- a/test/helper/common/TestAuthContext.cpp +++ b/test/helper/common/TestAuthContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "TestAuthContext.h" @@ -9,7 +9,7 @@ #include "TestFileHelper.h" - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -28,14 +28,14 @@ TestAuthContext::TestAuthContext(const QString& pFileName) initAccessRightManager(getTerminalCvc(eac1)); setDvCvc(eac1->getCvCertificates().at(1)); - QSharedPointer eac2(static_cast(DidAuthenticateEac2Parser().parse(TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml")))); + QSharedPointer eac2(static_cast(DidAuthenticateEac2Parser().parse(TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"_L1)))); setDidAuthenticateEac2(eac2); } } -const QSharedPointer TestAuthContext::getTerminalCvc(QSharedPointer pEac1) const +const QSharedPointer TestAuthContext::getTerminalCvc(QSharedPointer pEac1) { for (const auto& cvc : pEac1->getCvCertificates()) { @@ -102,13 +102,13 @@ void TestAuthContext::removeCvCertAt(int pPosition) } -QVector TestAuthContext::getAcceptedEidTypes() const +QList TestAuthContext::getAcceptedEidTypes() const { return mAcceptedEidTypes; } -void TestAuthContext::setAcceptedEidTypes(const QVector& pAcceptedEidTypes) +void TestAuthContext::setAcceptedEidTypes(const QList& pAcceptedEidTypes) { mAcceptedEidTypes = pAcceptedEidTypes; } diff --git a/test/helper/common/TestAuthContext.h b/test/helper/common/TestAuthContext.h index dd62e0ab1..88af78a5c 100644 --- a/test/helper/common/TestAuthContext.h +++ b/test/helper/common/TestAuthContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,11 +21,11 @@ class TestAuthContext Q_OBJECT private: - QVector mAcceptedEidTypes; - - const QSharedPointer getTerminalCvc(QSharedPointer pEac1) const; + QList mAcceptedEidTypes; public: + static const QSharedPointer getTerminalCvc(QSharedPointer pEac1); + explicit TestAuthContext(const QString& pFileName = QString()); ~TestAuthContext() override; @@ -34,8 +34,8 @@ class TestAuthContext void addCvCertificate(const QSharedPointer& pCvCertificate); void clearCvCertificates(); void removeCvCertAt(int pPosition); - [[nodiscard]] virtual QVector getAcceptedEidTypes() const override; - void setAcceptedEidTypes(const QVector& pAcceptedEidTypes); + [[nodiscard]] virtual QList getAcceptedEidTypes() const override; + void setAcceptedEidTypes(const QList& pAcceptedEidTypes); }; } // namespace governikus diff --git a/test/helper/common/TestFileHelper.cpp b/test/helper/common/TestFileHelper.cpp index fe75f17d9..b446657e3 100644 --- a/test/helper/common/TestFileHelper.cpp +++ b/test/helper/common/TestFileHelper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TestFileHelper.h" @@ -60,7 +60,7 @@ void TestFileHelper::createTranslations(const QString& pTranslationDir) for (const auto& filePart : testFiles) { - QFile file(dir.path() + QStringLiteral("/ausweisapp2_") + filePart + QStringLiteral(".qm")); + QFile file(dir.path() + QStringLiteral("/ausweisapp_") + filePart + QStringLiteral(".qm")); QVERIFY(file.open(QIODevice::WriteOnly)); QVERIFY(file.write(reinterpret_cast(qm_magic), sizeof(qm_magic))); QVERIFY(file.write(reinterpret_cast(qm_content), sizeof(qm_content))); diff --git a/test/helper/common/TestFileHelper.h b/test/helper/common/TestFileHelper.h index 29625eae1..a4d965286 100644 --- a/test/helper/common/TestFileHelper.h +++ b/test/helper/common/TestFileHelper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/common/TestWorkflowContext.cpp b/test/helper/common/TestWorkflowContext.cpp index 494f89ef0..9f8c30db0 100644 --- a/test/helper/common/TestWorkflowContext.cpp +++ b/test/helper/common/TestWorkflowContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #include "TestWorkflowContext.h" @@ -29,13 +29,13 @@ void TestWorkflowContext::setCanAllowedMode(bool pCanAllowed) } -QVector TestWorkflowContext::getAcceptedEidTypes() const +QList TestWorkflowContext::getAcceptedEidTypes() const { return mAcceptedEidTypes; } -void TestWorkflowContext::setAcceptedEidTypes(const QVector& pAcceptedEidTypes) +void TestWorkflowContext::setAcceptedEidTypes(const QList& pAcceptedEidTypes) { mAcceptedEidTypes = pAcceptedEidTypes; } diff --git a/test/helper/common/TestWorkflowContext.h b/test/helper/common/TestWorkflowContext.h index 3413bf29c..da4c2bad5 100644 --- a/test/helper/common/TestWorkflowContext.h +++ b/test/helper/common/TestWorkflowContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ #pragma once @@ -22,12 +22,12 @@ class TestWorkflowContext void setCanAllowedMode(bool pCanAllowed); - [[nodiscard]] virtual QVector getAcceptedEidTypes() const override; - void setAcceptedEidTypes(const QVector& pAcceptedEidTypes); + [[nodiscard]] virtual QList getAcceptedEidTypes() const override; + void setAcceptedEidTypes(const QList& pAcceptedEidTypes); private: bool mCanAllowed; - QVector mAcceptedEidTypes; + QList mAcceptedEidTypes; }; } // namespace governikus diff --git a/test/helper/common/TestWorkflowController.cpp b/test/helper/common/TestWorkflowController.cpp index 069bebd1c..0a57b47c3 100644 --- a/test/helper/common/TestWorkflowController.cpp +++ b/test/helper/common/TestWorkflowController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "TestWorkflowController.h" diff --git a/test/helper/common/TestWorkflowController.h b/test/helper/common/TestWorkflowController.h index eca7f0d49..fa7cf1e4a 100644 --- a/test/helper/common/TestWorkflowController.h +++ b/test/helper/common/TestWorkflowController.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/test/helper/ifd/MockDataChannel.cpp b/test/helper/ifd/MockDataChannel.cpp index 22fc30071..6a67704f9 100644 --- a/test/helper/ifd/MockDataChannel.cpp +++ b/test/helper/ifd/MockDataChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "MockDataChannel.h" @@ -61,7 +61,7 @@ void MockDataChannel::onReceived(const QByteArray& pDataBlock) } -const QVector& MockDataChannel::getReceivedDataBlocks() const +const QList& MockDataChannel::getReceivedDataBlocks() const { return mReceivedDataBlocks; } diff --git a/test/helper/ifd/MockDataChannel.h b/test/helper/ifd/MockDataChannel.h index ecb615eed..1085cd440 100644 --- a/test/helper/ifd/MockDataChannel.h +++ b/test/helper/ifd/MockDataChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,7 +11,7 @@ #include "DataChannel.h" #include -#include +#include namespace governikus { @@ -24,7 +24,7 @@ class MockDataChannel private: bool mPairing; QString mId; - QVector mReceivedDataBlocks; + QList mReceivedDataBlocks; public: explicit MockDataChannel(bool pPairing = false); @@ -36,7 +36,7 @@ class MockDataChannel [[nodiscard]] const QString& getId() const override; void closeAbnormal(); - [[nodiscard]] const QVector& getReceivedDataBlocks() const; + [[nodiscard]] const QList& getReceivedDataBlocks() const; public Q_SLOTS: void onReceived(const QByteArray& pDataBlock); diff --git a/test/helper/ifd/MockIfdDispatcher.cpp b/test/helper/ifd/MockIfdDispatcher.cpp index 065286cba..80af6f47a 100644 --- a/test/helper/ifd/MockIfdDispatcher.cpp +++ b/test/helper/ifd/MockIfdDispatcher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "MockIfdDispatcher.h" @@ -69,7 +69,7 @@ void MockIfdDispatcher::send(const QSharedPointer& pMessage) } bool withCard = (mState == DispatcherState::ReaderWithCard || mState == DispatcherState::ReaderWithCardError); - ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::PCSC, CardInfo(withCard ? CardType::EID_CARD : CardType::NONE)); + ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPluginType::PCSC, CardInfo(withCard ? CardType::EID_CARD : CardType::NONE)); const QSharedPointer message(new IfdStatus(info)); Q_EMIT fireReceived(message->getType(), QJsonDocument::fromJson(message->toByteArray(IfdVersion::Version::v2, mContextHandle)).object(), mId); return; diff --git a/test/helper/ifd/MockIfdDispatcher.h b/test/helper/ifd/MockIfdDispatcher.h index c4a89614b..4ddffac89 100644 --- a/test/helper/ifd/MockIfdDispatcher.h +++ b/test/helper/ifd/MockIfdDispatcher.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/ifd/MockIfdServer.cpp b/test/helper/ifd/MockIfdServer.cpp index 3addf4efd..ecfd9a2f4 100644 --- a/test/helper/ifd/MockIfdServer.cpp +++ b/test/helper/ifd/MockIfdServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "MockIfdServer.h" diff --git a/test/helper/ifd/MockIfdServer.h b/test/helper/ifd/MockIfdServer.h index 55ca7f636..cd8bda68f 100644 --- a/test/helper/ifd/MockIfdServer.h +++ b/test/helper/ifd/MockIfdServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/pcsc/CMakeLists.txt b/test/helper/pcsc/CMakeLists.txt index 6af1ae377..1aad412bf 100644 --- a/test/helper/pcsc/CMakeLists.txt +++ b/test/helper/pcsc/CMakeLists.txt @@ -1,6 +1,7 @@ if(LINUX OR BSD) file(GLOB SRC "*.cpp") - - add_library(Pcsc SHARED "${SRC}") - target_link_libraries(Pcsc ${Qt}::Core PkgConfig::PCSC) + add_library(AusweisAppTestHelperPcsc SHARED "${SRC}") + target_include_directories(AusweisAppTestHelperPcsc INTERFACE "$") + target_link_libraries(AusweisAppTestHelperPcsc ${Qt}::Core PkgConfig::PCSC) + set_target_properties(AusweisAppTestHelperPcsc PROPERTIES CXX_VISIBILITY_PRESET default) endif() diff --git a/test/helper/pcsc/main.cpp b/test/helper/pcsc/main.cpp index 6916fb47d..3907aaf06 100644 --- a/test/helper/pcsc/main.cpp +++ b/test/helper/pcsc/main.cpp @@ -1,7 +1,9 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ +#include "pcscmock.h" + #include #include #include @@ -9,6 +11,24 @@ #include #endif +struct MockSCardCommandData +{ + LONG mSCardGetStatusChange = 0; +} +mMockData; + + +void governikus::setResultGetCardStatus(LONG pReturnCode) +{ + mMockData.mSCardGetStatusChange = pReturnCode; +} + + +LONG governikus::getResultGetCardStatus() +{ + return mMockData.mSCardGetStatusChange; +} + LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { @@ -66,7 +86,7 @@ LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERST Q_UNUSED(rgReaderStates) Q_UNUSED(cReaders) - return SCARD_S_SUCCESS; + return governikus::getResultGetCardStatus(); } diff --git a/test/helper/pcsc/pcscmock.h b/test/helper/pcsc/pcscmock.h new file mode 100644 index 000000000..21f613b40 --- /dev/null +++ b/test/helper/pcsc/pcscmock.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ + +#pragma once + +#ifndef Q_OS_WIN + #include +#endif + +namespace governikus +{ + +void setResultGetCardStatus(LONG pReturnCode); +LONG getResultGetCardStatus(); + +} // namespace governikus diff --git a/test/helper/ui/json/MsgHandlerEnterPassword.cpp b/test/helper/ui/json/MsgHandlerEnterPassword.cpp index 85a99771e..d16c124ba 100644 --- a/test/helper/ui/json/MsgHandlerEnterPassword.cpp +++ b/test/helper/ui/json/MsgHandlerEnterPassword.cpp @@ -1,15 +1,16 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "MsgHandlerEnterPassword.h" #include "MockCardConnection.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; void governikus::setValidState(MessageDispatcher& pDispatcher, @@ -45,12 +46,12 @@ void governikus::setValidState(MessageDispatcher& pDispatcher, if (pSelectReader) { - auto* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader CARD"); + auto* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader CARD"_L1); auto info = reader->getReaderInfo(); info.setBasicReader(pBasicReader); reader->setReaderInfo(info); reader->setCard(MockCardConfig()); - pContext->setReaderName("MockReader CARD"); + pContext->setReaderName("MockReader CARD"_L1); QSharedPointer cardConnection(new MockCardConnection(reader->getReaderInfo())); pContext->setCardConnection(cardConnection); diff --git a/test/helper/ui/json/MsgHandlerEnterPassword.h b/test/helper/ui/json/MsgHandlerEnterPassword.h index c6368d1d6..70b60c7d0 100644 --- a/test/helper/ui/json/MsgHandlerEnterPassword.h +++ b/test/helper/ui/json/MsgHandlerEnterPassword.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/helper/ui/websocket/WebSocketHelper.cpp b/test/helper/ui/websocket/WebSocketHelper.cpp index cba160d2e..f86540fd8 100644 --- a/test/helper/ui/websocket/WebSocketHelper.cpp +++ b/test/helper/ui/websocket/WebSocketHelper.cpp @@ -1,10 +1,10 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "WebSocketHelper.h" -#include "UIPlugInWebSocket.h" +#include "UiPluginWebSocket.h" #include #include diff --git a/test/helper/ui/websocket/WebSocketHelper.h b/test/helper/ui/websocket/WebSocketHelper.h index 245e3610b..d5ee92688 100644 --- a/test/helper/ui/websocket/WebSocketHelper.h +++ b/test/helper/ui/websocket/WebSocketHelper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #pragma once diff --git a/test/integrated/test_Integrated.cpp b/test/integrated/test_Integrated.cpp index 4855b9ab5..24e557810 100644 --- a/test/integrated/test_Integrated.cpp +++ b/test/integrated/test_Integrated.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/integration/init/test_CommandLineParser.cpp b/test/integration/init/test_CommandLineParser.cpp index 973d579ab..9362eb59d 100644 --- a/test/integration/init/test_CommandLineParser.cpp +++ b/test/integration/init/test_CommandLineParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,8 @@ #include #include +using namespace Qt::Literals::StringLiterals; + class test_CommandLineParser : public QObject { @@ -25,11 +27,11 @@ class test_CommandLineParser #endif const QString& path = QStringLiteral(AUSWEISAPP_BINARY_DIR); - const QString& app = path + "AusweisApp"; + const QString& app = path + "AusweisApp"_L1; QStringList args; - args << "--help"; - args << "-platform" << "offscreen"; + args << "--help"_L1; + args << "-platform"_L1 << "offscreen"_L1; QProcess process; process.setProgram(app); @@ -43,7 +45,11 @@ class test_CommandLineParser out << QString(); out << QStringLiteral("Options:"); out << QStringLiteral(" -h, --help Displays help on commandline options."); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) + out << QStringLiteral(" --help-all Displays help, including generic Qt options."); +#else out << QStringLiteral(" --help-all Displays help including Qt specific options."); +#endif out << QStringLiteral(" -v, --version Displays version information."); out << QStringLiteral(" --keep Keep logfile."); out << QStringLiteral(" --no-logfile Disable logfile."); @@ -56,7 +62,7 @@ class test_CommandLineParser out << QString(); const auto& standardOut = process.readAllStandardOutput(); - const auto& expected = out.join(QLatin1Char('\n')).toLocal8Bit(); + const auto& expected = out.join('\n'_L1).toLocal8Bit(); // helps to debug if QCOMPARE fails qDebug().noquote() << '\n' << standardOut; diff --git a/test/integration/ui/qml/test_Qml.cpp b/test/integration/ui/qml/test_Qml.cpp index 5a2e322a6..8ea168ff4 100644 --- a/test/integration/ui/qml/test_Qml.cpp +++ b/test/integration/ui/qml/test_Qml.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ @@ -12,6 +12,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -31,12 +32,12 @@ class test_Qml QString logData; mHelper->sendMessage(QStringLiteral("{\"cmd\": \"GET_LOG\"}")); if (!mHelper->waitForMessage([&logData](const QJsonObject& pMessage){ - if (pMessage["msg"] != "LOG") + if (pMessage["msg"_L1] != "LOG"_L1) { return false; } - auto jsonData = pMessage[QLatin1String("data")]; + auto jsonData = pMessage["data"_L1]; if (!jsonData.isNull()) { logData = jsonData.toString(); @@ -63,7 +64,7 @@ class test_Qml const QString logData = getLogData(); bool initContainedAndSuccess = logData.contains(QLatin1String("QML engine initialization finished with 0 warnings.")); - bool noQmlWarning = !logData.contains(QRegularExpression(" W .*\\.qml:")); + bool noQmlWarning = !logData.contains(QRegularExpression(" W .*\\.qml:"_L1)); bool success = initContainedAndSuccess && noQmlWarning; if (!success) { @@ -88,33 +89,29 @@ class test_Qml void test_qmlEngineInit_data() { - QTest::addColumn("platformSelector"); + QTest::addColumn("platform"); - QTest::newRow("Android") << QString("mobile,android"); - QTest::newRow("iOS") << QString("mobile,ios"); -#ifdef Q_OS_WIN - QTest::newRow("Windows") << QString("desktop,win"); -#else - QTest::newRow("macOS") << QString("desktop,nowin"); -#endif + QTest::newRow("Android") << u"android"_s; + QTest::newRow("iOS") << u"ios"_s; + QTest::newRow("Desktop") << u""_s; } void test_qmlEngineInit() { - QFETCH(QString, platformSelector); + QFETCH(QString, platform); QString path = QStringLiteral(AUSWEISAPP_BINARY_DIR); - QString app = path + "AusweisApp"; + QString app = path + "AusweisApp"_L1; #ifdef Q_OS_WIN - app += ".exe"; + app += ".exe"_L1; #endif QStringList args; - args << "--ui" << "qml"; - args << "--ui" << "websocket"; - args << "--port" << "0"; - args << "-platform" << "offscreen"; + args << "--ui"_L1 << "qml"_L1; + args << "--ui"_L1 << "websocket"_L1; + args << "--port"_L1 << "0"_L1; + args << "-platform"_L1 << "offscreen"_L1; mApp2.reset(new QProcess()); mApp2->setProgram(app); @@ -122,9 +119,9 @@ class test_Qml mApp2->setArguments(args); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("OVERRIDE_PLATFORM_SELECTOR", platformSelector); - env.insert("QT_QPA_OFFSCREEN_NO_GLX", QStringLiteral("1")); - env.insert("QML_DISABLE_DISK_CACHE", QStringLiteral("1")); + env.insert("OVERRIDE_PLATFORM"_L1, platform); + env.insert("QT_QPA_OFFSCREEN_NO_GLX"_L1, "1"_L1); + env.insert("QML_DISABLE_DISK_CACHE"_L1, "1"_L1); mApp2->setProcessEnvironment(env); mApp2->start(); @@ -149,35 +146,35 @@ class test_Qml QNetworkAccessManager accessManager; QSignalSpy logSpy(&accessManager, &QNetworkAccessManager::finished); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("IDENTIFY")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("IDENTIFY"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 1, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("IDENTIFY")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("SETTINGS")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("SETTINGS"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 2, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("SETTINGS")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("UPDATEINFORMATION")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("UPDATEINFORMATION"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 3, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("UPDATEINFORMATION")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("PINMANAGEMENT")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("PINMANAGEMENT"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 4, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("PINMANAGEMENT")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("TUTORIAL")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("TUTORIAL"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 5, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("TUTORIAL")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("HELP")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("HELP"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 6, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("HELP")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("PROVIDER")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("PROVIDER"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 7, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("PROVIDER")), PROCESS_TIMEOUT); - accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("SELF_AUTHENTICATION")))); + accessManager.get(QNetworkRequest(QUrl(showUiUri.arg("SELF_AUTHENTICATION"_L1)))); QTRY_COMPARE_WITH_TIMEOUT(logSpy.size(), 8, PROCESS_TIMEOUT); QTRY_VERIFY_WITH_TIMEOUT(isShowUiInLog(QStringLiteral("SELF_AUTHENTICATION")), PROCESS_TIMEOUT); diff --git a/test/integration/ui/websocket/test_UIPlugInWebSocket.cpp b/test/integration/ui/websocket/test_UiPluginWebSocket.cpp similarity index 75% rename from test/integration/ui/websocket/test_UIPlugInWebSocket.cpp rename to test/integration/ui/websocket/test_UiPluginWebSocket.cpp index 9511d02eb..9084f1392 100644 --- a/test/integration/ui/websocket/test_UIPlugInWebSocket.cpp +++ b/test/integration/ui/websocket/test_UiPluginWebSocket.cpp @@ -1,9 +1,9 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UIPlugInWebSocket + * \brief Unit tests for \ref UiPluginWebSocket */ #include "PortFile.h" @@ -13,10 +13,11 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; -class test_UIPlugInWebSocket +class test_UiPluginWebSocket : public QObject { Q_OBJECT @@ -37,16 +38,16 @@ class test_UIPlugInWebSocket void init() { QString path = QStringLiteral(AUSWEISAPP_BINARY_DIR); - QString app = path + "AusweisApp"; + QString app = path + "AusweisApp"_L1; #ifdef Q_OS_WIN - app += ".exe"; + app += ".exe"_L1; #endif QStringList args; - args << "--ui" << "websocket"; - args << "--port" << "0"; + args << "--ui"_L1 << "websocket"_L1; + args << "--port"_L1 << "0"_L1; #ifndef Q_OS_WIN - args << "-platform" << "offscreen"; + args << "-platform"_L1 << "offscreen"_L1; #endif mApp2.reset(new QProcess()); @@ -116,16 +117,16 @@ class test_UIPlugInWebSocket void getInfoAndApiLevel() { - mHelper->sendMessage("{\"cmd\": \"GET_INFO\"}"); + mHelper->sendMessage("{\"cmd\": \"GET_INFO\"}"_L1); QVERIFY(mHelper->waitForMessage([](const QJsonObject& pMessage){ - return pMessage["msg"] == "INFO" && - pMessage["VersionInfo"].toObject()["Name"] == QLatin1String("AusweisApp2"); + return pMessage["msg"_L1] == "INFO"_L1 && + pMessage["VersionInfo"_L1].toObject()["Name"_L1] == QLatin1String("AusweisApp2"); })); - mHelper->sendMessage("{\"cmd\": \"GET_API_LEVEL\"}"); + mHelper->sendMessage("{\"cmd\": \"GET_API_LEVEL\"}"_L1); QVERIFY(mHelper->waitForMessage([](const QJsonObject& pMessage){ - return pMessage["msg"] == "API_LEVEL" && - pMessage["available"].toArray().size() >= 1; + return pMessage["msg"_L1] == "API_LEVEL"_L1 && + pMessage["available"_L1].toArray().size() >= 1; })); } @@ -136,18 +137,18 @@ class test_UIPlugInWebSocket QSKIP("Not supported"); #endif - mHelper->sendMessage("{\"cmd\": \"RUN_AUTH\", \"tcTokenURL\" : \"https://localhost/\"}"); + mHelper->sendMessage("{\"cmd\": \"RUN_AUTH\", \"tcTokenURL\" : \"https://localhost/\"}"_L1); QVERIFY(mHelper->waitForMessage([](const QJsonObject& pMessage){ - return pMessage["msg"] == "AUTH"; + return pMessage["msg"_L1] == "AUTH"_L1; })); QVERIFY(mHelper->waitForMessage([](const QJsonObject& pMessage){ - return pMessage["result"].toObject()["major"].toString().endsWith("#error"); + return pMessage["result"_L1].toObject()["major"_L1].toString().endsWith("#error"_L1); })); } }; -QTEST_GUILESS_MAIN(test_UIPlugInWebSocket) -#include "test_UIPlugInWebSocket.moc" +QTEST_GUILESS_MAIN(test_UiPluginWebSocket) +#include "test_UiPluginWebSocket.moc" diff --git a/test/json/CMakeLists.txt b/test/json/CMakeLists.txt deleted file mode 100644 index e3ae0f7d9..000000000 --- a/test/json/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -find_program(JSONSCHEMA_BIN NAMES jsonschema jsonschema-3 python-jsonschema python3-jsonschema py-jsonschema py3-jsonschema CMAKE_FIND_ROOT_PATH_BOTH) - -if(JSONSCHEMA_BIN) - set(JSON_FILES updatable-files/supported-providers.json updatable-files/supported-readers.json) - - foreach(jsonfile ${JSON_FILES}) - set(file ${RESOURCES_DIR}/${jsonfile}) - if(NOT EXISTS "${file}") - message(FATAL_ERROR "File does not exist: ${file}") - endif() - - get_filename_component(filename ${file} NAME) - set(schema ${TEST_DIR}/json/${filename}) - - add_test(NAME ${filename} COMMAND ${JSONSCHEMA_BIN} -i ${file} ${schema}) - set_tests_properties(${filename} PROPERTIES LABELS "json" TIMEOUT 10) - endforeach() -endif() diff --git a/test/qml/+desktop/test_ProgressView.qml b/test/qml/+desktop/test_ProgressView.qml index 6b50117bb..46e005f48 100644 --- a/test/qml/+desktop/test_ProgressView.qml +++ b/test/qml/+desktop/test_ProgressView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/+mobile/test_ProgressView.qml b/test/qml/+mobile/test_ProgressView.qml index f3821fa77..546484eaa 100644 --- a/test/qml/+mobile/test_ProgressView.qml +++ b/test/qml/+mobile/test_ProgressView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/AuthView/+desktop/test_AuthView.qml b/test/qml/AuthView/+desktop/test_AuthView.qml index 053861c63..1ad51c3c6 100644 --- a/test/qml/AuthView/+desktop/test_AuthView.qml +++ b/test/qml/AuthView/+desktop/test_AuthView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/AuthView/+desktop/test_ProviderInfoSection.qml b/test/qml/AuthView/+desktop/test_ProviderInfoSection.qml deleted file mode 100644 index c2485f812..000000000 --- a/test/qml/AuthView/+desktop/test_ProviderInfoSection.qml +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtTest - -TestCase { - id: testCase - - function createTestObject() { - return createTemporaryQmlObject("import \"qrc:/qml/Governikus/AuthView/+desktop/\"; ProviderInfoSection {}", testCase); - } - function test_load() { - let testObject = createTestObject(); - verify(testObject, "Object loaded"); - } - - name: "test_ProviderInfoSection" - visible: true - when: windowShown -} diff --git a/test/qml/AuthView/+mobile/test_AuthView.qml b/test/qml/AuthView/+mobile/test_AuthView.qml index d2289ccee..03266255f 100644 --- a/test/qml/AuthView/+mobile/test_AuthView.qml +++ b/test/qml/AuthView/+mobile/test_AuthView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/AuthView/test_EditRights.qml b/test/qml/AuthView/test_EditRights.qml new file mode 100644 index 000000000..21d0fbde8 --- /dev/null +++ b/test/qml/AuthView/test_EditRights.qml @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtTest + +TestCase { + id: testCase + + function createTestObject() { + return createTemporaryQmlObject(" + import Governikus.AuthView + + EditRights { + } + ", testCase); + } + function test_load() { + let testObject = createTestObject(); + verify(testObject, "Object loaded"); + let transactionText = findChild(testObject, "transactionText"); + verify(transactionText, "Child found"); + + // Text.StyledText will show HTML-Escaped text again + compare(transactionText.textFormat, Text.StyledText); + } + + name: "test_EditRights" + visible: true + when: windowShown +} diff --git a/test/qml/Global/+desktop/test_TitlePane.qml b/test/qml/AuthView/test_ProviderInfo.qml similarity index 53% rename from test/qml/Global/+desktop/test_TitlePane.qml rename to test/qml/AuthView/test_ProviderInfo.qml index 0475e18f0..2b46156a3 100644 --- a/test/qml/Global/+desktop/test_TitlePane.qml +++ b/test/qml/AuthView/test_ProviderInfo.qml @@ -1,6 +1,7 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ +import QtQuick import QtTest TestCase { @@ -8,12 +9,19 @@ TestCase { function createTestObject() { return createTemporaryQmlObject(" - import \"qrc:/qml/Governikus/TitleBar/+desktop/\" - TitlePane {} + import Governikus.AuthView + + ProviderInfo { + name: \"FooBar\" + } ", testCase); } function test_load() { let testObject = createTestObject(); verify(testObject, "Object loaded"); } + + name: "test_ProviderInfo" + visible: true + when: windowShown } diff --git a/test/qml/ChangePinView/+desktop/test_ChangePinView.qml b/test/qml/ChangePinView/+desktop/test_ChangePinView.qml index 1017a24b8..8bfcf9ca8 100644 --- a/test/qml/ChangePinView/+desktop/test_ChangePinView.qml +++ b/test/qml/ChangePinView/+desktop/test_ChangePinView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/ChangePinView/+mobile/test_ChangePinView.qml b/test/qml/ChangePinView/+mobile/test_ChangePinView.qml index ce28fc9e8..63f5bb781 100644 --- a/test/qml/ChangePinView/+mobile/test_ChangePinView.qml +++ b/test/qml/ChangePinView/+mobile/test_ChangePinView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/CheckIDCardView/+mobile/test_CheckIDCardView.qml b/test/qml/CheckIDCardView/+mobile/test_CheckIDCardView.qml index d376f203c..d26dbf508 100644 --- a/test/qml/CheckIDCardView/+mobile/test_CheckIDCardView.qml +++ b/test/qml/CheckIDCardView/+mobile/test_CheckIDCardView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/CheckResultView/+mobile/test_CheckIDCardSuggestionView.qml b/test/qml/CheckResultView/+mobile/test_CheckIDCardSuggestionView.qml index 10b24b039..20d9ace2f 100644 --- a/test/qml/CheckResultView/+mobile/test_CheckIDCardSuggestionView.qml +++ b/test/qml/CheckResultView/+mobile/test_CheckIDCardSuggestionView.qml @@ -1,38 +1,48 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ -import QtQuick 2.15 -import QtTest 1.15 -import Governikus.Type.CheckIDCardModel 1.0 +import QtQuick +import QtTest +import Governikus.Type TestCase { id: testCase - function createTestObject(result) { - return createTemporaryQmlObject("import \"qrc:/qml/Governikus/CheckIDCardView/+mobile/\"; CheckIDCardSuggestionView { result: %1 }".arg(result), testCase); - } function test_load(data) { - let testObject = createTestObject(data.result); + const component = Qt.createComponent(importPrefix + "/Governikus/CheckIDCardView/CheckIDCardSuggestionView.qml"); + verify(component.status === Component.Ready, "Component loaded"); + const testObject = component.createObject(parent, { + result: data.result + }); verify(testObject, "Object loaded"); } function test_load_data() { - return [{ - "result": CheckIDCardModel.NO_NFC - }, { - "result": CheckIDCardModel.UNKNOWN_CARD_DETECTED - }, { - "result": CheckIDCardModel.INSUFFICIENT_APDU_LENGTH - }, { - "result": CheckIDCardModel.CARD_ACCESS_FAILED - }, { - "result": CheckIDCardModel.PIN_DEACTIVATED - }, { - "result": CheckIDCardModel.PIN_SUSPENDED - }, { - "result": CheckIDCardModel.PIN_BLOCKED - }, { + return [ + { + "result": CheckIDCardModel.Result.NO_NFC + }, + { + "result": CheckIDCardModel.Result.UNKNOWN_CARD_DETECTED + }, + { + "result": CheckIDCardModel.Result.INSUFFICIENT_APDU_LENGTH + }, + { + "result": CheckIDCardModel.Result.CARD_ACCESS_FAILED + }, + { + "result": CheckIDCardModel.Result.PIN_DEACTIVATED + }, + { + "result": CheckIDCardModel.Result.PIN_SUSPENDED + }, + { + "result": CheckIDCardModel.Result.PIN_BLOCKED + }, + { "result": -1 - }]; + } + ]; } name: "test_CheckIDCardSuggestionView" diff --git a/test/qml/CheckResultView/+mobile/test_CheckResultSuggestionView.qml b/test/qml/CheckResultView/+mobile/test_CheckResultSuggestionView.qml index dbf578419..02e46c1a5 100644 --- a/test/qml/CheckResultView/+mobile/test_CheckResultSuggestionView.qml +++ b/test/qml/CheckResultView/+mobile/test_CheckResultSuggestionView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/CheckResultView/+mobile/test_CheckResultView.qml b/test/qml/CheckResultView/+mobile/test_CheckResultView.qml index 1ca9a24c0..914924101 100644 --- a/test/qml/CheckResultView/+mobile/test_CheckResultView.qml +++ b/test/qml/CheckResultView/+mobile/test_CheckResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/EnterPasswordView/+desktop/test_EnterPasswordView.qml b/test/qml/EnterPasswordView/+desktop/test_EnterPasswordView.qml deleted file mode 100644 index 2061977fd..000000000 --- a/test/qml/EnterPasswordView/+desktop/test_EnterPasswordView.qml +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtTest -import Governikus.Type.PasswordType - -TestCase { - id: parent - - function test_load_EnterPasswordView(data) { - let item = createTemporaryQmlObject(" - import Governikus.EnterPasswordView - EnterPasswordView { - passwordType: %1 - } - ".arg(data.passwordType), parent); - item.destroy(); - } - function test_load_EnterPasswordView_data() { - return [{ - "passwordType": PasswordType.PIN - }, { - "passwordType": PasswordType.CAN - }, { - "passwordType": PasswordType.PUK - }, { - "passwordType": PasswordType.REMOTE_PIN - }]; - } - - visible: true - when: windowShown -} diff --git a/test/qml/EnterPasswordView/+mobile/test_EnterPasswordView.qml b/test/qml/EnterPasswordView/test_EnterPasswordView.qml similarity index 50% rename from test/qml/EnterPasswordView/+mobile/test_EnterPasswordView.qml rename to test/qml/EnterPasswordView/test_EnterPasswordView.qml index 99b79eab8..e3af06dbb 100644 --- a/test/qml/EnterPasswordView/+mobile/test_EnterPasswordView.qml +++ b/test/qml/EnterPasswordView/test_EnterPasswordView.qml @@ -1,7 +1,8 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtTest +import Governikus.Global TestCase { id: parent @@ -9,12 +10,12 @@ TestCase { function test_load_EnterPasswordView() { let item = createTemporaryQmlObject(" import Governikus.EnterPasswordView - import Governikus.Type.PasswordType + import Governikus.Type EnterPasswordView { - passwordType: PasswordType.PIN - title: \"EnterPasswordView\" + passwordType: NumberModel.PasswordType.PIN + %1 } - ", parent); + ".arg(Constants.is_desktop ? "" : "title: \"EnterPasswordView\""), parent); item.destroy(); } diff --git a/test/qml/FeedbackView/+desktop/test_DetachedLogView.qml b/test/qml/FeedbackView/+desktop/test_DetachedLogView.qml index 67ea00e44..a8293b3aa 100644 --- a/test/qml/FeedbackView/+desktop/test_DetachedLogView.qml +++ b/test/qml/FeedbackView/+desktop/test_DetachedLogView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+mobile/test_ListItem.qml b/test/qml/FeedbackView/+mobile/test_ListItem.qml similarity index 73% rename from test/qml/Global/+mobile/test_ListItem.qml rename to test/qml/FeedbackView/+mobile/test_ListItem.qml index 94c2cd522..1b4f95d99 100644 --- a/test/qml/Global/+mobile/test_ListItem.qml +++ b/test/qml/FeedbackView/+mobile/test_ListItem.qml @@ -1,15 +1,20 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest -import Governikus.Global TestCase { id: testCase function createTestObject() { - return createTemporaryQmlObject("import Governikus.Global; ListItem {}", testCase); + return createTemporaryQmlObject(" + import Governikus.FeedbackView + ListItem { + width: 200 + height: 50 + } + ", testCase); } function test_icon() { let testObject = createTestObject(); @@ -20,14 +25,6 @@ TestCase { testObject.tintIcon = true; verify(testObject.tintIcon, "tintIcon: true"); } - function test_linkIcon() { - let testObject = createTestObject(); - compare(testObject.showLinkIcon, Constants.is_layout_ios, "Initial showLinkIcon: false"); - testObject.showLinkIcon = false; - verify(!testObject.showLinkIcon, "tintIcon: false"); - testObject.showLinkIcon = true; - verify(testObject.showLinkIcon, "tintIcon: true"); - } function test_load() { let testObject = createTestObject(); verify(testObject, "Object loaded"); diff --git a/test/qml/FeedbackView/+mobile/test_LogView.qml b/test/qml/FeedbackView/+mobile/test_LogView.qml index 955831068..48e1c64d7 100644 --- a/test/qml/FeedbackView/+mobile/test_LogView.qml +++ b/test/qml/FeedbackView/+mobile/test_LogView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/FeedbackView/+mobile/test_StoreFeedbackPopup.qml b/test/qml/FeedbackView/+mobile/test_StoreFeedbackPopup.qml index 5034b904f..f4a23efc5 100644 --- a/test/qml/FeedbackView/+mobile/test_StoreFeedbackPopup.qml +++ b/test/qml/FeedbackView/+mobile/test_StoreFeedbackPopup.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_DecisionView.qml b/test/qml/Global/+desktop/test_DecisionView.qml index 39a2d9c6b..0e5442d7e 100644 --- a/test/qml/Global/+desktop/test_DecisionView.qml +++ b/test/qml/Global/+desktop/test_DecisionView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_GFileDialog.qml b/test/qml/Global/+desktop/test_GFileDialog.qml index f9d3da950..d30941415 100644 --- a/test/qml/Global/+desktop/test_GFileDialog.qml +++ b/test/qml/Global/+desktop/test_GFileDialog.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_LocationButton.qml b/test/qml/Global/+desktop/test_LocationButton.qml index 0adb701be..754da88ba 100644 --- a/test/qml/Global/+desktop/test_LocationButton.qml +++ b/test/qml/Global/+desktop/test_LocationButton.qml @@ -1,10 +1,10 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest import Governikus.Global -import Governikus.Type.SettingsModel +import Governikus.Type TestCase { id: testCase diff --git a/test/qml/Global/+desktop/test_NavigationButton.qml b/test/qml/Global/+desktop/test_NavigationButton.qml index 7aaa066c3..4c0e5237a 100644 --- a/test/qml/Global/+desktop/test_NavigationButton.qml +++ b/test/qml/Global/+desktop/test_NavigationButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -15,17 +15,15 @@ TestCase { let testObject = createTestObject(); verify(testObject, "Object loaded"); } - function test_subtext() { + function test_text() { let testObject = createTestObject(); - compare(testObject.text, "Continue", "Initial subText: Continue"); - testObject.subText = "test"; - compare(testObject.text, "test", "subText: test"); + compare(testObject.text, "", "No initial text"); + testObject.text = "test"; + compare(testObject.text, "test", "text: test"); } function test_type() { let testObject = createTestObject(); compare(testObject.buttonType, NavigationButton.Type.Forward, "Initial type: Forward"); - testObject.buttonType = NavigationButton.Type.Back; - compare(testObject.buttonType, NavigationButton.Type.Back, "type: Back"); testObject.buttonType = NavigationButton.Type.Check; compare(testObject.buttonType, NavigationButton.Type.Check, "type: Check"); testObject.buttonType = NavigationButton.Type.Cancel; diff --git a/test/qml/Global/+desktop/test_RetryCounter.qml b/test/qml/Global/+desktop/test_RetryCounter.qml deleted file mode 100644 index 6f6fa4d2b..000000000 --- a/test/qml/Global/+desktop/test_RetryCounter.qml +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtTest -import Governikus.Global - -TestCase { - id: testCase - - function createTestObject() { - return createTemporaryQmlObject("import Governikus.Global; RetryCounter { width: 64; height: 64 }", testCase); - } - function test_load() { - let testObject = createTestObject(); - verify(testObject, "Object loaded"); - } - - name: "test_RetryCounter" - visible: true - when: windowShown -} diff --git a/test/qml/Global/+desktop/test_RoundedRectangle.qml b/test/qml/Global/+desktop/test_RoundedRectangle.qml index f1d2acb21..14c475d82 100644 --- a/test/qml/Global/+desktop/test_RoundedRectangle.qml +++ b/test/qml/Global/+desktop/test_RoundedRectangle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_ScrollGradients.qml b/test/qml/Global/+desktop/test_ScrollGradients.qml index 9469288b4..a9ab9c198 100644 --- a/test/qml/Global/+desktop/test_ScrollGradients.qml +++ b/test/qml/Global/+desktop/test_ScrollGradients.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_TabbedPane.qml b/test/qml/Global/+desktop/test_TabbedPane.qml index d0194543a..091909607 100644 --- a/test/qml/Global/+desktop/test_TabbedPane.qml +++ b/test/qml/Global/+desktop/test_TabbedPane.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+mobile/test_GCollapsibleSubButton.qml b/test/qml/Global/+mobile/test_GCollapsibleSubButton.qml index 5c16eab46..31fcf1a15 100644 --- a/test/qml/Global/+mobile/test_GCollapsibleSubButton.qml +++ b/test/qml/Global/+mobile/test_GCollapsibleSubButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+mobile/test_GOptionsContainer.qml b/test/qml/Global/+mobile/test_GOptionsContainer.qml index 9bbb0d14f..efcd34aa4 100644 --- a/test/qml/Global/+mobile/test_GOptionsContainer.qml +++ b/test/qml/Global/+mobile/test_GOptionsContainer.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+mobile/test_PaneTitle.qml b/test/qml/Global/+mobile/test_PaneTitle.qml index b1547421d..35d992527 100644 --- a/test/qml/Global/+mobile/test_PaneTitle.qml +++ b/test/qml/Global/+mobile/test_PaneTitle.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+mobile/test_SwipeActionDelegate.qml b/test/qml/Global/+mobile/test_SwipeActionDelegate.qml deleted file mode 100644 index 6b926949d..000000000 --- a/test/qml/Global/+mobile/test_SwipeActionDelegate.qml +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtTest -import Governikus.Global - -TestCase { - id: testCase - - function createTestObject() { - return createTemporaryQmlObject("import Governikus.Global; SwipeActionDelegate {}", testCase); - } - function test_load() { - let testObject = createTestObject(); - verify(testObject, "Object loaded"); - } - - name: "test_SwipeActionDelegate" - visible: true - when: windowShown -} diff --git a/test/qml/Global/+mobile/test_TitledSeparator.qml b/test/qml/Global/+mobile/test_TitledSeparator.qml index 32ae47431..f006998c1 100644 --- a/test/qml/Global/+mobile/test_TitledSeparator.qml +++ b/test/qml/Global/+mobile/test_TitledSeparator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_ConfirmationPopup.qml b/test/qml/Global/test_ConfirmationPopup.qml index 3dd0ac4eb..b2c43993a 100644 --- a/test/qml/Global/test_ConfirmationPopup.qml +++ b/test/qml/Global/test_ConfirmationPopup.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -32,12 +32,12 @@ TestCase { let testObject = createTestObject(); testObject.open(); tryVerify(function () { - return testObject.opened; - }); + return testObject.opened; + }); testObject.close(); tryVerify(function () { - return !testObject.opened; - }); + return !testObject.opened; + }); } function test_style() { let testObject = createTestObject(); @@ -81,12 +81,12 @@ TestCase { compare(testObject.text, "", "text: empty"); testObject.open(); tryVerify(function () { - return testObject.opened; - }); + return testObject.opened; + }); testObject.accept(); tryVerify(function () { - return !testObject.opened; - }); + return !testObject.opened; + }); compare(testObject.text, "confirmed", "text: confirmed"); } function test_cancel() { @@ -95,12 +95,12 @@ TestCase { compare(testObject.text, "", "text: empty"); testObject.open(); tryVerify(function () { - return testObject.opened; - }); + return testObject.opened; + }); testObject.cancel(); tryVerify(function () { - return !testObject.opened; - }); + return !testObject.opened; + }); compare(testObject.text, "cancelled", "text: cancelled"); } diff --git a/test/qml/Global/test_Constants.qml b/test/qml/Global/test_Constants.qml index 420d23cce..552ba469b 100644 --- a/test/qml/Global/test_Constants.qml +++ b/test/qml/Global/test_Constants.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GBusyIndicator.qml b/test/qml/Global/test_GBusyIndicator.qml index a685e5179..0a8cf0c93 100644 --- a/test/qml/Global/test_GBusyIndicator.qml +++ b/test/qml/Global/test_GBusyIndicator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GButton.qml b/test/qml/Global/test_GButton.qml index 499784680..cf3f2ec7c 100644 --- a/test/qml/Global/test_GButton.qml +++ b/test/qml/Global/test_GButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQml import QtQuick @@ -75,49 +75,154 @@ TestCase { } ", testCase); tryCompare(buttonSmallLayout, "buttonHeight", data.height); - tryCompare(buttonSmallLayout, "buttonWidth", Math.min(data.width, Constants.is_desktop ? 120 : 80)); + tryCompare(buttonSmallLayout, "buttonWidth", Math.min(data.width, Constants.is_desktop ? 132 : 104)); } function test_size_data() { let longText = createTemporaryQmlObject("import Governikus.Global; import Governikus.Style; GText {textStyle: Style.text.button; text: \"test test test test test test\"}", testCase); verify(waitForRendering(longText)); let longTextWidth = Math.ceil(longText.width); - return [{ + return [ + { "tag": "noIconNoText", "icon": "", "text": "", "height": Constants.is_desktop ? 40 : 39, - "width": Constants.is_desktop ? 120 : 80 - }, { + "width": Constants.is_desktop ? 132 : 104 + }, + { "tag": "noIconSmallText", "icon": "", "text": "t", "height": Constants.is_desktop ? 40 : 39, - "width": Constants.is_desktop ? 120 : 80 - }, { + "width": Constants.is_desktop ? 132 : 104 + }, + { "tag": "noIconLongText", "icon": "", "text": "test test test test test test", "height": Constants.is_desktop ? 40 : 39, - "width": 16 + longTextWidth - }, { + "width": (Constants.is_desktop ? 36 : 40) + longTextWidth + }, + { "tag": "withIconNoText", "icon": "qrc:///images/npa.svg", "text": "", "height": Constants.is_desktop ? 40 : 39, - "width": Constants.is_desktop ? 120 : 80 - }, { + "width": Constants.is_desktop ? 132 : 104 + }, + { "tag": "withIconSmallText", "icon": "qrc:///images/npa.svg", "text": "t", "height": Constants.is_desktop ? 40 : 39, - "width": Constants.is_desktop ? 120 : 80 - }, { + "width": Constants.is_desktop ? 132 : 104 + }, + { "tag": "withIconLongText", "icon": "qrc:///images/npa.svg", "text": "test test test test test test", "height": Constants.is_desktop ? 40 : 39, - "width": (Constants.is_desktop ? 50 : 53) + longTextWidth - }]; + "width": 68 + longTextWidth + } + ]; + } + function test_size_withoutBackground(data) { + let button = createTemporaryQmlObject(" + import Governikus.Global + GButton { + icon.source: \"" + data.icon + "\" + text: \"" + data.text + "\" + background: null + } + ", testCase); + tryCompare(button, "height", data.height); + tryCompare(button, "width", data.width); + let buttonInLayout = createTemporaryQmlObject(" + import Governikus.Global + import QtQuick.Layouts + ColumnLayout { + readonly property alias buttonHeight: mybutton.height + readonly property alias buttonWidth: mybutton.width + width: 1000 + GButton { + id: mybutton + icon.source: \"" + data.icon + "\" + text: \"" + data.text + "\" + background: null + } + } + ", testCase); + tryCompare(buttonInLayout, "buttonHeight", data.height); + tryCompare(buttonInLayout, "buttonWidth", data.width); + let buttonSmallLayout = createTemporaryQmlObject(" + import Governikus.Global + import QtQuick.Layouts + ColumnLayout { + readonly property alias buttonHeight: mybutton.height + readonly property alias buttonWidth: mybutton.width + width: 75 + GButton { + id: mybutton + icon.source: \"" + data.icon + "\" + text: \"" + data.text + "\" + background: null + } + } + ", testCase); + tryCompare(buttonSmallLayout, "buttonHeight", data.height); + tryCompare(buttonSmallLayout, "buttonWidth", Math.min(data.width, 75)); + } + function test_size_withoutBackground_data() { + let longText = createTemporaryQmlObject("import Governikus.Global; import Governikus.Style; GText {textStyle: Style.text.button; text: \"test test test test test test\"}", testCase); + verify(waitForRendering(longText)); + let longTextWidth = Math.ceil(longText.width); + let smallText = createTemporaryQmlObject("import Governikus.Global; import Governikus.Style; GText {textStyle: Style.text.button; text: \"t\"}", testCase); + verify(waitForRendering(smallText)); + let smallTextWidth = Math.ceil(smallText.width); + return [ + { + "tag": "noIconNoText", + "icon": "", + "text": "", + "height": Constants.is_desktop ? 40 : 39, + "width": Constants.is_desktop ? 36 : 40 + }, + { + "tag": "noIconSmallText", + "icon": "", + "text": "t", + "height": Constants.is_desktop ? 40 : 39, + "width": (Constants.is_desktop ? 36 : 40) + smallTextWidth + }, + { + "tag": "noIconLongText", + "icon": "", + "text": "test test test test test test", + "height": Constants.is_desktop ? 40 : 39, + "width": (Constants.is_desktop ? 36 : 40) + longTextWidth + }, + { + "tag": "withIconNoText", + "icon": "qrc:///images/npa.svg", + "text": "", + "height": Constants.is_desktop ? 40 : 39, + "width": Constants.is_desktop ? 56 : 58 + }, + { + "tag": "withIconSmallText", + "icon": "qrc:///images/npa.svg", + "text": "t", + "height": Constants.is_desktop ? 40 : 39, + "width": 68 + smallTextWidth + }, + { + "tag": "withIconLongText", + "icon": "qrc:///images/npa.svg", + "text": "test test test test test test", + "height": Constants.is_desktop ? 40 : 39, + "width": 68 + longTextWidth + } + ]; } function test_text() { let testObject = createTestObject(); @@ -128,8 +233,6 @@ TestCase { function test_textStyle() { let testObject = createTestObject(); compare(testObject.textStyle, Style.text.button, "Initial textStyle: button"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); } function test_tooltipText() { let testObject = createTestObject(); @@ -157,12 +260,12 @@ TestCase { verify(!testObject.pressed, "pressed: false"); mousePress(testObject); tryVerify(function () { - return testObject.pressed; - }); + return testObject.pressed; + }); mouseRelease(testObject); tryVerify(function () { - return !testObject.pressed; - }); + return !testObject.pressed; + }); } function test_tintIcon() { verify(!testObject.tintIcon, "Initial tintIcon: false"); diff --git a/test/qml/Global/test_GCheckBox.qml b/test/qml/Global/test_GCheckBox.qml index 7bffd2432..cc6564cc4 100644 --- a/test/qml/Global/test_GCheckBox.qml +++ b/test/qml/Global/test_GCheckBox.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -42,8 +42,8 @@ TestCase { verify(!testObject.checked, "Initial checked: false"); mouseClick(testObject); tryVerify(function () { - return testObject.checked; - }); + return testObject.checked; + }); } when: windowShown diff --git a/test/qml/Global/test_GComboBox.qml b/test/qml/Global/test_GComboBox.qml index eaffe6daf..c0f46dffb 100644 --- a/test/qml/Global/test_GComboBox.qml +++ b/test/qml/Global/test_GComboBox.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -25,8 +25,6 @@ TestCase { function test_textStyle() { let testObject = createTestObject(); compare(testObject.textStyle, Style.text.normal, "Initial textStyle: normal"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); } name: "test_GComboBox" @@ -43,13 +41,13 @@ TestCase { verify(!testObject.popup.visible, "Initial popup visible: false"); mouseClick(testObject); tryVerify(function () { - return testObject.popup; - }); + return testObject.popup; + }); compare(testObject.popup.visible, true); mouseClick(testObject); tryVerify(function () { - return testObject.popup; - }); + return testObject.popup; + }); compare(testObject.popup.visible, false); } function test_model() { diff --git a/test/qml/Global/test_GFlickable.qml b/test/qml/Global/test_GFlickable.qml index 74f8bd86b..3961f205b 100644 --- a/test/qml/Global/test_GFlickable.qml +++ b/test/qml/Global/test_GFlickable.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -15,8 +15,52 @@ TestCase { let testObject = createTestObject(); verify(testObject, "Object loaded"); } + function test_positionViewAtItem() { + let testFlickable = flickable.createObject(testCase); + let childrenCount = testFlickable.columnChildren.length; + for (let i = 0; i < childrenCount; ++i) { + let child = testFlickable.columnChildren[i]; + testFlickable.positionViewAtItem(child); + verify(testFlickable.contentY >= child.y); + verify(testFlickable.contentY <= (child.y + child.height)); + } + for (let j = childrenCount - 1; j >= 0; --j) { + let child = testFlickable.columnChildren[j]; + testFlickable.positionViewAtItem(child); + verify(testFlickable.contentY >= child.y); + verify(testFlickable.contentY <= (child.y + child.height)); + } + } name: "test_GFlickable" visible: true when: windowShown + + Component { + id: flickable + + GFlickable { + property alias columnChildren: column.children + + contentHeight: column.implicitHeight + height: 50 + width: 50 + + Column { + id: column + + anchors.fill: parent + spacing: 0 + + Repeater { + model: 10 + + Rectangle { + height: 50 + width: 50 + } + } + } + } + } } diff --git a/test/qml/Global/test_GFlickableColumnLayout.qml b/test/qml/Global/test_GFlickableColumnLayout.qml index 80bf13023..6b08d58d1 100644 --- a/test/qml/Global/test_GFlickableColumnLayout.qml +++ b/test/qml/Global/test_GFlickableColumnLayout.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GInformativeButton.qml b/test/qml/Global/test_GInformativeButton.qml index 44c9601b2..873567cea 100644 --- a/test/qml/Global/test_GInformativeButton.qml +++ b/test/qml/Global/test_GInformativeButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -28,24 +28,12 @@ TestCase { let testObject = createTestObject(); verify(testObject, "Object loaded"); } - function test_scaleIcon() { - let testObject = createTestObject(); - compare(testObject.scaleIcon, 1.0, "Initial scale factor 1.0"); - testObject.scaleIcon = 0.75; - compare(testObject.scaleIcon, 0.75, "scaleIcon: 1.0"); - } function test_text() { let testObject = createTestObject(); compare(testObject.text, "", "Initial empty text"); testObject.text = "test"; compare(testObject.text, "test", "text: test"); } - function test_textStyle() { - let testObject = createTestObject(); - compare(testObject.textStyle, Style.text.button, "Initial textStyle: button"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); - } name: "test_GInformativeButton" visible: true @@ -55,7 +43,6 @@ TestCase { id: testObject icon.source: "qrc:///images/material_check.svg" - scaleIcon: 0.5 text: "test" TestCase { @@ -63,19 +50,12 @@ TestCase { verify(!testObject.pressed, "pressed: false"); mousePress(testObject); tryVerify(function () { - return testObject.pressed; - }); + return testObject.pressed; + }); mouseRelease(testObject); tryVerify(function () { - return !testObject.pressed; - }); - } - function test_tintIcon() { - verify(!testObject.tintIcon, "Initial tintIcon: false"); - testObject.tintIcon = true; - verify(testObject.tintIcon, "tintIcon: true"); - testObject.tintIcon = false; - verify(!testObject.tintIcon, "tintIcon: false"); + return !testObject.pressed; + }); } when: windowShown diff --git a/test/qml/Global/test_GListView.qml b/test/qml/Global/test_GListView.qml index a2eed4192..bbb8122e1 100644 --- a/test/qml/Global/test_GListView.qml +++ b/test/qml/Global/test_GListView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/+desktop/test_ScrollablePane.qml b/test/qml/Global/test_GMenuItem.qml similarity index 72% rename from test/qml/Global/+desktop/test_ScrollablePane.qml rename to test/qml/Global/test_GMenuItem.qml index 09e268115..a4448024c 100644 --- a/test/qml/Global/+desktop/test_ScrollablePane.qml +++ b/test/qml/Global/test_GMenuItem.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -9,7 +9,7 @@ TestCase { id: testCase function createTestObject() { - return createTemporaryQmlObject("import Governikus.Global; ScrollablePane {}", testCase); + return createTemporaryQmlObject("import Governikus.Global; GMenuItem {}", testCase); } function test_load() { let testObject = createTestObject(); @@ -22,7 +22,7 @@ TestCase { compare(testObject.title, "test", "title: test"); } - name: "test_ScrollablePane" + name: "test_GMenuItem" visible: true when: windowShown } diff --git a/test/qml/Global/test_GPane.qml b/test/qml/Global/test_GPane.qml index 61456dfb8..eb6bcc8f6 100644 --- a/test/qml/Global/test_GPane.qml +++ b/test/qml/Global/test_GPane.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GPaneBackground.qml b/test/qml/Global/test_GPaneBackground.qml index 3813239cc..a110b7d3f 100644 --- a/test/qml/Global/test_GPaneBackground.qml +++ b/test/qml/Global/test_GPaneBackground.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GPaneBackgroundDelegate.qml b/test/qml/Global/test_GPaneBackgroundDelegate.qml index edb15aabd..2d1503b3c 100644 --- a/test/qml/Global/test_GPaneBackgroundDelegate.qml +++ b/test/qml/Global/test_GPaneBackgroundDelegate.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GProgressBar.qml b/test/qml/Global/test_GProgressBar.qml new file mode 100644 index 000000000..b24aa4fd1 --- /dev/null +++ b/test/qml/Global/test_GProgressBar.qml @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtTest +import Governikus.Global +import Governikus.Type + +TestCase { + id: testCase + + function createTestObject() { + return createTemporaryQmlObject("import Governikus.Global; GProgressBar {}", testCase); + } + function test_load() { + let testObject = createTestObject(""); + verify(testObject, "Object loaded"); + } + function test_text() { + let testObject = createTestObject(); + compare(testObject.text, "", "Initial empty text"); + testObject.text = "test"; + compare(testObject.text, "test", "Text: test"); + } + function test_value(data) { + SettingsModel.useAnimations = data.useAnimations; + let testObject = createTestObject(); + testObject.value = data.value; + tryCompare(testObject, "effectiveVisualPosition", data.effectiveVisualPosition); + } + function test_value_data() { + return [ + { + "tag": "With Animation, 0", + "useAnimations": true, + "value": 0, + "effectiveVisualPosition": 0 + }, + { + "tag": "With Animation, 10", + "useAnimations": true, + "value": 10, + "effectiveVisualPosition": 0.1 + }, + { + "tag": "With Animation, 50", + "useAnimations": true, + "value": 50, + "effectiveVisualPosition": 0.5 + }, + { + "tag": "With Animation, 100", + "useAnimations": true, + "value": 100, + "effectiveVisualPosition": 1 + }, + { + "tag": "Without Animation, 0", + "useAnimations": false, + "value": 0, + "effectiveVisualPosition": 0.25 + }, + { + "tag": "Without Animation, 10", + "useAnimations": false, + "value": 10, + "effectiveVisualPosition": 0.25 + }, + { + "tag": "Without Animation, 50", + "useAnimations": false, + "value": 50, + "effectiveVisualPosition": 0.25 + }, + { + "tag": "Without Animation, 100", + "useAnimations": false, + "value": 100, + "effectiveVisualPosition": 1 + } + ]; + } + + name: "test_GProgressBar" + visible: true + when: windowShown +} diff --git a/test/qml/Global/test_GRadioButton.qml b/test/qml/Global/test_GRadioButton.qml index 64c677057..cc47252cd 100644 --- a/test/qml/Global/test_GRadioButton.qml +++ b/test/qml/Global/test_GRadioButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -28,12 +28,6 @@ TestCase { testObject.text = "test"; compare(testObject.text, "test", "text: test"); } - function test_textStyle() { - let testObject = createTestObject(); - compare(testObject.textStyle, Style.text.normal, "Initial textStyle: normal"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); - } function test_tintIcon() { let testObject = createTestObject(); verify(!testObject.tintIcon, "Initial tintIcon: false"); diff --git a/test/qml/Global/test_GRepeater.qml b/test/qml/Global/test_GRepeater.qml index 52c3afa1b..eef1289f8 100644 --- a/test/qml/Global/test_GRepeater.qml +++ b/test/qml/Global/test_GRepeater.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtQml.Models @@ -17,21 +17,35 @@ TestCase { verify(testObject, "Object loaded"); } function test_model() { + let testModel = testModelComponent.createObject(testCase); + let testObject = testObjectComponent.createObject(testCase, { + "model": testModel + }); expected.text = testModel.get(2).name; - compare(testObject1.maxItemWidth, expected.implicitWidth, "maxItemWidth"); + compare(testObject.maxItemWidth, expected.implicitWidth, "maxItemWidth"); testModel.append({ - "name": "Test" - }); - compare(testObject1.maxItemWidth, expected.implicitWidth, "maxItemWidth"); + "name": "Test" + }); + compare(testObject.maxItemWidth, expected.implicitWidth, "maxItemWidth"); testModel.append({ - "name": "a large new text" - }); + "name": "a large new text" + }); expected.text = testModel.get(4).name; - compare(testObject1.maxItemWidth, expected.implicitWidth, "maxItemWidth"); + compare(testObject.maxItemWidth, expected.implicitWidth, "maxItemWidth"); testModel.append({ - "name": "Test" - }); - compare(testObject1.maxItemWidth, expected.implicitWidth, "maxItemWidth"); + "name": "Test" + }); + compare(testObject.maxItemWidth, expected.implicitWidth, "maxItemWidth"); + } + function test_model_without_autoConsider() { + let testModel = testModelComponent.createObject(testCase); + let testObject = testObjectComponent.createObject(testCase, { + "autoConsiderItems": false, + "considerFirstItem": true, + "model": testModel + }); + expected.text = testModel.get(0).name; + compare(testObject.maxItemWidth, expected.implicitWidth, "maxItemWidth"); } name: "test_GRepeater" @@ -42,26 +56,39 @@ TestCase { id: expected } - ListModel { - id: testModel + Component { + id: testModelComponent - ListElement { - name: "Apple" - } - ListElement { - name: "Orange" - } - ListElement { - name: "Banana" + ListModel { + ListElement { + name: "Apple" + } + ListElement { + name: "Orange" + } + ListElement { + name: "Banana" + } } } - GRepeater { - id: testObject1 + Component { + id: testObjectComponent + + GRepeater { + id: repeater + + property bool considerFirstItem: false - model: testModel + Text { + text: name - Text { - text: name + Component.onCompleted: { + if (repeater.considerFirstItem && index === 0) { + repeater.addConsideredItem(this); + } + } + Component.onDestruction: repeater.removeConsideredItem(this) + } } } } diff --git a/test/qml/Global/test_GScrollBar.qml b/test/qml/Global/test_GScrollBar.qml index 7982530ce..0aa46d8c3 100644 --- a/test/qml/Global/test_GScrollBar.qml +++ b/test/qml/Global/test_GScrollBar.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -15,23 +15,23 @@ TestCase { let testObject = createTestObject(); mousePress(testObject); tryVerify(function () { - return testObject.pressed; - }); + return testObject.pressed; + }); mouseRelease(testObject); tryVerify(function () { - return !testObject.pressed; - }); + return !testObject.pressed; + }); } function test_highlight() { let testObject = createTestObject(); tryVerify(function () { - return !testObject.highlighted; - }); + return !testObject.highlighted; + }); testObject.highlight(); verify(testObject.highlighted, "highlighted: true"); tryVerify(function () { - return !testObject.highlighted; - }); + return !testObject.highlighted; + }); } function test_load() { let testObject = createTestObject(); diff --git a/test/qml/Global/test_GSeparator.qml b/test/qml/Global/test_GSeparator.qml index 9a230532e..02928982f 100644 --- a/test/qml/Global/test_GSeparator.qml +++ b/test/qml/Global/test_GSeparator.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_GSwitch.qml b/test/qml/Global/test_GSwitch.qml index b2b39e197..be87bf207 100644 --- a/test/qml/Global/test_GSwitch.qml +++ b/test/qml/Global/test_GSwitch.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -19,10 +19,22 @@ TestCase { testObject.checked = false; verify(!testObject.checked, "checked: false"); } + function test_description() { + let testObject = createTestObject(); + compare(testObject.description, "", "Initial description: empty"); + testObject.description = "test"; + compare(testObject.description, "test", "description: test"); + } function test_load() { let testObject = createTestObject(); verify(testObject, "Object loaded"); } + function test_text() { + let testObject = createTestObject(); + compare(testObject.text, "", "Initial text: empty"); + testObject.text = "test"; + compare(testObject.text, "test", "text: test"); + } name: "test_GSwitch" visible: true diff --git a/test/qml/Global/test_GText.qml b/test/qml/Global/test_GText.qml index f0602c882..f313f8648 100644 --- a/test/qml/Global/test_GText.qml +++ b/test/qml/Global/test_GText.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -25,8 +25,6 @@ TestCase { function test_textStyle() { let testObject = createTestObject(); compare(testObject.textStyle, Style.text.normal, "Initial textStyle: normal"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); } name: "test_GText" diff --git a/test/qml/Global/test_GTextField.qml b/test/qml/Global/test_GTextField.qml index ff639e8b8..f1a6d9be4 100644 --- a/test/qml/Global/test_GTextField.qml +++ b/test/qml/Global/test_GTextField.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -12,12 +12,6 @@ TestCase { function createTestObject() { return createTemporaryQmlObject("import Governikus.Global; GTextField {}", testCase); } - function test_enabled() { - let testObject = createTestObject(); - verify(testObject.enabled, "Initial enabled true"); - testObject.enabled = false; - verify(!testObject.enabled, "enabled false"); - } function test_enterKeyType() { let testObject = createTestObject(); compare(testObject.enterKeyType, Qt.EnterKeyDefault, "Initial enterKeyType: Qt.EnterKeyDefault"); @@ -37,14 +31,6 @@ TestCase { function test_textStyle() { let testObject = createTestObject(); compare(testObject.textStyle, Style.text.normal, "Initial textStyle: normal"); - testObject.textStyle = Style.text.normal_warning; - compare(testObject.textStyle, Style.text.normal_warning, "textStyle: hint_warning"); - } - function test_valid() { - let testObject = createTestObject(); - verify(testObject.valid, "Initial valid true"); - testObject.valid = false; - verify(!testObject.valid, "valid false"); } name: "test_GTextField" diff --git a/test/qml/Global/test_Hint.qml b/test/qml/Global/test_Hint.qml index b9f3776db..564ebb161 100644 --- a/test/qml/Global/test_Hint.qml +++ b/test/qml/Global/test_Hint.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_LabeledSwitch.qml b/test/qml/Global/test_LabeledSwitch.qml deleted file mode 100644 index 6c2d41417..000000000 --- a/test/qml/Global/test_LabeledSwitch.qml +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany - */ -import QtQuick -import QtTest -import Governikus.Global - -TestCase { - id: testCase - - function createTestObject() { - return createTemporaryQmlObject("import Governikus.Global; LabeledSwitch {}", testCase); - } - function test_checked() { - let testObject = createTestObject(); - verify(!testObject.checked, "Initial checked: false"); - testObject.checked = true; - verify(testObject.checked, "checked: true"); - testObject.checked = false; - verify(!testObject.checked, "checked: false"); - } - function test_description() { - let testObject = createTestObject(); - compare(testObject.description, "", "Initial description: empty"); - testObject.description = "test"; - compare(testObject.description, "test", "description: test"); - } - function test_load() { - let testObject = createTestObject(); - verify(testObject, "Object loaded"); - } - function test_title() { - if (!Constants.is_desktop) { - skip("Skip test because of flaky behavior for mobile on Linux"); - } - let testObject = createTestObject(); - compare(testObject.title, "", "Initial title: empty"); - testObject.title = "test"; - compare(testObject.title, "test", "title: test"); - } - - name: "test_LabeledSwitch" - visible: true - when: windowShown -} diff --git a/test/qml/Global/test_LabeledText.qml b/test/qml/Global/test_LabeledText.qml index 14f83c9dd..d0e9543a3 100644 --- a/test/qml/Global/test_LabeledText.qml +++ b/test/qml/Global/test_LabeledText.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_NumberField.qml b/test/qml/Global/test_NumberField.qml index eb3473636..ea1e6fe4c 100644 --- a/test/qml/Global/test_NumberField.qml +++ b/test/qml/Global/test_NumberField.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_PkiSwitch.qml b/test/qml/Global/test_PkiSwitch.qml index 4ecab6045..344c4557f 100644 --- a/test/qml/Global/test_PkiSwitch.qml +++ b/test/qml/Global/test_PkiSwitch.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_PrivacyStatement.qml b/test/qml/Global/test_PrivacyStatement.qml index b171fb7c5..8bd166309 100644 --- a/test/qml/Global/test_PrivacyStatement.qml +++ b/test/qml/Global/test_PrivacyStatement.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_ProxyCredentialsPopup.qml b/test/qml/Global/test_ProxyCredentialsPopup.qml index 5b1bc9493..a15f7d299 100644 --- a/test/qml/Global/test_ProxyCredentialsPopup.qml +++ b/test/qml/Global/test_ProxyCredentialsPopup.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Global/test_StatefulColors.qml b/test/qml/Global/test_StatefulColors.qml new file mode 100644 index 000000000..52b4edeff --- /dev/null +++ b/test/qml/Global/test_StatefulColors.qml @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtTest +import Governikus.Global +import Governikus.Type + +Item { + id: control + + property bool checkable: true + property bool checked: false + property bool enabled: true + property bool hovered: false + property bool pressed: false + + StatefulColors { + id: colors + + statefulControl: control + } + TestCase { + id: testCase + + function test_checked() { + control.enabled = true; + control.pressed = false; + control.hovered = false; + control.checked = true; + compare(colors.state, "checked"); + } + function test_disabled(data) { + control.enabled = false; + control.pressed = data.pressed; + control.hovered = data.hovered; + control.checked = data.checked; + compare(colors.state, "disabled"); + } + function test_disabled_data() { + return [ + { + "tag": "1", + "hovered": false, + "pressed": false, + "checked": false + }, + { + "tag": "2", + "hovered": true, + "pressed": false, + "checked": false + }, + { + "tag": "3", + "hovered": false, + "pressed": true, + "checked": false + }, + { + "tag": "4", + "hovered": false, + "pressed": false, + "checked": true + }, + ]; + } + function test_hovered(data) { + let desktopOrChromeOS = Constants.is_desktop || UiPluginModel.isChromeOS; + control.enabled = true; + control.pressed = false; + control.hovered = desktopOrChromeOS; + control.checked = data.checked; + colors.groupMember = data.groupMember; + if (desktopOrChromeOS) { + compare(colors.state, data.state); + } else { + verify(colors.state !== "hovered"); + } + } + function test_hovered_data() { + return [ + { + "tag": "1", + "checked": false, + "groupMember": false, + "state": "hovered" + }, + { + "tag": "2", + "checked": true, + "groupMember": false, + "state": "hovered" + }, + { + "tag": "3", + "checked": false, + "groupMember": true, + "state": "hovered" + }, + { + "tag": "4", + "checked": true, + "groupMember": true, + "state": "checked" + } + ]; + } + function test_pressed(data) { + control.enabled = true; + control.pressed = true; + control.hovered = data.hovered; + control.checked = data.checked; + colors.groupMember = data.groupMember; + compare(colors.state, data.state); + } + function test_pressed_data() { + return [ + { + "tag": "1", + "hovered": false, + "checked": false, + "groupMember": false, + "state": "pressed" + }, + { + "tag": "2", + "hovered": true, + "checked": false, + "groupMember": false, + "state": "pressed" + }, + { + "tag": "3", + "hovered": false, + "checked": true, + "groupMember": false, + "state": "pressed" + }, + { + "tag": "4", + "hovered": false, + "checked": false, + "groupMember": true, + "state": "pressed" + }, + { + "tag": "5", + "hovered": true, + "checked": false, + "groupMember": true, + "state": "pressed" + }, + { + "tag": "6", + "hovered": false, + "checked": true, + "groupMember": true, + "state": "checked" + } + ]; + } + + name: "test_StatefulColors" + visible: true + when: windowShown + } +} diff --git a/test/qml/Global/test_TintableIcon.qml b/test/qml/Global/test_TintableIcon.qml index 7844c2c16..e3790e198 100644 --- a/test/qml/Global/test_TintableIcon.qml +++ b/test/qml/Global/test_TintableIcon.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -12,10 +12,6 @@ TestCase { function createTestObject() { return createTemporaryQmlObject("import Governikus.Global; TintableIcon {}", testCase); } - function test_fillMode() { - let testObject = createTestObject(); - compare(testObject.fillMode, Image.PreserveAspectFit, "Initial fillMode: PreserveAspectFit"); - } function test_icon() { let testObject = createTestObject(); compare(testObject.source, "", "Initial no image"); @@ -28,7 +24,7 @@ TestCase { } function test_tintColor() { let testObject = createTestObject(); - compare(testObject.tintColor, Style.color.text, "Initial tintColor: text"); + compare(testObject.tintColor, Style.color.textNormal.basic, "Initial tintColor: text"); testObject.tintColor = "#000000"; compare(testObject.tintColor, "#000000", "Set tintColor"); } diff --git a/test/qml/Global/test_Utils.qml b/test/qml/Global/test_Utils.qml index 43562a713..9dd891be8 100644 --- a/test/qml/Global/test_Utils.qml +++ b/test/qml/Global/test_Utils.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ import QtTest import Governikus.Global diff --git a/test/qml/InformationView/+desktop/test_ReleaseNotes.qml b/test/qml/InformationView/+desktop/test_ReleaseNotes.qml index 83bf3163b..b9ad349f9 100644 --- a/test/qml/InformationView/+desktop/test_ReleaseNotes.qml +++ b/test/qml/InformationView/+desktop/test_ReleaseNotes.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/InformationView/+mobile/test_ReleaseNotes.qml b/test/qml/InformationView/+mobile/test_ReleaseNotes.qml index f668b32f0..d9d1cd41f 100644 --- a/test/qml/InformationView/+mobile/test_ReleaseNotes.qml +++ b/test/qml/InformationView/+mobile/test_ReleaseNotes.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/InformationView/test_LicenseInformation.qml b/test/qml/InformationView/test_LicenseInformation.qml index 21aa57c44..444338a94 100644 --- a/test/qml/InformationView/test_LicenseInformation.qml +++ b/test/qml/InformationView/test_LicenseInformation.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/InformationView/test_ReleaseNotesView.qml b/test/qml/InformationView/test_ReleaseNotesView.qml index 53607102b..ab0f41c4a 100644 --- a/test/qml/InformationView/test_ReleaseNotesView.qml +++ b/test/qml/InformationView/test_ReleaseNotesView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtTest import Governikus.Global diff --git a/test/qml/Navigation/+mobile/test_Navigation.qml b/test/qml/Navigation/+mobile/test_Navigation.qml index 1198fc073..2858ebbe0 100644 --- a/test/qml/Navigation/+mobile/test_Navigation.qml +++ b/test/qml/Navigation/+mobile/test_Navigation.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/PasswordInfoView/+desktop/test_PasswordInfoView.qml b/test/qml/PasswordInfoView/test_PasswordInfoView.qml similarity index 64% rename from test/qml/PasswordInfoView/+desktop/test_PasswordInfoView.qml rename to test/qml/PasswordInfoView/test_PasswordInfoView.qml index d5b264eb3..1b1bf376a 100644 --- a/test/qml/PasswordInfoView/+desktop/test_PasswordInfoView.qml +++ b/test/qml/PasswordInfoView/test_PasswordInfoView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtTest import Governikus.PasswordInfoView @@ -19,13 +19,17 @@ TestCase { item.destroy(); } function test_load_PasswordInfoView_data() { - return [{ - "contentType": PasswordInfoContent.Type.PIN - }, { - "contentType": PasswordInfoContent.Type.CAN - }, { - "contentType": PasswordInfoContent.Type.PUK - }]; + return [ + { + "contentType": PasswordInfoData.Type.PIN + }, + { + "contentType": PasswordInfoData.Type.CAN + }, + { + "contentType": PasswordInfoData.Type.PUK + } + ]; } visible: true diff --git a/test/qml/QmlTestRunner.cpp b/test/qml/QmlTestRunner.cpp index f5945c6ff..32bfee836 100644 --- a/test/qml/QmlTestRunner.cpp +++ b/test/qml/QmlTestRunner.cpp @@ -1,25 +1,27 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "Env.h" #include "MockNetworkManager.h" #include "ReaderManager.h" #include "ResourceLoader.h" -#include "UIPlugInQml.h" +#include "UiLoader.h" +#include "UiPluginQml.h" #include #include #include #include -#include #include #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; +Q_IMPORT_PLUGIN(UiPluginQml) Q_DECLARE_LOGGING_CATEGORY(init) class QmlTestRunner @@ -27,47 +29,21 @@ class QmlTestRunner { Q_OBJECT - // Mock of the UIPluginQml properties - Q_PROPERTY(bool debugBuild MEMBER mFalse CONSTANT) - Q_PROPERTY(bool developerVersion MEMBER mFalse CONSTANT) - Q_PROPERTY(bool dominated MEMBER mFalse CONSTANT) - Q_PROPERTY(QVariantMap safeAreaMargins MEMBER mSafeAreaMargins CONSTANT) - Q_PROPERTY(bool highContrastEnabled MEMBER mFalse CONSTANT) - Q_PROPERTY(QString platformStyle MEMBER mPlatformStyle CONSTANT) - Q_PROPERTY(QString fixedFontFamily MEMBER mFixedFontFamily CONSTANT) - Q_PROPERTY(qreal scaleFactor MEMBER mScaleFactor CONSTANT) - Q_PROPERTY(qreal fontScaleFactor MEMBER mFontScaleFactor CONSTANT) - private: - const bool mFalse = false; - const QVariantMap mSafeAreaMargins = { - {"top", 0}, {"right", 0}, {"bottom", 0}, {"left", 0} - }; - QString mPlatformStyle; - QString mFixedFontFamily; - static constexpr qreal mScaleFactor = 0.6; - static constexpr qreal mFontScaleFactor = 1.0; - QSharedPointer mMockNetworkManager; - public: - Q_INVOKABLE void applyPlatformStyle(const QString& pPlatformStyle) - { - Q_UNUSED(pPlatformStyle) - } - public Q_SLOTS: void applicationAvailable() { QStandardPaths::setTestModeEnabled(true); - QCoreApplication::setApplicationName("TestQmlRunner"); + QCoreApplication::setApplicationName("TestQmlRunner"_L1); QQuickStyle::setStyle(QStringLiteral("Basic")); QThread::currentThread()->setObjectName(QStringLiteral("MainThread")); ResourceLoader::getInstance().init(); Env::getSingleton()->init(); mMockNetworkManager.reset(new MockNetworkManager()); Env::set(NetworkManager::staticMetaObject, mMockNetworkManager.get()); - UIPlugInQml::registerQmlTypes(); + UiPluginQml::registerQmlTypes(); } @@ -82,14 +58,20 @@ class QmlTestRunner void qmlEngineAvailable(QQmlEngine* pEngine) { - pEngine->rootContext()->setContextProperty(QStringLiteral("plugin"), this); + const auto& prefix = UiPluginQml::adjustQmlImportPath(pEngine); + pEngine->rootContext()->setContextProperty(QStringLiteral("importPrefix"), prefix); #if (QT_VERSION < QT_VERSION_CHECK(6, 4, 2)) - pEngine->rootContext()->setContextProperty("hasBindingLoop", true); + pEngine->rootContext()->setContextProperty(QStringLiteral("hasBindingLoop"), true); +#else + pEngine->rootContext()->setContextProperty(QStringLiteral("hasBindingLoop"), false); +#endif +#if (QT_VERSION < QT_VERSION_CHECK(6, 5, 2)) + pEngine->rootContext()->setContextProperty(QStringLiteral("hasPolishLoop"), true); #else - pEngine->rootContext()->setContextProperty("hasBindingLoop", false); + pEngine->rootContext()->setContextProperty(QStringLiteral("hasPolishLoop"), false); #endif - connect(pEngine, &QQmlEngine::warnings, [](const QList& pWarnings){ + connect(pEngine, &QQmlEngine::warnings, this, [](const QList& pWarnings){ bool fail = false; for (auto& warning : pWarnings) { @@ -104,10 +86,7 @@ class QmlTestRunner } }); - const QStringList selectors = QQmlFileSelector(pEngine).selector()->extraSelectors(); - mPlatformStyle = selectors.join(QLatin1String(",")); - - mFixedFontFamily = QFontDatabase::systemFont(QFontDatabase::FixedFont).family(); + Q_UNUSED(Env::getSingleton()->load()) } diff --git a/test/qml/AuthView/+mobile/test_ProviderInfoSection.qml b/test/qml/RemoteServiceView/+mobile/test_RemoteServiceSettings.qml similarity index 52% rename from test/qml/AuthView/+mobile/test_ProviderInfoSection.qml rename to test/qml/RemoteServiceView/+mobile/test_RemoteServiceSettings.qml index 2d00a5511..1fd415065 100644 --- a/test/qml/AuthView/+mobile/test_ProviderInfoSection.qml +++ b/test/qml/RemoteServiceView/+mobile/test_RemoteServiceSettings.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -8,14 +8,14 @@ TestCase { id: testCase function createTestObject() { - return createTemporaryQmlObject("import \"qrc:/qml/Governikus/AuthView/+mobile/\"; ProviderInfoSection {}", testCase); + return createTemporaryQmlObject("import Governikus.RemoteServiceView; RemoteServiceSettings { }", testCase); } function test_load() { let testObject = createTestObject(); verify(testObject, "Object loaded"); } - name: "test_ProviderInfoSection" + name: "test_RemoteServiceSettings" visible: true when: windowShown } diff --git a/test/qml/RemoteServiceView/+mobile/test_RemoteServiceView.qml b/test/qml/RemoteServiceView/+mobile/test_RemoteServiceView.qml index 33833b3af..e6ab2ad0c 100644 --- a/test/qml/RemoteServiceView/+mobile/test_RemoteServiceView.qml +++ b/test/qml/RemoteServiceView/+mobile/test_RemoteServiceView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/RemoteServiceView/test_LinkQuality.qml b/test/qml/RemoteServiceView/test_LinkQuality.qml new file mode 100644 index 000000000..5f1fcc650 --- /dev/null +++ b/test/qml/RemoteServiceView/test_LinkQuality.qml @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtTest +import Governikus.RemoteServiceView +import Governikus.Type + +TestCase { + id: testCase + + function createTestObject() { + return createTemporaryQmlObject("import Governikus.RemoteServiceView; LinkQuality {}", testCase); + } + function test_image(data) { + SettingsModel.useAnimations = data.useAnimations; + let testObject = createTestObject(); + testObject.inactive = !!data.inactive; + testObject.percent = data.percent; + verify(testObject.source.toString().includes(data.imageContains)); + } + function test_image_data() { + return [ + { + "tag": "With Animations, Inactive 0 %", + "useAnimations": true, + "inactive": true, + "percent": 0, + "imageContains": "inactive" + }, + { + "tag": "With Animations, Inactive 100 %", + "useAnimations": true, + "inactive": true, + "percent": 100, + "imageContains": "inactive" + }, + { + "tag": "With Animations, 10 %", + "useAnimations": true, + "percent": 10, + "imageContains": "inactive" + }, + { + "tag": "With Animations, 30 %", + "useAnimations": true, + "percent": 30, + "imageContains": "_25_" + }, + { + "tag": "With Animations, 45 %", + "useAnimations": true, + "percent": 45, + "imageContains": "_50_" + }, + { + "tag": "With Animations, 70 %", + "useAnimations": true, + "percent": 70, + "imageContains": "_75_" + }, + { + "tag": "With Animations, 90 %", + "useAnimations": true, + "percent": 90, + "imageContains": "_100_" + }, + { + "tag": "Without Animations, Inactive 0 %", + "useAnimations": false, + "inactive": true, + "percent": 0, + "imageContains": "inactive" + }, + { + "tag": "Without Animations, Inactive 100 %", + "useAnimations": false, + "inactive": true, + "percent": 100, + "imageContains": "inactive" + }, + { + "tag": "Without Animations, 10 %", + "useAnimations": false, + "percent": 10, + "imageContains": "inactive" + }, + { + "tag": "Without Animations, 30 %", + "useAnimations": false, + "percent": 30, + "imageContains": "_100_" + }, + { + "tag": "Without Animations, 45 %", + "useAnimations": false, + "percent": 45, + "imageContains": "_100_" + }, + { + "tag": "Without Animations, 70 %", + "useAnimations": false, + "percent": 70, + "imageContains": "_100_" + }, + { + "tag": "Without Animations, 90 %", + "useAnimations": false, + "percent": 90, + "imageContains": "_100_" + } + ]; + } + function test_load() { + let testObject = createTestObject(); + verify(testObject, "Object loaded"); + } + + name: "test_LinkQuality" + visible: true + when: windowShown +} diff --git a/test/qml/ResultView/+desktop/test_ResultView.qml b/test/qml/ResultView/+desktop/test_ResultView.qml index b60c74164..55e8a0e1f 100644 --- a/test/qml/ResultView/+desktop/test_ResultView.qml +++ b/test/qml/ResultView/+desktop/test_ResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/ResultView/+mobile/test_ResultErrorView.qml b/test/qml/ResultView/+mobile/test_ResultErrorView.qml index a3ea70386..67539d6b6 100644 --- a/test/qml/ResultView/+mobile/test_ResultErrorView.qml +++ b/test/qml/ResultView/+mobile/test_ResultErrorView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/ResultView/+mobile/test_ResultView.qml b/test/qml/ResultView/+mobile/test_ResultView.qml index 0d8ec54a0..8a7c14ac0 100644 --- a/test/qml/ResultView/+mobile/test_ResultView.qml +++ b/test/qml/ResultView/+mobile/test_ResultView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/SettingsView/+desktop/test_LanguageButtons.qml b/test/qml/SettingsView/+desktop/test_LanguageButtons.qml index d325c013d..ec7748d3b 100644 --- a/test/qml/SettingsView/+desktop/test_LanguageButtons.qml +++ b/test/qml/SettingsView/+desktop/test_LanguageButtons.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/SettingsView/+desktop/test_TabbedReaderView.qml b/test/qml/SettingsView/+desktop/test_TabbedReaderView.qml index 81d2dc61b..cf8511a15 100644 --- a/test/qml/SettingsView/+desktop/test_TabbedReaderView.qml +++ b/test/qml/SettingsView/+desktop/test_TabbedReaderView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/SettingsView/test_DarkModeButtons.qml b/test/qml/SettingsView/test_DarkModeButtons.qml index 65d1c3d1e..ba4f0112f 100644 --- a/test/qml/SettingsView/test_DarkModeButtons.qml +++ b/test/qml/SettingsView/test_DarkModeButtons.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/SettingsView/test_SettingsView.qml b/test/qml/SettingsView/test_SettingsView.qml index f0dcafb24..08271cf99 100644 --- a/test/qml/SettingsView/test_SettingsView.qml +++ b/test/qml/SettingsView/test_SettingsView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/SetupAssistantView/+desktop/test_SetupAutostartView.qml b/test/qml/SetupAssistantView/+desktop/test_SetupAutostartView.qml index 6cfdbc7d0..8bab114ee 100644 --- a/test/qml/SetupAssistantView/+desktop/test_SetupAutostartView.qml +++ b/test/qml/SetupAssistantView/+desktop/test_SetupAutostartView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/SmartView/+mobile/test_CheckSmartResultView.qml b/test/qml/SmartView/+mobile/test_CheckSmartResultView.qml index cc3a23d6f..31dc2bedc 100644 --- a/test/qml/SmartView/+mobile/test_CheckSmartResultView.qml +++ b/test/qml/SmartView/+mobile/test_CheckSmartResultView.qml @@ -1,34 +1,42 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ -import QtQuick 2.15 -import QtTest 1.15 -import Governikus.Type.SmartModel 1.0 +import QtQuick +import QtTest +import Governikus.Type TestCase { id: testCase - function createTestObject(result) { - return createTemporaryQmlObject("import \"qrc:/qml/Governikus/SmartView/+mobile\"; CheckSmartResultView { result: %1 }".arg(result), testCase); - } function test_load(data) { - let testObject = createTestObject(data.result); + const component = Qt.createComponent(importPrefix + "/Governikus/SmartView/CheckSmartResultView.qml"); + verify(component.status === Component.Ready, "Component loaded"); + const testObject = component.createObject(parent, { + result: data.result + }); verify(testObject, "Object loaded"); } function test_load_data() { - return [{ - "result": SmartModel.SMART_UPDATING_STATUS - }, { - "result": SmartModel.SMART_UNAVAILABLE - }, { - "result": SmartModel.SMART_UNUSABLE - }, { - "result": SmartModel.SMART_NO_PROVISIONING - }, { - "result": SmartModel.SMART_NO_PERSONALIZATION - }, { + return [ + { + "result": SmartModel.State.UPDATING_STATUS + }, + { + "result": SmartModel.State.UNAVAILABLE + }, + { + "result": SmartModel.State.UNUSABLE + }, + { + "result": SmartModel.State.NO_PROVISIONING + }, + { + "result": SmartModel.State.NO_PERSONALIZATION + }, + { "result": -1 - }]; + } + ]; } name: "test_CheckSmartResultView" diff --git a/test/qml/SmartView/+mobile/test_SmartView.qml b/test/qml/SmartView/+mobile/test_SmartView.qml index 620ec884a..8d42369b5 100644 --- a/test/qml/SmartView/+mobile/test_SmartView.qml +++ b/test/qml/SmartView/+mobile/test_SmartView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/TechnologyInfo/+mobile/test_TechnologyInfo.qml b/test/qml/TechnologyInfo/+mobile/test_TechnologyInfo.qml index 790da7e2b..38bfe786a 100644 --- a/test/qml/TechnologyInfo/+mobile/test_TechnologyInfo.qml +++ b/test/qml/TechnologyInfo/+mobile/test_TechnologyInfo.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/TitleBar/+desktop/test_TitleBarButton.qml b/test/qml/TitleBar/+desktop/test_TitleBarButton.qml index 30d8ce111..4bac29453 100644 --- a/test/qml/TitleBar/+desktop/test_TitleBarButton.qml +++ b/test/qml/TitleBar/+desktop/test_TitleBarButton.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/TitleBar/test_NavigationAction.qml b/test/qml/TitleBar/test_NavigationAction.qml index 414554ea9..38bb7a02f 100644 --- a/test/qml/TitleBar/test_NavigationAction.qml +++ b/test/qml/TitleBar/test_NavigationAction.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/TitleBar/test_TitleBar.qml b/test/qml/TitleBar/test_TitleBar.qml index 0caa180a1..9472caf34 100644 --- a/test/qml/TitleBar/test_TitleBar.qml +++ b/test/qml/TitleBar/test_TitleBar.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/TitleBar/test_TitlePane.qml b/test/qml/TitleBar/test_TitlePane.qml new file mode 100644 index 000000000..e1763bf2a --- /dev/null +++ b/test/qml/TitleBar/test_TitlePane.qml @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany + */ +import QtQuick +import QtTest + +TestCase { + id: testCase + + function test_load() { + const component = Qt.createComponent(importPrefix + "/Governikus/TitleBar/TitlePane.qml"); + verify(component.status === Component.Ready, "Component loaded"); + const testObject = component.createObject(parent, {}); + verify(testObject, "Object loaded"); + } +} diff --git a/test/qml/View/+desktop/test_SectionPage.qml b/test/qml/View/+desktop/test_SectionPage.qml index 917142025..eee1d8783 100644 --- a/test/qml/View/+desktop/test_SectionPage.qml +++ b/test/qml/View/+desktop/test_SectionPage.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/View/+mobile/test_ContentArea.qml b/test/qml/View/+mobile/test_ContentArea.qml index 287d14288..d5db7029a 100644 --- a/test/qml/View/+mobile/test_ContentArea.qml +++ b/test/qml/View/+mobile/test_ContentArea.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest @@ -11,6 +11,9 @@ TestCase { return createTemporaryQmlObject("import Governikus.View; ContentArea { width: 500 }", testCase); } function test_load() { + if (hasPolishLoop) { + skip("Skip test because of old Qt version with unfixed Polish Loops"); + } let testObject = createTestObject(); verify(testObject, "Object loaded"); } diff --git a/test/qml/View/+mobile/test_SectionPage.qml b/test/qml/View/+mobile/test_SectionPage.qml index e3808b8c3..e460b8555 100644 --- a/test/qml/View/+mobile/test_SectionPage.qml +++ b/test/qml/View/+mobile/test_SectionPage.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/View/+mobile/test_TabBarView.qml b/test/qml/View/+mobile/test_TabBarView.qml index 832c2f08a..eb382025c 100644 --- a/test/qml/View/+mobile/test_TabBarView.qml +++ b/test/qml/View/+mobile/test_TabBarView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/View/test_Controller.qml b/test/qml/View/test_Controller.qml index 0f26b0a9e..a03df1b2c 100644 --- a/test/qml/View/test_Controller.qml +++ b/test/qml/View/test_Controller.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/View/test_FocusFrame.qml b/test/qml/View/test_FocusFrame.qml index c25d48c76..5156893ca 100644 --- a/test/qml/View/test_FocusFrame.qml +++ b/test/qml/View/test_FocusFrame.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/View/test_FocusPoint.qml b/test/qml/View/test_FocusPoint.qml index 5e865bd28..80ae849d9 100644 --- a/test/qml/View/test_FocusPoint.qml +++ b/test/qml/View/test_FocusPoint.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/WhiteListClient/+mobile/test_WhiteListSurveyView.qml b/test/qml/WhiteListClient/+mobile/test_WhiteListSurveyView.qml index 1e4bf21b3..08a7c0efb 100644 --- a/test/qml/WhiteListClient/+mobile/test_WhiteListSurveyView.qml +++ b/test/qml/WhiteListClient/+mobile/test_WhiteListSurveyView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Workflow/+desktop/test_GeneralWorkflow.qml b/test/qml/Workflow/+desktop/test_GeneralWorkflow.qml index ccd87e2ec..8ee86fbda 100644 --- a/test/qml/Workflow/+desktop/test_GeneralWorkflow.qml +++ b/test/qml/Workflow/+desktop/test_GeneralWorkflow.qml @@ -1,10 +1,10 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest import Governikus.Global -import Governikus.Type.ReaderPlugIn +import Governikus.Type TestCase { id: testCase diff --git a/test/qml/Workflow/+mobile/test_GeneralWorkflow.qml b/test/qml/Workflow/+mobile/test_GeneralWorkflow.qml index ee50222d7..85660b950 100644 --- a/test/qml/Workflow/+mobile/test_GeneralWorkflow.qml +++ b/test/qml/Workflow/+mobile/test_GeneralWorkflow.qml @@ -1,10 +1,10 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest import Governikus.Global -import Governikus.Type.ReaderPlugIn +import Governikus.Type TestCase { id: testCase @@ -14,15 +14,15 @@ TestCase { import QtQuick import QtQuick.Controls import Governikus.Workflow - import Governikus.Type.ReaderPlugIn + import Governikus.Type ApplicationWindow { menuBar: Item {} GeneralWorkflow { workflowModel: Item { - property var readerPlugInType: ReaderPlugIn.NFC + property var readerPluginType: ReaderManagerPluginType.NFC property bool isCurrentSmartCardAllowed: false - property var supportedPlugInTypes: [ReaderPlugIn.NFC, ReaderPlugIn.REMOTE_IFD, ReaderPlugIn.SMART] + property var supportedPluginTypes: [ReaderManagerPluginType.NFC, ReaderManagerPluginType.REMOTE_IFD, ReaderManagerPluginType.SMART] } } } diff --git a/test/qml/Workflow/+mobile/test_NfcWorkflow.qml b/test/qml/Workflow/+mobile/test_NfcWorkflow.qml index f4c830a2a..5d6ab645d 100644 --- a/test/qml/Workflow/+mobile/test_NfcWorkflow.qml +++ b/test/qml/Workflow/+mobile/test_NfcWorkflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Workflow/+mobile/test_SmartWorkflow.qml b/test/qml/Workflow/+mobile/test_SmartWorkflow.qml index c831e92b2..5e04ff25f 100644 --- a/test/qml/Workflow/+mobile/test_SmartWorkflow.qml +++ b/test/qml/Workflow/+mobile/test_SmartWorkflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/Workflow/test_Workflow.qml b/test/qml/Workflow/test_Workflow.qml index 8203f7631..c0dc3e26b 100644 --- a/test/qml/Workflow/test_Workflow.qml +++ b/test/qml/Workflow/test_Workflow.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest diff --git a/test/qml/test_MainView.qml b/test/qml/test_MainView.qml index 7a585e39d..683f20765 100644 --- a/test/qml/test_MainView.qml +++ b/test/qml/test_MainView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/test_MoreView.qml b/test/qml/test_MoreView.qml index 8a52f44a2..07ff7d345 100644 --- a/test/qml/test_MoreView.qml +++ b/test/qml/test_MoreView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/test_SelfAuthenticationView.qml b/test/qml/test_SelfAuthenticationView.qml index 4c5ebbfa7..48226edf1 100644 --- a/test/qml/test_SelfAuthenticationView.qml +++ b/test/qml/test_SelfAuthenticationView.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/test_Style.qml b/test/qml/test_Style.qml index b4798a1a4..d619793f8 100644 --- a/test/qml/test_Style.qml +++ b/test/qml/test_Style.qml @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtTest diff --git a/test/qml/test_UiPluginQml.qml b/test/qml/test_UiPluginQml.qml index d41120e2d..b5177ce21 100644 --- a/test/qml/test_UiPluginQml.qml +++ b/test/qml/test_UiPluginQml.qml @@ -1,10 +1,9 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ import QtQuick import QtTest -import Governikus.Type.UiModule -import Governikus.Type.SettingsModel +import Governikus.Type TestCase { id: testCase @@ -12,7 +11,7 @@ TestCase { function createTestObject() { return createTemporaryQmlObject(" import QtQuick - import Governikus.Type.UiModule + import Governikus.Type Item { readonly property int v1: UiModule.CURRENT readonly property int v2: UiModule.DEFAULT diff --git a/test/qt/card/base/apdu/test_CommandData.cpp b/test/qt/card/asn1/test_ASN1Struct.cpp similarity index 63% rename from test/qt/card/base/apdu/test_CommandData.cpp rename to test/qt/card/asn1/test_ASN1Struct.cpp index e485bcca7..1f5256af8 100644 --- a/test/qt/card/base/apdu/test_CommandData.cpp +++ b/test/qt/card/asn1/test_ASN1Struct.cpp @@ -1,15 +1,20 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ -#include "apdu/CommandData.h" +#include "asn1/ASN1Struct.h" + +#include "TestFileHelper.h" #include #include + +using namespace Qt::Literals::StringLiterals; using namespace governikus; -class test_CommandData + +class test_ASN1Struct : public QObject { Q_OBJECT @@ -64,7 +69,7 @@ class test_CommandData QFETCH(int, objectCount); QFETCH(QByteArray, data); - const CommandData cmd(data); + const ASN1Struct cmd(data); QCOMPARE(cmd.getObjectCount(), objectCount); QCOMPARE(QByteArray(cmd), data); } @@ -91,80 +96,80 @@ class test_CommandData QFETCH(int, number); QFETCH(QByteArray, data); - CommandData cmd; - cmd.append(CommandData::PRIVATE_KEY_REFERENCE, number); + ASN1Struct cmd; + cmd.append(ASN1Struct::PRIVATE_KEY_REFERENCE, number); QCOMPARE(cmd, data); } void setOid() { - CommandData data; + ASN1Struct data; Oid oid(KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128); - data.append(CommandData::CRYPTOGRAPHIC_MECHANISM_REFERENCE, oid); - QCOMPARE(data, QByteArray::fromHex("800A").append(oid.getData())); + data.append(ASN1Struct::CRYPTOGRAPHIC_MECHANISM_REFERENCE, oid); + QCOMPARE(data, QByteArray::fromHex("800A").append(QByteArray(oid))); } void setPublicKey() { - CommandData data; + ASN1Struct data; QByteArray publicKey = QByteArray::fromHex("A9D9E9F9493954939495"); - data.append(CommandData::PACE_EPHEMERAL_PUBLIC_KEY, publicKey); + data.append(ASN1Struct::PACE_EPHEMERAL_PUBLIC_KEY, publicKey); QCOMPARE(data, QByteArray::fromHex("830A").append(publicKey)); } void setPublicKeyId() { - CommandData data; + ASN1Struct data; PacePasswordId pinId = PacePasswordId::PACE_PIN; - data.append(CommandData::PUBLIC_KEY_REFERENCE, pinId); + data.append(ASN1Struct::PUBLIC_KEY_REFERENCE, pinId); QCOMPARE(data, QByteArray::fromHex("8301").append(static_cast(pinId))); } void setPaceMappingData() { - CommandData data; + ASN1Struct data; QByteArray mapping = QByteArray::fromHex("A9D9E9F949395493999994"); - data.append(CommandData::MAPPING_DATA, mapping); + data.append(ASN1Struct::MAPPING_DATA, mapping); QCOMPARE(data, QByteArray::fromHex("810B").append(mapping)); } void setPaceAuthenticationToken() { - CommandData data; + ASN1Struct data; QByteArray token = QByteArray::fromHex("A9D9E9F949395493999994"); - data.append(CommandData::AUTHENTICATION_TOKEN, token); + data.append(ASN1Struct::AUTHENTICATION_TOKEN, token); QCOMPARE(data, QByteArray::fromHex("850B").append(token)); } void setPaceEphemeralPublicKey() { - CommandData data; + ASN1Struct data; QByteArray publicKey = QByteArray::fromHex("A9D9E9F949395493999994"); - data.append(CommandData::PACE_EPHEMERAL_PUBLIC_KEY, publicKey); + data.append(ASN1Struct::PACE_EPHEMERAL_PUBLIC_KEY, publicKey); QCOMPARE(data, QByteArray::fromHex("830B").append(publicKey)); } void setCaEphemeralPublicKey() { - CommandData data; + ASN1Struct data; QByteArray publicKey = QByteArray::fromHex("A9D9E9F949395493999994"); - data.append(CommandData::CA_EPHEMERAL_PUBLIC_KEY, publicKey); + data.append(ASN1Struct::CA_EPHEMERAL_PUBLIC_KEY, publicKey); QCOMPARE(data, QByteArray::fromHex("800B").append(publicKey)); } void setTaEphemeralPublicKey() { - CommandData data; + ASN1Struct data; QByteArray publicKey = QByteArray::fromHex("A9D9E9F949395493999994"); - data.append(CommandData::TA_EPHEMERAL_PUBLIC_KEY, publicKey); + data.append(ASN1Struct::TA_EPHEMERAL_PUBLIC_KEY, publicKey); QCOMPARE(data, QByteArray::fromHex("910B").append(publicKey)); } @@ -224,57 +229,92 @@ class test_CommandData QFETCH(QByteArray, data); QFETCH(QByteArray, object); - const CommandData cmd(asn1); - QCOMPARE(cmd.getData(V_ASN1_CONTEXT_SPECIFIC, CommandData::MAPPING_DATA), data); - QCOMPARE(cmd.getObject(V_ASN1_CONTEXT_SPECIFIC, CommandData::MAPPING_DATA), object); + const ASN1Struct cmd(asn1); + QCOMPARE(cmd.getData(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::MAPPING_DATA), data); + QCOMPARE(cmd.getObject(V_ASN1_CONTEXT_SPECIFIC, ASN1Struct::MAPPING_DATA), object); } void setCertificateSignature() { - CommandData data; + ASN1Struct data; QByteArray signature = QByteArray::fromHex("5f37050102030405"); data.append(signature); QCOMPARE(data, signature); - QCOMPARE(data.getData(V_ASN1_APPLICATION, CommandData::CERTIFICATE_SIGNATURE), signature.mid(3)); - QCOMPARE(data.getObject(V_ASN1_APPLICATION, CommandData::CERTIFICATE_SIGNATURE), signature); + QCOMPARE(data.getData(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_SIGNATURE), signature.mid(3)); + QCOMPARE(data.getObject(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_SIGNATURE), signature); } void setAuxiliaryData() { - CommandData data; + ASN1Struct data; QByteArray auxData = QByteArray::fromHex("6703800101"); data.append(auxData); QCOMPARE(data, auxData); - QCOMPARE(data.getData(V_ASN1_APPLICATION, CommandData::AUXILIARY_AUTHENTICATED_DATA), QByteArray()); - QCOMPARE(data.getObject(V_ASN1_APPLICATION, CommandData::AUXILIARY_AUTHENTICATED_DATA), auxData); + QCOMPARE(data.getData(V_ASN1_APPLICATION, ASN1Struct::AUXILIARY_AUTHENTICATED_DATA), QByteArray()); + QCOMPARE(data.getObject(V_ASN1_APPLICATION, ASN1Struct::AUXILIARY_AUTHENTICATED_DATA), auxData); } void setChat() { - CommandData data; + ASN1Struct data; QByteArray chat = QByteArray::fromHex("7f4C03800101"); data.append(chat); QCOMPARE(data, chat); - QCOMPARE(data.getData(V_ASN1_APPLICATION, CommandData::CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE), QByteArray()); - QCOMPARE(data.getObject(V_ASN1_APPLICATION, CommandData::CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE), chat); + QCOMPARE(data.getData(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE), QByteArray()); + QCOMPARE(data.getObject(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE), chat); } void setCertificateBody() { - CommandData data; + ASN1Struct data; QByteArray body = QByteArray::fromHex("7f4e03800101"); data.append(body); QCOMPARE(data, body); - QCOMPARE(data.getData(V_ASN1_APPLICATION, CommandData::CERTIFICATE_BODY), QByteArray()); - QCOMPARE(data.getObject(V_ASN1_APPLICATION, CommandData::CERTIFICATE_BODY), body); + QCOMPARE(data.getData(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_BODY), QByteArray()); + QCOMPARE(data.getObject(V_ASN1_APPLICATION, ASN1Struct::CERTIFICATE_BODY), body); + } + + + void debugOperator() + { + QTest::ignoreMessage(QtDebugMsg, R"(ASN1Struct: +[APPLICATION 33] + [APPLICATION 78] + [APPLICATION 41] 00 + [APPLICATION 2] 4445445674494447564b333030303239 + [APPLICATION 73] + [UNIVERSAL 6] 04007f00070202020203 + [CONTEXT_SPECIFIC 6] 04327560563d276d3f5e190196e264d0d391ac134aeb27e07250fa562096b14a8a169a298dc80285cb6e3133e0ffccde7964747d754dd356b4401df2cca7d43dc9 + [APPLICATION 32] 44454250524c4f43414c333030303337 + [APPLICATION 76] + [UNIVERSAL 6] 04007f000703010202 + [APPLICATION 19] 000713ff07 + [APPLICATION 37] 020400020001 + [APPLICATION 36] 020400030002 + [APPLICATION 5] + [APPLICATION 19] + [UNIVERSAL 6] 04007f000703010301 + [CONTEXT_SPECIFIC 0] 315a1da468ae12c839f8ab386e5cab88c9ffac2033c9910e202e2004bde07fe6 + [APPLICATION 19] + [UNIVERSAL 6] 04007f000703010302 + [CONTEXT_SPECIFIC 0] 39d51f1942520ae8ec7f5cc654e78a521d8c09f607cd9adf7bb9fdc5bffb90d7 + [APPLICATION 19] + [UNIVERSAL 6] 04007f000703010303 + [CONTEXT_SPECIFIC 0] + [CONTEXT_SPECIFIC 0] 0d + [CONTEXT_SPECIFIC 1] 5f2513575dd25b7c4b60d2aa66f489f26055dd90d4b6f5997e4e6ee75a89473a + [APPLICATION 55] 6ae52f47b70da13b1114db0879d504aef804f8c353ffff253c65254897c3bf000f2bcc37a6550b921e9554185f6fa2e3d14658541b467fb480338faad2422e67)"); + + const auto& rawCert = TestFileHelper::readFile(":/card/cvdv-DEDVtIDGVK300029.hex"_L1); + qDebug() << ASN1Struct(QByteArray::fromHex(rawCert)); } }; -QTEST_GUILESS_MAIN(test_CommandData) -#include "test_CommandData.moc" +QTEST_GUILESS_MAIN(test_ASN1Struct) +#include "test_ASN1Struct.moc" diff --git a/test/qt/card/asn1/test_AccessRoleAndRight.cpp b/test/qt/card/asn1/test_AccessRoleAndRight.cpp index b5ee1b428..5005c66c3 100644 --- a/test/qt/card/asn1/test_AccessRoleAndRight.cpp +++ b/test/qt/card/asn1/test_AccessRoleAndRight.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_AccessRoleAndRight @@ -52,8 +53,9 @@ class test_AccessRoleAndRight { fillTestData(); QTest::newRow("") << AccessRight::WRITE_DG21; - QTest::newRow("") << AccessRight::RFU_32; + QTest::newRow("") << AccessRight::WRITE_DG22; QTest::newRow("") << AccessRight::PRIVILEGED_TERMINAL; + QTest::newRow("") << AccessRight::PSA; } @@ -99,44 +101,44 @@ class test_AccessRoleAndRight right = pRight; }; - QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName(QString("crap"), func)); + QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName("crap"_L1, func)); QCOMPARE(right, undefined); - QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName(QString("CAN_ALLOWED"), func)); + QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName("CAN_ALLOWED"_L1, func)); QCOMPARE(right, undefined); - QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName(QString("familyname"), func)); + QVERIFY(!AccessRoleAndRightsUtil::fromTechnicalName("familyname"_L1, func)); QCOMPARE(right, undefined); } void checkJoinFromTechnicalName() { - auto data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType", "DoctoralDegree"}); + auto data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType"_L1, "DoctoralDegree"_L1}); QCOMPARE(data, QStringLiteral("Document type, Doctoral degree")); // previous versions stored translated display names instead of technical names, so be compatible here. - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte", "FamilyName"}); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte"_L1, "FamilyName"_L1}); QCOMPARE(data, QStringLiteral("Alte Rechte, Family name")); // do not add "Alte Rechte" for WRITE only rights as previous version had no WRITE. - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte", "FamilyName"}, AccessRoleAndRightsUtil::WRITE); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte"_L1, "FamilyName"_L1}, AccessRoleAndRightsUtil::WRITE); QCOMPARE(data, QString()); - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte", "WriteCommunityID"}, AccessRoleAndRightsUtil::WRITE); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"Alte Rechte"_L1, "WriteCommunityID"_L1}, AccessRoleAndRightsUtil::WRITE); QCOMPARE(data, QStringLiteral("Community-ID")); const auto right = AccessRoleAndRightsUtil::JoinRights(AccessRoleAndRightsUtil::READ | AccessRoleAndRightsUtil::WRITE); - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType", "WriteAddress"}, right); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType"_L1, "WriteAddress"_L1}, right); QCOMPARE(data, QStringLiteral("Document type, Address")); - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType", "WriteAddress"}, AccessRoleAndRightsUtil::READWRITE); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType"_L1, "WriteAddress"_L1}, AccessRoleAndRightsUtil::READWRITE); QCOMPARE(data, QStringLiteral("Document type, Address")); - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType", "WriteAddress"}, AccessRoleAndRightsUtil::WRITE); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType"_L1, "WriteAddress"_L1}, AccessRoleAndRightsUtil::WRITE); QCOMPARE(data, QStringLiteral("Address")); - data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType", "WriteAddress"}, AccessRoleAndRightsUtil::READ); + data = AccessRoleAndRightsUtil::joinFromTechnicalName({"DocumentType"_L1, "WriteAddress"_L1}, AccessRoleAndRightsUtil::READ); QCOMPARE(data, QStringLiteral("Document type")); } @@ -164,57 +166,56 @@ class test_AccessRoleAndRight void test_ToDisplayText_data() { QTest::addColumn("input"); - QTest::addColumn("output"); - - const auto& reserved = QStringLiteral("Unknown (reserved)"); - QTest::newRow("RFU_29") << AccessRight::RFU_29 << reserved; - QTest::newRow("RFU_30") << AccessRight::RFU_30 << reserved; - QTest::newRow("RFU_31") << AccessRight::RFU_31 << reserved; - QTest::newRow("RFU_32") << AccessRight::RFU_32 << reserved; - - QTest::newRow("writeDG17") << AccessRight::WRITE_DG17 << QString("Address"); - QTest::newRow("writeDG18") << AccessRight::WRITE_DG18 << QString("Community-ID"); - QTest::newRow("writeDG19") << AccessRight::WRITE_DG19 << QString("Residence permit I"); - QTest::newRow("writeDG20") << AccessRight::WRITE_DG20 << QString("Residence permit II"); - QTest::newRow("writeDG21") << AccessRight::WRITE_DG21 << QString("Optional data"); - QTest::newRow("readDG21") << AccessRight::READ_DG21 << QString("Optional data"); - QTest::newRow("readDG20") << AccessRight::READ_DG20 << QString("Residence permit II"); - QTest::newRow("readDG19") << AccessRight::READ_DG19 << QString("Residence permit I"); - QTest::newRow("readDG18") << AccessRight::READ_DG18 << QString("Community-ID"); - QTest::newRow("readDG17") << AccessRight::READ_DG17 << QString("Address"); - QTest::newRow("readDG16") << AccessRight::READ_DG16 << QString("RFU"); - QTest::newRow("readDG15") << AccessRight::READ_DG15 << QString("RFU"); - QTest::newRow("readDG14") << AccessRight::READ_DG14 << QString("RFU"); - QTest::newRow("readDG13") << AccessRight::READ_DG13 << QString("Birth name"); - QTest::newRow("readDG12") << AccessRight::READ_DG12 << QString("Optional data"); - QTest::newRow("readDG11") << AccessRight::READ_DG11 << QString("Gender"); - QTest::newRow("readDG10") << AccessRight::READ_DG10 << QString("Nationality"); - QTest::newRow("readDG09") << AccessRight::READ_DG09 << QString("Place of birth"); - QTest::newRow("readDG08") << AccessRight::READ_DG08 << QString("Date of birth"); - QTest::newRow("readDG07") << AccessRight::READ_DG07 << QString("Doctoral degree"); - QTest::newRow("readDG06") << AccessRight::READ_DG06 << QString("Religious / artistic name"); - QTest::newRow("readDG05") << AccessRight::READ_DG05 << QString("Family name"); - QTest::newRow("readDG04") << AccessRight::READ_DG04 << QString("Given name(s)"); - QTest::newRow("readDG03") << AccessRight::READ_DG03 << QString("Valid until"); - QTest::newRow("readDG02") << AccessRight::READ_DG02 << QString("Issuing country"); - QTest::newRow("readDG01") << AccessRight::READ_DG01 << QString("Document type"); - QTest::newRow("installQualCert") << AccessRight::INSTALL_QUAL_CERT << QString("Installation of qualified signature certificates"); - QTest::newRow("installCert") << AccessRight::INSTALL_CERT << QString("Installation of signature certificates"); - QTest::newRow("pinManagement") << AccessRight::PIN_MANAGEMENT << QString("PIN Management"); - QTest::newRow("canAllowed") << AccessRight::CAN_ALLOWED << QString("CAN allowed"); - QTest::newRow("privilegedTerminal") << AccessRight::PRIVILEGED_TERMINAL << QString("Privileged terminal"); - QTest::newRow("restrictedIdentification") << AccessRight::RESTRICTED_IDENTIFICATION << QString("Pseudonym"); - QTest::newRow("comunityIdVerification") << AccessRight::COMMUNITY_ID_VERIFICATION << QString("Address verification"); - QTest::newRow("ageVerification") << AccessRight::AGE_VERIFICATION << QString("Age verification"); - - QTest::newRow("default") << static_cast(100) << QString("Unknown"); + QTest::addColumn("output"); + + QTest::newRow("RFU") << AccessRight::RFU << "Unknown (reserved)"_L1; + + QTest::newRow("writeDG17") << AccessRight::WRITE_DG17 << "Address"_L1; + QTest::newRow("writeDG18") << AccessRight::WRITE_DG18 << "Community-ID"_L1; + QTest::newRow("writeDG19") << AccessRight::WRITE_DG19 << "Residence permit I"_L1; + QTest::newRow("writeDG20") << AccessRight::WRITE_DG20 << "Residence permit II"_L1; + QTest::newRow("writeDG21") << AccessRight::WRITE_DG21 << "Optional data"_L1; + QTest::newRow("writeDG22") << AccessRight::WRITE_DG22 << "Optional data"_L1; + QTest::newRow("readDG22") << AccessRight::READ_DG22 << "Optional data"_L1; + QTest::newRow("readDG21") << AccessRight::READ_DG21 << "Optional data"_L1; + QTest::newRow("readDG20") << AccessRight::READ_DG20 << "Residence permit II"_L1; + QTest::newRow("readDG19") << AccessRight::READ_DG19 << "Residence permit I"_L1; + QTest::newRow("readDG18") << AccessRight::READ_DG18 << "Community-ID"_L1; + QTest::newRow("readDG17") << AccessRight::READ_DG17 << "Address"_L1; + QTest::newRow("readDG16") << AccessRight::READ_DG16 << "RFU"_L1; + QTest::newRow("readDG15") << AccessRight::READ_DG15 << "RFU"_L1; + QTest::newRow("readDG14") << AccessRight::READ_DG14 << "RFU"_L1; + QTest::newRow("readDG13") << AccessRight::READ_DG13 << "Birth name"_L1; + QTest::newRow("readDG12") << AccessRight::READ_DG12 << "Optional data"_L1; + QTest::newRow("readDG11") << AccessRight::READ_DG11 << "Gender"_L1; + QTest::newRow("readDG10") << AccessRight::READ_DG10 << "Nationality"_L1; + QTest::newRow("readDG09") << AccessRight::READ_DG09 << "Place of birth"_L1; + QTest::newRow("readDG08") << AccessRight::READ_DG08 << "Date of birth"_L1; + QTest::newRow("readDG07") << AccessRight::READ_DG07 << "Doctoral degree"_L1; + QTest::newRow("readDG06") << AccessRight::READ_DG06 << "Religious / artistic name"_L1; + QTest::newRow("readDG05") << AccessRight::READ_DG05 << "Family name"_L1; + QTest::newRow("readDG04") << AccessRight::READ_DG04 << "Given name(s)"_L1; + QTest::newRow("readDG03") << AccessRight::READ_DG03 << "Valid until"_L1; + QTest::newRow("readDG02") << AccessRight::READ_DG02 << "Issuing country"_L1; + QTest::newRow("readDG01") << AccessRight::READ_DG01 << "Document type"_L1; + QTest::newRow("installQualCert") << AccessRight::INSTALL_QUAL_CERT << "Installation of qualified signature certificates"_L1; + QTest::newRow("installCert") << AccessRight::INSTALL_CERT << "Installation of signature certificates"_L1; + QTest::newRow("pinManagement") << AccessRight::PIN_MANAGEMENT << "PIN Management"_L1; + QTest::newRow("canAllowed") << AccessRight::CAN_ALLOWED << "CAN allowed"_L1; + QTest::newRow("privilegedTerminal") << AccessRight::PRIVILEGED_TERMINAL << "Privileged terminal"_L1; + QTest::newRow("pseudonymousSignatureAuthentication") << AccessRight::PSA << "Pseudonym"_L1; + QTest::newRow("restrictedIdentification") << AccessRight::RESTRICTED_IDENTIFICATION << "Pseudonym"_L1; + QTest::newRow("comunityIdVerification") << AccessRight::COMMUNITY_ID_VERIFICATION << "Address verification"_L1; + QTest::newRow("ageVerification") << AccessRight::AGE_VERIFICATION << "Age verification"_L1; + + QTest::newRow("default") << static_cast(100) << "Unknown"_L1; } void test_ToDisplayText() { QFETCH(AccessRight, input); - QFETCH(QString, output); + QFETCH(QLatin1String, output); QCOMPARE(AccessRoleAndRightsUtil::toDisplayText(input), output); } diff --git a/test/qt/card/asn1/test_ApplicationTemplate.cpp b/test/qt/card/asn1/test_ApplicationTemplate.cpp index d0465e33a..ce69c5155 100644 --- a/test/qt/card/asn1/test_ApplicationTemplate.cpp +++ b/test/qt/card/asn1/test_ApplicationTemplate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_ApplicationTemplates.cpp b/test/qt/card/asn1/test_ApplicationTemplates.cpp index 0a2ef65ed..8e65ea987 100644 --- a/test/qt/card/asn1/test_ApplicationTemplates.cpp +++ b/test/qt/card/asn1/test_ApplicationTemplates.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_Asn1BCDDateUtil.cpp b/test/qt/card/asn1/test_Asn1BCDDateUtil.cpp index 05326369b..43c457b32 100644 --- a/test/qt/card/asn1/test_Asn1BCDDateUtil.cpp +++ b/test/qt/card/asn1/test_Asn1BCDDateUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_Asn1IntegerUtil.cpp b/test/qt/card/asn1/test_Asn1IntegerUtil.cpp index 8e1edc731..dc3574d40 100644 --- a/test/qt/card/asn1/test_Asn1IntegerUtil.cpp +++ b/test/qt/card/asn1/test_Asn1IntegerUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_Asn1OctetStringUtil.cpp b/test/qt/card/asn1/test_Asn1OctetStringUtil.cpp index 95f7c7438..9be537589 100644 --- a/test/qt/card/asn1/test_Asn1OctetStringUtil.cpp +++ b/test/qt/card/asn1/test_Asn1OctetStringUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_Asn1StringUtil.cpp b/test/qt/card/asn1/test_Asn1StringUtil.cpp index 6af8ba5e5..b3734d678 100644 --- a/test/qt/card/asn1/test_Asn1StringUtil.cpp +++ b/test/qt/card/asn1/test_Asn1StringUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -27,7 +28,7 @@ class test_Asn1StringUtil { ASN1_UTF8STRING* asn1String = ASN1_UTF8STRING_new(); - Asn1StringUtil::setValue(QString("abc"), asn1String); + Asn1StringUtil::setValue("abc"_L1, asn1String); QCOMPARE(asn1String->length, 3); QCOMPARE(asn1String->data[0], static_cast('a')); QCOMPARE(asn1String->data[1], static_cast('b')); @@ -45,7 +46,7 @@ class test_Asn1StringUtil void getValue() { - QString utf8Text("Dieß öst äin UTF8-Đext ɃϢݢૂૂૂ"); + const QString utf8Text(u"Dieß öst äin UTF8-Đext ɃϢݢૂૂૂ"_s); ASN1_UTF8STRING* asn1String = ASN1_UTF8STRING_new(); ASN1_STRING_set(asn1String, utf8Text.toUtf8().data(), static_cast(utf8Text.toUtf8().length())); diff --git a/test/qt/card/asn1/test_Asn1TypeUtil.cpp b/test/qt/card/asn1/test_Asn1TypeUtil.cpp index 0b315667e..6cd6f183a 100644 --- a/test/qt/card/asn1/test_Asn1TypeUtil.cpp +++ b/test/qt/card/asn1/test_Asn1TypeUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_Asn1Util.cpp b/test/qt/card/asn1/test_Asn1Util.cpp index a4e79dd43..6bfc9099e 100644 --- a/test/qt/card/asn1/test_Asn1Util.cpp +++ b/test/qt/card/asn1/test_Asn1Util.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include "asn1/ASN1Util.h" diff --git a/test/qt/card/asn1/test_AuxiliaryAuthenticatedData.cpp b/test/qt/card/asn1/test_AuxiliaryAuthenticatedData.cpp index 5c59ab4ab..4b1a2daef 100644 --- a/test/qt/card/asn1/test_AuxiliaryAuthenticatedData.cpp +++ b/test/qt/card/asn1/test_AuxiliaryAuthenticatedData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -57,7 +58,7 @@ class test_AuxiliaryAuthenticatedData QVERIFY(auxData != nullptr); QVERIFY(auxData->hasAgeVerificationDate()); - QCOMPARE(auxData->getAgeVerificationDate(), QDate::fromString("1978-08-16", Qt::DateFormat::ISODate)); + QCOMPARE(auxData->getAgeVerificationDate(), QDate::fromString("1978-08-16"_L1, Qt::DateFormat::ISODate)); } @@ -162,7 +163,7 @@ class test_AuxiliaryAuthenticatedData QVERIFY(auxData != nullptr); QVERIFY(auxData->hasValidityDate()); - QCOMPARE(auxData->getValidityDate(), QDate::fromString("2015-06-30", Qt::DateFormat::ISODate)); + QCOMPARE(auxData->getValidityDate(), QDate::fromString("2015-06-30"_L1, Qt::DateFormat::ISODate)); } diff --git a/test/qt/card/asn1/test_CVCertificate.cpp b/test/qt/card/asn1/test_CVCertificate.cpp index 879bc491f..00567243e 100644 --- a/test/qt/card/asn1/test_CVCertificate.cpp +++ b/test/qt/card/asn1/test_CVCertificate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,13 +8,16 @@ #include "asn1/CVCertificate.h" -#include "TestFileHelper.h" #include "asn1/ASN1Util.h" +#include "CertificateHelper.h" +#include "TestFileHelper.h" + #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -30,7 +33,7 @@ class test_CVCertificate return QByteArray(); } int bufLen = BN_num_bytes(pBigNum); - QVector buf(bufLen); + QList buf(bufLen); BN_bn2bin(pBigNum, buf.data()); return QByteArray(reinterpret_cast(buf.data()), bufLen); } @@ -39,8 +42,8 @@ class test_CVCertificate void getRawBody() { QByteArray body("7f4e82016e5f290100420e44454356434165494430303130337f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641048925419fc7f194922cfc6b8dd25ae6a19c1b59216e6cf06270e5d75cfd64205f55cf867bbfefeefd6e680e1fd197f18ab684484901362568efc9adb5c6018d728701015f200e44454356434165494430303130337f4c12060904007f0007030102025305fc0f13ffff5f25060102010200035f2406010501020003"); - QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"); - auto cvc = CVCertificate::fromHex(source); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"_L1); + auto cvc = CertificateHelper::fromHex(source); QCOMPARE(cvc->getRawBody(), QByteArray::fromHex(body)); } @@ -49,8 +52,8 @@ class test_CVCertificate void getRawSignature() { QByteArray signature("5f37406018cff8ee22ae417a63446a5fbf53ac39dd1ee331af4b62569604966f7575359b0c536673dcb98f9ae62c5f9724e0236bef6dc485ffa331be5e82de4410e2e8"); - QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"); - auto cvc = CVCertificate::fromHex(source); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"_L1); + auto cvc = CertificateHelper::fromHex(source); QCOMPARE(cvc->getRawSignature(), QByteArray::fromHex(signature)); } @@ -58,8 +61,8 @@ class test_CVCertificate void toHex() { - QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"); - auto cvc = CVCertificate::fromHex(source); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"_L1); + auto cvc = CertificateHelper::fromHex(source); QCOMPARE(cvc->encode().toHex(), source); } @@ -73,7 +76,7 @@ class test_CVCertificate ) { QByteArray bytes = TestFileHelper::readFile(QStringLiteral(":/card/") + QLatin1String(name)); - auto cvc = CVCertificate::fromHex(bytes); + auto cvc = CertificateHelper::fromHex(bytes); QVERIFY(cvc); } } @@ -81,34 +84,34 @@ class test_CVCertificate void testIsValidOn() { - QByteArray source = TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"); - auto cvc = CVCertificate::fromHex(source); - - QVERIFY(!cvc->isValidOn(QDateTime(QDate(2010, 8, 12), QTime(22, 59, 59, 999), Qt::OffsetFromUTC, -60 * 60 * 1))); - QVERIFY(cvc->isValidOn(QDateTime(QDate(2010, 8, 13), QTime(23, 0, 0, 0), Qt::OffsetFromUTC, -60 * 60 * 1)) /*lower bound*/); - QVERIFY(cvc->isValidOn(QDateTime(QDate(2012, 8, 13), QTime(23, 0, 0, 0), Qt::OffsetFromUTC, -60 * 60 * 1)) /*lower bound*/); - QVERIFY(cvc->isValidOn(QDateTime(QDate(2013, 8, 14), QTime(2, 59, 59, 999), Qt::OffsetFromUTC, +60 * 60 * 3)) /*upper bound*/); - QVERIFY(!cvc->isValidOn(QDateTime(QDate(2013, 8, 14), QTime(3, 0, 0, 0), Qt::OffsetFromUTC, +60 * 60 * 3))); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1); + auto cvc = CertificateHelper::fromHex(source); + + QVERIFY(!cvc->isValidOn(QDateTime(QDate(2010, 8, 12), QTime(22, 59, 59, 999), QTimeZone(-60 * 60 * 1)))); + QVERIFY(cvc->isValidOn(QDateTime(QDate(2010, 8, 13), QTime(23, 0, 0, 0), QTimeZone(-60 * 60 * 1))) /*lower bound*/); + QVERIFY(cvc->isValidOn(QDateTime(QDate(2012, 8, 13), QTime(23, 0, 0, 0), QTimeZone(-60 * 60 * 1))) /*lower bound*/); + QVERIFY(cvc->isValidOn(QDateTime(QDate(2013, 8, 14), QTime(2, 59, 59, 999), QTimeZone(+60 * 60 * 3))) /*upper bound*/); + QVERIFY(!cvc->isValidOn(QDateTime(QDate(2013, 8, 14), QTime(3, 0, 0, 0), QTimeZone(+60 * 60 * 3)))); } void testParseCrap() { - QVERIFY(CVCertificate::fromHex(QByteArray("01020304060708")) == nullptr); + QVERIFY(CertificateHelper::fromHex(QByteArray("01020304060708")) == nullptr); } void testSuccess() { - QByteArray source = TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"); - QVERIFY(CVCertificate::fromHex(source) != nullptr); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1); + QVERIFY(CertificateHelper::fromHex(source) != nullptr); } void testIsIssuedBy() { - auto cvca1 = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); - auto cvcaLink2_1 = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex")); + auto cvca1 = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); + auto cvcaLink2_1 = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex"_L1)); QVERIFY(cvca1->isIssuedBy(*cvca1)); QVERIFY(cvcaLink2_1->isIssuedBy(*cvca1)); @@ -118,7 +121,7 @@ class test_CVCertificate void getEcdsaSignature() { - auto cvca1 = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); + auto cvca1 = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); auto ecdsaSignature = cvca1->getEcdsaSignature(); const BIGNUM* r = nullptr; @@ -136,7 +139,7 @@ class test_CVCertificate const QRegularExpression output(QRegularExpression::escape(regex)); QTest::ignoreMessage(QtDebugMsg, output); - QSharedPointer cvca = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); + QSharedPointer cvca = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); qDebug() << cvca; QTest::ignoreMessage(QtDebugMsg, output); @@ -144,19 +147,19 @@ class test_CVCertificate qDebug() << cvcsNonConst; QTest::ignoreMessage(QtDebugMsg, output); - QVector> cvcsVector = {qSharedPointerConstCast(cvca)}; + QList> cvcsVector = {qSharedPointerConstCast(cvca)}; qDebug() << cvcsVector; QTest::ignoreMessage(QtDebugMsg, output); - QVector> cvcsVectorConst({cvca}); + QList> cvcsVectorConst({cvca}); qDebug() << cvcsVectorConst; } void equals() { - QSharedPointer cvca1_const = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); - QSharedPointer cvca2_const = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); + QSharedPointer cvca1_const = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); + QSharedPointer cvca2_const = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); QSharedPointer cvca1 = qSharedPointerConstCast(cvca1_const); QSharedPointer cvca2 = qSharedPointerConstCast(cvca2_const); @@ -171,8 +174,8 @@ class test_CVCertificate void notEquals() { - QSharedPointer cvca1_const = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); - QSharedPointer cvca2_const = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002.hex")); + QSharedPointer cvca1_const = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); + QSharedPointer cvca2_const = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002.hex"_L1)); QSharedPointer cvca1 = qSharedPointerConstCast(cvca1_const); QSharedPointer cvca2 = qSharedPointerConstCast(cvca2_const); diff --git a/test/qt/card/asn1/test_CVCertificateBody.cpp b/test/qt/card/asn1/test_CVCertificateBody.cpp index cdd22f94d..9655785c0 100644 --- a/test/qt/card/asn1/test_CVCertificateBody.cpp +++ b/test/qt/card/asn1/test_CVCertificateBody.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,10 +12,12 @@ #include "asn1/CVCertificate.h" #include "asn1/Oid.h" +#include "CertificateHelper.h" #include "TestFileHelper.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_CVCertificateBody @@ -32,33 +34,47 @@ class test_CVCertificateBody body->encode(); - QCOMPARE(body->getCertificateExpirationDate().toString("yyMMdd"), QString("030429")); - QCOMPARE(body->getCertificateEffectiveDate().toString("yyMMdd"), QString("150102")); + QCOMPARE(body->getCertificateExpirationDate().toString("yyMMdd"_L1), "030429"_L1); + QCOMPARE(body->getCertificateEffectiveDate().toString("yyMMdd"_L1), "150102"_L1); } - void getExtensions_noExtensions() + void getExtensions() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex")); - QVERIFY(cvc->getBody().getExtensions().isEmpty()); + const auto& rawCert = TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1); + auto cvc = CertificateHelper::fromHex(rawCert); + + QByteArray expectedDescription = QByteArray::fromHex("12CA9D0A51DF9297EABA7EBE9AB49DF2F4CF83E0DBB02772EFAD89C8AD75FCCD"); + QCOMPARE(cvc->getBody().getExtension(KnownOid::ID_DESCRIPTION), expectedDescription); + + QByteArray expectedSector = QByteArray::fromHex("CB1E1940159F11DC96845B87C23B86F9BAA755A789A914BBD5B8FA9784019D1C"); + QCOMPARE(cvc->getBody().getExtension(KnownOid::ID_SECTOR_RI), expectedSector); + + QVERIFY(rawCert.contains(cvc->getRawBody().toHex())); } - void getExtensions() + void testExtendedExtensions() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); - QCOMPARE(cvc->getBody().getExtensions().size(), 2); + const auto& rawCert = TestFileHelper::readFile(":/card/cvdv-DEDVtIDGVK300029.hex"_L1); + auto cvc = CertificateHelper::fromHex(rawCert); - QByteArray expectedDescription = QByteArray::fromHex("12CA9D0A51DF9297EABA7EBE9AB49DF2F4CF83E0DBB02772EFAD89C8AD75FCCD"); - QByteArray expectedSector = QByteArray::fromHex("CB1E1940159F11DC96845B87C23B86F9BAA755A789A914BBD5B8FA9784019D1C"); - QCOMPARE(cvc->getBody().getExtensions().value(KnownOid::ID_DESCRIPTION), expectedDescription); - QCOMPARE(cvc->getBody().getExtensions().value(KnownOid::ID_SECTOR), expectedSector); + QByteArray expectedDescription = QByteArray::fromHex("315A1DA468AE12C839F8AB386E5CAB88C9FFAC2033C9910E202E2004BDE07FE6"); + QCOMPARE(cvc->getBody().getExtension(KnownOid::ID_DESCRIPTION), expectedDescription); + + QByteArray expectedSectorRi = QByteArray::fromHex("39D51F1942520AE8EC7F5CC654E78A521D8C09F607CD9ADF7BB9FDC5BFFB90D7"); + QCOMPARE(cvc->getBody().getExtension(KnownOid::ID_SECTOR_RI), expectedSectorRi); + + QByteArray expectedSectorPs = QByteArray::fromHex("0D"); + QCOMPARE(cvc->getBody().getExtension(KnownOid::ID_SECTOR_PS), expectedSectorPs); + + QVERIFY(rawCert.contains(cvc->getRawBody().toHex())); } void getPublicKey_noCompletePublicKey() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00035.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00035.hex"_L1)); const auto& key = cvc->getBody().getPublicKey(); QVERIFY(!key.getUncompressedPublicPoint().isNull()); @@ -69,7 +85,7 @@ class test_CVCertificateBody void getPublicKey_completePublicKey() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex"_L1)); const auto& key = cvc->getBody().getPublicKey(); QVERIFY(!key.getUncompressedPublicPoint().isNull()); @@ -80,7 +96,7 @@ class test_CVCertificateBody void getCertificationAuthorityReference() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); QCOMPARE(cvc->getBody().getCertificationAuthorityReference(), QByteArray("DETESTeID00001")); } @@ -88,7 +104,7 @@ class test_CVCertificateBody void getCertificateHolderReference() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DETESTeID00001.hex"_L1)); QCOMPARE(cvc->getBody().getCertificateHolderReference(), QByteArray("DETESTeID00001")); } @@ -96,16 +112,16 @@ class test_CVCertificateBody void getCHAT() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1)); auto chat = const_cast(cvc->getBody().getCHAT()); - QCOMPARE(encodeObject(&chat).toHex().toUpper(), QByteArray("7F4C12060904007F0007030102025305000513FF87")); + QCOMPARE(encodeObject(&chat).toHex().toUpper(), "7F4C12060904007F0007030102025305000513FF87"_ba); } void getCertificateEffectiveDate() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1)); QCOMPARE(cvc->getBody().getCertificateEffectiveDate(), QDate(2014, 03, 13)); } @@ -113,7 +129,7 @@ class test_CVCertificateBody void getCertificateExpirationDate() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1)); QCOMPARE(cvc->getBody().getCertificateExpirationDate(), QDate(2014, 04, 11)); } @@ -121,7 +137,7 @@ class test_CVCertificateBody void getHashAlgorithm() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1)); QCOMPARE(static_cast(cvc->getBody().getHashAlgorithm()), static_cast(QCryptographicHash::Sha256)); } @@ -129,7 +145,7 @@ class test_CVCertificateBody void getCertificateProfileIdentifier() { - auto cvc = CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex")); + auto cvc = CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1)); QCOMPARE(cvc->getBody().getCertificateProfileIdentifier(), QByteArray::fromHex("00")); } diff --git a/test/qt/card/asn1/test_CVCertificateChainBuilder.cpp b/test/qt/card/asn1/test_CVCertificateChainBuilder.cpp index 82eefad1e..0a34d02a9 100644 --- a/test/qt/card/asn1/test_CVCertificateChainBuilder.cpp +++ b/test/qt/card/asn1/test_CVCertificateChainBuilder.cpp @@ -1,18 +1,20 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! * \brief Unit tests for \ref CVCertificateChain */ -#include -#include +#include "asn1/CVCertificateChainBuilder.h" +#include "CertificateHelper.h" #include "TestFileHelper.h" -#include "asn1/CVCertificateChainBuilder.h" +#include +#include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,7 +38,7 @@ class test_CVCertificateChainBuilder QByteArray readFile(const QString& pFileName) { - return TestFileHelper::readFile(QString(":/card/").append(pFileName)); + return TestFileHelper::readFile(QStringLiteral(":/card/").append(pFileName)); } @@ -60,18 +62,18 @@ class test_CVCertificateChainBuilder private Q_SLOTS: void initTestCase() { - mCvca_DETESTeID00001 = CVCertificate::fromHex(readFile("cvca-DETESTeID00001.hex")); - mCvca_DETESTeID00002_DETESTeID00001 = CVCertificate::fromHex(readFile("cvca-DETESTeID00002_DETESTeID00001.hex")); - mCvca_DETESTeID00002 = CVCertificate::fromHex(readFile("cvca-DETESTeID00002.hex")); - mCvca_DETESTeID00004_DETESTeID00002 = CVCertificate::fromHex(readFile("cvca-DETESTeID00004_DETESTeID00002.hex")); - mCvca_DETESTeID00004 = CVCertificate::fromHex(readFile("cvca-DETESTeID00004.hex")); - mCvdv_DEDVeIDDPST00035 = CVCertificate::fromHex(readFile("cvdv-DEDVeIDDPST00035.hex")); // DV issued from CVCA DETESTeID00004 - mCvat_DEDEMODEV00038 = CVCertificate::fromHex(readFile("cvat-DEDEMODEV00038.hex")); // TA issued from DV DEDVeIDDPST00035 - - mCvca_DETESTeID00005_DETESTeID00004 = CVCertificate::fromHex(readFile("cvca-DETESTeID00005_DETESTeID00004.hex")); - mCvca_DETESTeID00005 = CVCertificate::fromHex(readFile("cvca-DETESTeID00005.hex")); - mCvdv_DEDVtIDGVNK00005 = CVCertificate::fromHex(readFile("cvdv-DEDVtIDGVNK00005.hex")); // DV issued from CVCA DETESTeID00005 - mCvat_DEDEVDEMO00020 = CVCertificate::fromHex(readFile("cvat-DEDEVDEMO00020.hex")); // TA issued from DV DEDVtIDGVNK00005 + mCvca_DETESTeID00001 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00001.hex"_L1)); + mCvca_DETESTeID00002_DETESTeID00001 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00002_DETESTeID00001.hex"_L1)); + mCvca_DETESTeID00002 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00002.hex"_L1)); + mCvca_DETESTeID00004_DETESTeID00002 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00004_DETESTeID00002.hex"_L1)); + mCvca_DETESTeID00004 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00004.hex"_L1)); + mCvdv_DEDVeIDDPST00035 = CertificateHelper::fromHex(readFile("cvdv-DEDVeIDDPST00035.hex"_L1)); // DV issued from CVCA DETESTeID00004 + mCvat_DEDEMODEV00038 = CertificateHelper::fromHex(readFile("cvat-DEDEMODEV00038.hex"_L1)); // TA issued from DV DEDVeIDDPST00035 + + mCvca_DETESTeID00005_DETESTeID00004 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00005_DETESTeID00004.hex"_L1)); + mCvca_DETESTeID00005 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00005.hex"_L1)); + mCvdv_DEDVtIDGVNK00005 = CertificateHelper::fromHex(readFile("cvdv-DEDVtIDGVNK00005.hex"_L1)); // DV issued from CVCA DETESTeID00005 + mCvat_DEDEVDEMO00020 = CertificateHelper::fromHex(readFile("cvat-DEDEVDEMO00020.hex"_L1)); // TA issued from DV DEDVtIDGVNK00005 } @@ -109,7 +111,7 @@ class test_CVCertificateChainBuilder void noDV_getChainStartingWith() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -129,7 +131,7 @@ class test_CVCertificateChainBuilder void noDV_getChainForCertificationAuthority() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -149,7 +151,7 @@ class test_CVCertificateChainBuilder void noAT_getChainStartingWith() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -169,7 +171,7 @@ class test_CVCertificateChainBuilder void noAT_getChainForCertificationAuthority() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -189,7 +191,7 @@ class test_CVCertificateChainBuilder void onlyATandDV_getChainStartingWith() { - QVector> list; + QList> list; // list.append(mCvca_DETESTeID00005); // list.append(mCvca_DETESTeID00005_DETESTeID00004); do not include any CVCA certificates // list.append(mCvca_DETESTeID00004); @@ -209,7 +211,7 @@ class test_CVCertificateChainBuilder void onlyATandDV_getChainForCertificationAuthority() { - QVector> list; + QList> list; // list.append(mCvca_DETESTeID00005); // list.append(mCvca_DETESTeID00005_DETESTeID00004); do not include any CVCA certificates // list.append(mCvca_DETESTeID00004); @@ -229,7 +231,7 @@ class test_CVCertificateChainBuilder void missingLinkCert_getChainStartingWith() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -254,7 +256,7 @@ class test_CVCertificateChainBuilder void missingLinkCert_getChainForCertificationAuthority() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -292,7 +294,7 @@ class test_CVCertificateChainBuilder */ void match_getChainStartingWith() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -317,7 +319,7 @@ class test_CVCertificateChainBuilder void match_getChainForCertificationAuthority() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -342,7 +344,7 @@ class test_CVCertificateChainBuilder void noMatch_getChainStartingWith() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -362,7 +364,7 @@ class test_CVCertificateChainBuilder void noMatch_getChainForCertificationAuthority() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -382,7 +384,7 @@ class test_CVCertificateChainBuilder void getChainForCertificationAuthority_forCarCurr() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); @@ -405,7 +407,7 @@ class test_CVCertificateChainBuilder void getChainForCertificationAuthority_forCarPrev() { - QVector> list; + QList> list; list.append(mCvca_DETESTeID00005); list.append(mCvca_DETESTeID00005_DETESTeID00004); list.append(mCvca_DETESTeID00004); diff --git a/test/qt/card/asn1/test_CertificateDescription.cpp b/test/qt/card/asn1/test_CertificateDescription.cpp index d44906225..a92afc433 100644 --- a/test/qt/card/asn1/test_CertificateDescription.cpp +++ b/test/qt/card/asn1/test_CertificateDescription.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -109,13 +110,13 @@ class test_CertificateDescription auto certDescr = CertificateDescription::fromHex(hexString); QVERIFY(certDescr != nullptr); - QCOMPARE(QByteArray(certDescr->getDescriptionType()), QByteArray("0.4.0.127.0.7.3.1.3.1.3 (id-pdfFormat)")); - QCOMPARE(certDescr->getIssuerName(), QString("D-Trust GmbH")); + QCOMPARE(certDescr->getDescriptionType(), KnownOid::ID_PFD_FORMAT); + QCOMPARE(certDescr->getIssuerName(), "D-Trust GmbH"_L1); QCOMPARE(certDescr->getIssuerUrl(), QString()); - QCOMPARE(certDescr->getSubjectName(), QString("Gesamtverband der deutschen Versicherungswirtschaft e.V.")); + QCOMPARE(certDescr->getSubjectName(), "Gesamtverband der deutschen Versicherungswirtschaft e.V."_L1); QCOMPARE(certDescr->getSubjectUrl(), QString()); QCOMPARE(certDescr->getTermsOfUsageType(), CertificateDescription::TermsOfUsageType::PDF); - QCOMPARE(certDescr->getTermsOfUsage(), QString("048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978")); + QCOMPARE(certDescr->getTermsOfUsage(), "048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978"_L1); QCOMPARE(certDescr->getRedirectUrl(), QString()); QCOMPARE(certDescr->getCommCertificates().size(), 0); } @@ -143,19 +144,19 @@ class test_CertificateDescription auto certDescr = CertificateDescription::fromHex(hexString); QVERIFY(certDescr != nullptr); - QCOMPARE(QByteArray(certDescr->getDescriptionType()), QByteArray("0.4.0.127.0.7.3.1.3.1.3 (id-pdfFormat)")); - QCOMPARE(certDescr->getIssuerName(), QString("D-Trust GmbH")); - QCOMPARE(certDescr->getIssuerUrl(), QString("http://www.d-trust.net")); - QCOMPARE(certDescr->getSubjectName(), QString("Gesamtverband der deutschen Versicherungswirtschaft e.V.")); - QCOMPARE(certDescr->getSubjectUrl(), QString("https://www.gdv-testportal.de")); + QCOMPARE(certDescr->getDescriptionType(), KnownOid::ID_PFD_FORMAT); + QCOMPARE(certDescr->getIssuerName(), "D-Trust GmbH"_L1); + QCOMPARE(certDescr->getIssuerUrl(), "http://www.d-trust.net"_L1); + QCOMPARE(certDescr->getSubjectName(), "Gesamtverband der deutschen Versicherungswirtschaft e.V."_L1); + QCOMPARE(certDescr->getSubjectUrl(), "https://www.gdv-testportal.de"_L1); QCOMPARE(certDescr->getTermsOfUsageType(), CertificateDescription::TermsOfUsageType::PDF); - QCOMPARE(certDescr->getTermsOfUsage(), QString("048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978")); - QCOMPARE(certDescr->getRedirectUrl(), QString("https://www.redirect-test.de")); + QCOMPARE(certDescr->getTermsOfUsage(), "048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978"_L1); + QCOMPARE(certDescr->getRedirectUrl(), "https://www.redirect-test.de"_L1); QCOMPARE(certDescr->getCommCertificates().size(), 4); - QVERIFY(certDescr->getCommCertificates().contains(QString("0617A64C37179860FEA3044A14052505FB4F8EF4D61F047B6A30130CD06718E6"))); - QVERIFY(certDescr->getCommCertificates().contains(QString("718FA21C2DF3A81BEF1B7A53360481C78C017F1EC7170266C2C4E9BB654B0E3B"))); - QVERIFY(certDescr->getCommCertificates().contains(QString("94B0AA7E8114F3E6DFCD52DA9F43E8B13CCB0589B8957E364728198FB4971AE6"))); - QVERIFY(certDescr->getCommCertificates().contains(QString("E85E1E8A78864E9246C86CF1C2A3810603EEEE75746C70CD51ACB86B5E2655D8"))); + QVERIFY(certDescr->getCommCertificates().contains("0617A64C37179860FEA3044A14052505FB4F8EF4D61F047B6A30130CD06718E6"_L1)); + QVERIFY(certDescr->getCommCertificates().contains("718FA21C2DF3A81BEF1B7A53360481C78C017F1EC7170266C2C4E9BB654B0E3B"_L1)); + QVERIFY(certDescr->getCommCertificates().contains("94B0AA7E8114F3E6DFCD52DA9F43E8B13CCB0589B8957E364728198FB4971AE6"_L1)); + QVERIFY(certDescr->getCommCertificates().contains("E85E1E8A78864E9246C86CF1C2A3810603EEEE75746C70CD51ACB86B5E2655D8"_L1)); } @@ -173,7 +174,7 @@ class test_CertificateDescription QVERIFY(certDescr != nullptr); QCOMPARE(certDescr->getTermsOfUsageType(), CertificateDescription::TermsOfUsageType::PDF); - QCOMPARE(certDescr->getTermsOfUsage(), QString("048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978")); + QCOMPARE(certDescr->getTermsOfUsage(), "048202444E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978"_L1); } @@ -198,7 +199,7 @@ class test_CertificateDescription "

      \n" "

      \n" "Klappt's?\n" - "

      \n"); + "

      \n"_L1); auto certDescr = CertificateDescription::fromHex(hexString); @@ -241,7 +242,7 @@ class test_CertificateDescription const QString providerAddress("Governikus GmbH & Co.KG\n" "Am Fallturm 9\n" "28359 Bremen\n" - "kontakt@governikus.com"); + "kontakt@governikus.com"_L1); auto certDescr = CertificateDescription::fromHex(HEX_STRING); QVERIFY(certDescr); @@ -250,7 +251,7 @@ class test_CertificateDescription const QString providerAddress2017("Governikus GmbH & Co. KG\n" "Am Fallturm 9\n" "28359 Bremen\n" - "kontakt@governikus.com"); + "kontakt@governikus.com"_L1); certDescr = CertificateDescription::fromHex(SELF_AUTH_CERT_2017); QVERIFY(certDescr); QCOMPARE(certDescr->getServiceProviderAddress(), providerAddress2017); @@ -259,7 +260,7 @@ class test_CertificateDescription void purposeFromTermsOfUsage() { - const QString expectedPurpose("Selbstauskunft"); + const QString expectedPurpose("Selbstauskunft"_L1); auto certDescr = CertificateDescription::fromHex(HEX_STRING); QVERIFY(certDescr); @@ -304,18 +305,18 @@ class test_CertificateDescription ASN1_OBJECT_free(certDescr->mDescriptionType); certDescr->mDescriptionType = OBJ_txt2obj("0.4.0.127.0.7.3.1.3.1.3", 1); - Asn1StringUtil::setValue("D-Trust GmbH", certDescr->mIssuerName); + Asn1StringUtil::setValue("D-Trust GmbH"_L1, certDescr->mIssuerName); certDescr->mIssuerURL = ASN1_PRINTABLESTRING_new(); - Asn1StringUtil::setValue("http://www.d-trust.net", certDescr->mIssuerURL); + Asn1StringUtil::setValue("http://www.d-trust.net"_L1, certDescr->mIssuerURL); - Asn1StringUtil::setValue("Gesamtverband der deutschen Versicherungswirtschaft e.V.", certDescr->mSubjectName); + Asn1StringUtil::setValue("Gesamtverband der deutschen Versicherungswirtschaft e.V."_L1, certDescr->mSubjectName); certDescr->mSubjectURL = ASN1_PRINTABLESTRING_new(); - Asn1StringUtil::setValue("https://www.gdv-testportal.de", certDescr->mSubjectURL); + Asn1StringUtil::setValue("https://www.gdv-testportal.de"_L1, certDescr->mSubjectURL); certDescr->mRedirectURL = ASN1_PRINTABLESTRING_new(); - Asn1StringUtil::setValue("https://www.redirect-test.de", certDescr->mRedirectURL); + Asn1StringUtil::setValue("https://www.redirect-test.de"_L1, certDescr->mRedirectURL); QByteArray termsOfUsageBytes = QByteArray::fromHex("4E616D652C20416E7363687269667420756E6420452D4D61696C2D4164726573736520646573204469656E737465616E626965746572733A0D0A476573616D7476657262616E64206465722064657574736368656E20566572736963686572756E67737769727473636861667420652E562E0D0A57696C68656C6D73747261C39F652034332F3433670D0A3130313137204265726C696E0D0A6265726C696E406764762E64650D0A0D0A4765736368C3A46674737A7765636B3A0D0A2D52656769737472696572756E6720756E64204C6F67696E20616D204744562D4D616B6C6572706F7274616C2D0D0A0D0A48696E7765697320617566206469652066C3BC722064656E204469656E737465616E626965746572207A757374C3A46E646967656E205374656C6C656E2C20646965206469652045696E68616C74756E672064657220566F7273636872696674656E207A756D20446174656E73636875747A206B6F6E74726F6C6C696572656E3A0D0A4265726C696E6572204265617566747261677465722066C3BC7220446174656E73636875747A20756E6420496E666F726D6174696F6E7366726569686569740D0A416E20646572205572616E696120342D31300D0A3130373837204265726C696E0D0A3033302F3133382038392D300D0A6D61696C626F7840646174656E73636875747A2D6265726C696E2E64650D0A687474703A2F2F7777772E646174656E73636875747A2D6265726C696E2E64650D0A416E737072656368706172746E65723A2044722E20416C6578616E64657220446978"); ASN1_TYPE_set_octetstring(certDescr->mTermsOfUsage, reinterpret_cast(termsOfUsageBytes.data()), static_cast(termsOfUsageBytes.length())); diff --git a/test/qt/card/asn1/test_ChainBuilder.cpp b/test/qt/card/asn1/test_ChainBuilder.cpp index f98fa5d77..88f568cc0 100644 --- a/test/qt/card/asn1/test_ChainBuilder.cpp +++ b/test/qt/card/asn1/test_ChainBuilder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -44,7 +44,7 @@ class test_ChainBuilder private Q_SLOTS: void testEmpty() { - const QVector allElements; + const QList allElements; ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QVERIFY(chainBuilder.getChains().isEmpty()); @@ -53,7 +53,7 @@ class test_ChainBuilder void testOneShortChain() { - const QVector allElements({"AB"}); + const QList allElements({"AB"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 1); @@ -63,7 +63,7 @@ class test_ChainBuilder void testManyShortChain() { - const QVector allElements({"AB", "AC", "AD", "AE"}); + const QList allElements({"AB", "AC", "AD", "AE"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 4); @@ -76,7 +76,7 @@ class test_ChainBuilder void testShortChainWithDuplicates() { - const QVector allElements({"AB", "AC", "AB", "AC", "AC", "AB"}); + const QList allElements({"AB", "AC", "AB", "AC", "AC", "AB"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 2); @@ -87,7 +87,7 @@ class test_ChainBuilder void testOneLongChain() { - const QVector allElements({"AB", "BC", "CD", "DE", "EF", "FG"}); + const QList allElements({"AB", "BC", "CD", "DE", "EF", "FG"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 1); @@ -97,7 +97,7 @@ class test_ChainBuilder void testOneLongChainWithDuplicates() { - const QVector allElements({"AB", "BC", "BC", "CD", "BC", "CD", "DE", "DE", "EF", "BC", "FG"}); + const QList allElements({"AB", "BC", "BC", "CD", "BC", "CD", "DE", "DE", "EF", "BC", "FG"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 1); @@ -118,13 +118,13 @@ class test_ChainBuilder * | * DE */ - const QVector allElements({"AA", "AB", "BC", "CD", "DE", "BB"}); + const QList allElements({"AA", "AB", "BC", "CD", "DE", "BB"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 2); - QVERIFY(chainBuilder.getChains().contains(QVector({"AA", "AB", "BC", "CD", "DE"}))); - QVERIFY(chainBuilder.getChains().contains(QVector({"BB", "BC", "CD", "DE"}))); + QVERIFY(chainBuilder.getChains().contains(QList({"AA", "AB", "BC", "CD", "DE"}))); + QVERIFY(chainBuilder.getChains().contains(QList({"BB", "BC", "CD", "DE"}))); } @@ -141,13 +141,13 @@ class test_ChainBuilder * | * DE */ - const QVector allElements({"AA", "AB", "BC", "CD", "DE", "CF"}); + const QList allElements({"AA", "AB", "BC", "CD", "DE", "CF"}); ChainBuilder chainBuilder(allElements, &test_ChainBuilder::isChild); QCOMPARE(chainBuilder.getChains().size(), 2); - QVERIFY(chainBuilder.getChains().contains(QVector({"AA", "AB", "BC", "CD", "DE"}))); - QVERIFY(chainBuilder.getChains().contains(QVector({"AA", "AB", "BC", "CF"}))); + QVERIFY(chainBuilder.getChains().contains(QList({"AA", "AB", "BC", "CD", "DE"}))); + QVERIFY(chainBuilder.getChains().contains(QList({"AA", "AB", "BC", "CF"}))); } @@ -166,11 +166,11 @@ class test_ChainBuilder */ QBENCHMARK { - QVector allElements({"AA", "AB", "BC", "CD", "DE", "BB", "CF"}); - const QVector chain1({"AA", "AB", "BC", "CD", "DE"}); - const QVector chain2({"BB", "BC", "CD", "DE"}); - const QVector chain3({"AA", "AB", "BC", "CF"}); - const QVector chain4({"BB", "BC", "CF"}); + QList allElements({"AA", "AB", "BC", "CD", "DE", "BB", "CF"}); + const QList chain1({"AA", "AB", "BC", "CD", "DE"}); + const QList chain2({"BB", "BC", "CD", "DE"}); + const QList chain3({"AA", "AB", "BC", "CF"}); + const QList chain4({"BB", "BC", "CF"}); do { diff --git a/test/qt/card/asn1/test_Chat.cpp b/test/qt/card/asn1/test_Chat.cpp index 1f913aeab..ea2e42752 100644 --- a/test/qt/card/asn1/test_Chat.cpp +++ b/test/qt/card/asn1/test_Chat.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -193,7 +193,7 @@ class test_CHAT auto chat = CHAT::fromHex(hexEncodedChat); QVERIFY(chat != nullptr); - QCOMPARE(QByteArray(chat->getType()), QByteArray("0.4.0.127.0.7.3.1.2.2 (id-AT)")); + QCOMPARE(chat->getType(), KnownOid::ID_AT); QCOMPARE(chat->getTemplate().toHex().toUpper(), QByteArray("FC0F13FFFF")); QVERIFY(encodeObject(chat.data()).toHex().toUpper().endsWith(QByteArray("FC0F13FFFF"))); } diff --git a/test/qt/card/asn1/test_ChipAuthenticationInfo.cpp b/test/qt/card/asn1/test_ChipAuthenticationInfo.cpp index 47675368d..b03439005 100644 --- a/test/qt/card/asn1/test_ChipAuthenticationInfo.cpp +++ b/test/qt/card/asn1/test_ChipAuthenticationInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_EcdsaPublicKey.cpp b/test/qt/card/asn1/test_EcdsaPublicKey.cpp index affd7b8e3..5fb5b9885 100644 --- a/test/qt/card/asn1/test_EcdsaPublicKey.cpp +++ b/test/qt/card/asn1/test_EcdsaPublicKey.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -35,7 +35,7 @@ class test_EcdsaPublicKey return QByteArray(); } - QVector buf(BN_num_bytes(pBigNum)); + QList buf(BN_num_bytes(pBigNum)); BN_bn2bin(pBigNum, buf.data()); return QByteArray(reinterpret_cast(buf.data()), buf.size()); } @@ -66,7 +66,7 @@ class test_EcdsaPublicKey auto bufLen = EC_POINT_point2oct(ecGroup, generator, point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); Q_ASSERT(bufLen <= INT_MAX); - QVector buf(static_cast(bufLen)); + QList buf(static_cast(bufLen)); EC_POINT_point2oct(ecGroup, generator, point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED, reinterpret_cast(buf.data()), static_cast(buf.size()), nullptr); return QByteArray(buf.data(), buf.size()); diff --git a/test/qt/card/asn1/test_Oid.cpp b/test/qt/card/asn1/test_Oid.cpp index 8ca811b10..2befd2658 100644 --- a/test/qt/card/asn1/test_Oid.cpp +++ b/test/qt/card/asn1/test_Oid.cpp @@ -1,16 +1,18 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "asn1/Oid.h" #include "LogHandler.h" +#include "TestFileHelper.h" #include "asn1/ASN1TemplateUtil.h" #include #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_Oid @@ -51,7 +53,7 @@ class test_Oid QCOMPARE(oid, Oid()); QCOMPARE(oid.operator QByteArray(), QByteArray()); - QCOMPARE(oid.getData(), QByteArray()); + QCOMPARE(QByteArray(oid), QByteArray()); QCOMPARE(logSpy.count(), 0); @@ -63,9 +65,9 @@ class test_Oid QTest::addColumn("oid"); QTest::addColumn("warnings"); - QTest::newRow("openssl") << QByteArray("1.2.840.113549.1.7.2") << false; - QTest::newRow("known") << QByteArray("0.4.0.127.0.7.2.2.4") << false; - QTest::newRow("unknown") << QByteArray("0.4.0.127.0.7.2.0") << true; + QTest::newRow("openssl") << QByteArray::fromHex("2A864886F70D010702") << false; + QTest::newRow("known") << QByteArray::fromHex("04007F0007020204") << false; + QTest::newRow("unknown") << QByteArray::fromHex("04007F00070200") << true; } @@ -88,9 +90,9 @@ class test_Oid QTest::addColumn("oid"); QTest::addColumn("warnings"); - QTest::newRow("openssl") << QByteArray("1.2.840.113549.1.7.2") << false; - QTest::newRow("known") << QByteArray("0.4.0.127.0.7.2.2.4") << false; - QTest::newRow("unknown") << QByteArray("0.4.0.127.0.7.2.0") << true; + QTest::newRow("openssl") << QByteArray::fromHex("2A864886F70D010702") << false; + QTest::newRow("known") << QByteArray::fromHex("04007F0007020204") << false; + QTest::newRow("unknown") << QByteArray::fromHex("04007F00070200") << true; } @@ -117,9 +119,9 @@ class test_Oid QTest::addColumn("oid"); QTest::addColumn("warnings"); - QTest::newRow("openssl") << QByteArray("1.2.840.113549.1.7.2") << false; - QTest::newRow("known") << QByteArray("0.4.0.127.0.7.2.2.4") << false; - QTest::newRow("unknown") << QByteArray("0.4.0.127.0.7.2.0") << true; + QTest::newRow("openssl") << QByteArray::fromHex("2A864886F70D010702") << false; + QTest::newRow("known") << QByteArray::fromHex("04007F0007020204") << false; + QTest::newRow("unknown") << QByteArray::fromHex("04007F00070200") << true; } @@ -143,9 +145,9 @@ class test_Oid QTest::addColumn("oid"); QTest::addColumn("warnings"); - QTest::newRow("openssl") << QByteArray("1.2.840.113549.1.7.2") << false; - QTest::newRow("known") << QByteArray("0.4.0.127.0.7.2.2.4") << false; - QTest::newRow("unknown") << QByteArray("0.4.0.127.0.7.2.0") << true; + QTest::newRow("openssl") << QByteArray::fromHex("2A864886F70D010702") << false; + QTest::newRow("known") << QByteArray::fromHex("04007F0007020204") << false; + QTest::newRow("unknown") << QByteArray::fromHex("04007F00070200") << true; } @@ -171,166 +173,168 @@ class test_Oid void getter_data() { QTest::addColumn("oid"); - QTest::addColumn("data"); - QTest::addColumn("logging"); + QTest::addColumn("logging"); QTest::addColumn("warnings"); - QTest::newRow("openssl") << QByteArray("1.2.840.113549.1.7.2") << QByteArray::fromHex("2A864886F70D010702") << QByteArray("1.2.840.113549.1.7.2 (pkcs7-signedData)") << false; - QTest::newRow("known") << QByteArray("0.4.0.127.0.7.2.2.4") << QByteArray::fromHex("04007F0007020204") << QByteArray("0.4.0.127.0.7.2.2.4 (id-PACE)") << false; - QTest::newRow("unknown") << QByteArray("0.4.0.127.0.7.2.0") << QByteArray::fromHex("04007F00070200") << QByteArray("0.4.0.127.0.7.2.0") << true; + QTest::newRow("openssl") << QByteArray::fromHex("2A864886F70D010702") << QLatin1String("1.2.840.113549.1.7.2 (pkcs7-signedData)") << false; + QTest::newRow("known") << QByteArray::fromHex("04007F0007020204") << QLatin1String("0.4.0.127.0.7.2.2.4 (id-PACE)") << false; + QTest::newRow("unknown") << QByteArray::fromHex("04007F00070200") << QLatin1String("0.4.0.127.0.7.2.0") << true; } void getter() { QFETCH(QByteArray, oid); - QFETCH(QByteArray, data); - QFETCH(QByteArray, logging); + QFETCH(QLatin1String, logging); QFETCH(bool, warnings); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); Oid oidObject(oid); + qDebug() << oidObject; - QCOMPARE(oidObject.getData(), data); - QCOMPARE(oidObject.operator QByteArray(), logging); - QCOMPARE(logSpy.count() > 0, warnings); + QCOMPARE(QByteArray(oidObject), oid); + QVERIFY(logSpy.count() > 0); + QVERIFY(TestFileHelper::containsLog(logSpy, logging)); + QCOMPARE(logSpy.count() > 1, warnings); } void knownOids_data() { QTest::addColumn("knownOid"); + QTest::addColumn("bin"); QTest::addColumn("oid"); QTest::addColumn("sn"); QTest::addColumn("ln"); - QTest::newRow("001") << KnownOid::ID_SIGNED_DATA << QByteArray("1.2.840.113549.1.7.2") << QByteArray("pkcs7-signedData") << QByteArray("pkcs7-signedData"); - - QTest::newRow("002") << KnownOid::EC_PS_PUBLICKEY << QByteArray("0.4.0.127.0.7.1.1.2.3") << QByteArray("ecPSPublicKey") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Static keys for Pseudonymous Signatures A.6.1"); - - QTest::newRow("003") << KnownOid::STANDARDIZED_DOMAINPARAMETERS << QByteArray("0.4.0.127.0.7.1.2") << QByteArray("standardizedDomainParameters") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Standardized Domain Parameters A.2.1.1"); - - QTest::newRow("004") << KnownOid::BSI_DE_PROTOCOLS_SMARTCARD << QByteArray("0.4.0.127.0.7.2.2") << QByteArray("bsi-de-protocols-smartcard") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Supported Protocols A.1.1"); - - QTest::newRow("005") << KnownOid::ID_PK << QByteArray("0.4.0.127.0.7.2.2.1") << QByteArray("id-PK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1"); - QTest::newRow("006") << KnownOid::ID_PK_DH << QByteArray("0.4.0.127.0.7.2.2.1.1") << QByteArray("id-PK-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.1"); - QTest::newRow("007") << KnownOid::ID_PK_ECDH << QByteArray("0.4.0.127.0.7.2.2.1.2") << QByteArray("id-PK-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.2"); - QTest::newRow("008") << KnownOid::ID_PS_PK << QByteArray("0.4.0.127.0.7.2.2.1.3") << QByteArray("id-PS-PK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.3"); - QTest::newRow("009") << KnownOid::ID_PS_PK_ECDH_ESCHNORR << QByteArray("0.4.0.127.0.7.2.2.1.3.2") << QByteArray("id-PS-PK-ECDH-ECSchnorr") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.3.2"); - - QTest::newRow("010") << KnownOid::ID_TA << QByteArray("0.4.0.127.0.7.2.2.2") << QByteArray("id-TA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3"); - QTest::newRow("011") << KnownOid::ID_TA_RSA << QByteArray("0.4.0.127.0.7.2.2.2.1") << QByteArray("id-TA-RSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1"); - QTest::newRow("012") << KnownOid::ID_TA_RSA_V1_5_SHA_1 << QByteArray("0.4.0.127.0.7.2.2.2.1.1") << QByteArray("id-TA-RSA-v1-5-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.1"); - QTest::newRow("013") << KnownOid::ID_TA_RSA_V1_5_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.2.1.2") << QByteArray("id-TA-RSA-v1-5-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.2"); - QTest::newRow("014") << KnownOid::ID_TA_RSA_PSS_SHA_1 << QByteArray("0.4.0.127.0.7.2.2.2.1.3") << QByteArray("id-TA-RSA-PSS-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.3"); - QTest::newRow("015") << KnownOid::ID_TA_RSA_PSS_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.2.1.4") << QByteArray("id-TA-RSA-PSS-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.4"); - QTest::newRow("016") << KnownOid::ID_TA_RSA_V1_5_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.2.1.5") << QByteArray("id-TA-RSA-v1-5-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.5"); - QTest::newRow("017") << KnownOid::ID_TA_RSA_PSS_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.2.1.6") << QByteArray("id-TA-RSA-PSS-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.6"); - QTest::newRow("018") << KnownOid::ID_TA_ECDSA << QByteArray("0.4.0.127.0.7.2.2.2.2") << QByteArray("id-TA-ECDSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2"); - QTest::newRow("019") << KnownOid::ID_TA_ECDSA_SHA_1 << QByteArray("0.4.0.127.0.7.2.2.2.2.1") << QByteArray("id-TA-ECDSA-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.1"); - QTest::newRow("020") << KnownOid::ID_TA_ECDSA_SHA_224 << QByteArray("0.4.0.127.0.7.2.2.2.2.2") << QByteArray("id-TA-ECDSA-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.2"); - QTest::newRow("021") << KnownOid::ID_TA_ECDSA_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.2.2.3") << QByteArray("id-TA-ECDSA-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.3"); - QTest::newRow("022") << KnownOid::ID_TA_ECDSA_SHA_384 << QByteArray("0.4.0.127.0.7.2.2.2.2.4") << QByteArray("id-TA-ECDSA-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.4"); - QTest::newRow("023") << KnownOid::ID_TA_ECDSA_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.2.2.5") << QByteArray("id-TA-ECDSA-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.5"); - - QTest::newRow("024") << KnownOid::ID_CA << QByteArray("0.4.0.127.0.7.2.2.3") << QByteArray("id-CA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3"); - QTest::newRow("025") << KnownOid::ID_CA_DH << QByteArray("0.4.0.127.0.7.2.2.3.1") << QByteArray("id-CA-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1"); - QTest::newRow("026") << KnownOid::ID_CA_DH_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.3.1.1") << QByteArray("id-CA-DH-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.1"); - QTest::newRow("027") << KnownOid::ID_CA_DH_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.3.1.2") << QByteArray("id-CA-DH-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.2"); - QTest::newRow("028") << KnownOid::ID_CA_DH_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.3.1.3") << QByteArray("id-CA-DH-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.3"); - QTest::newRow("029") << KnownOid::ID_CA_DH_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.3.1.4") << QByteArray("id-CA-DH-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.4"); - QTest::newRow("030") << KnownOid::ID_CA_ECDH << QByteArray("0.4.0.127.0.7.2.2.3.2") << QByteArray("id-CA-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2"); - QTest::newRow("031") << KnownOid::ID_CA_ECDH_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.3.2.1") << QByteArray("id-CA-ECDH-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.1"); - QTest::newRow("032") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.3.2.2") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.2"); - QTest::newRow("033") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.3.2.3") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.3"); - QTest::newRow("034") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.3.2.4") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.4"); - - QTest::newRow("035") << KnownOid::ID_PACE << QByteArray("0.4.0.127.0.7.2.2.4") << QByteArray("id-PACE") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4"); - QTest::newRow("036") << KnownOid::ID_PACE_DH_GM << QByteArray("0.4.0.127.0.7.2.2.4.1") << QByteArray("id-PACE-DH-GM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1"); - QTest::newRow("037") << KnownOid::ID_PACE_DH_GM_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.4.1.1") << QByteArray("id-PACE-DH-GM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.1"); - QTest::newRow("038") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.4.1.2") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.2"); - QTest::newRow("039") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.4.1.3") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.3"); - QTest::newRow("040") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.4.1.4") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.4"); - QTest::newRow("041") << KnownOid::ID_PACE_ECDH_GM << QByteArray("0.4.0.127.0.7.2.2.4.2") << QByteArray("id-PACE-ECDH-GM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2"); - QTest::newRow("042") << KnownOid::ID_PACE_ECDH_GM_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.4.2.1") << QByteArray("id-PACE-ECDH-GM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.1"); - QTest::newRow("043") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.4.2.2") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.2"); - QTest::newRow("044") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.4.2.3") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.3"); - QTest::newRow("045") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.4.2.4") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.4"); - QTest::newRow("046") << KnownOid::ID_PACE_DH_IM << QByteArray("0.4.0.127.0.7.2.2.4.3") << QByteArray("id-PACE-DH-IM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3"); - QTest::newRow("047") << KnownOid::ID_PACE_DH_IM_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.4.3.1") << QByteArray("id-PACE-DH-IM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.1"); - QTest::newRow("048") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.4.3.2") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.2"); - QTest::newRow("049") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.4.3.3") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.3"); - QTest::newRow("050") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.4.3.4") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.4"); - QTest::newRow("051") << KnownOid::ID_PACE_ECDH_IM << QByteArray("0.4.0.127.0.7.2.2.4.4") << QByteArray("id-PACE-ECDH-IM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4"); - QTest::newRow("052") << KnownOid::ID_PACE_ECDH_IM_3DES_CBC_CBC << QByteArray("0.4.0.127.0.7.2.2.4.4.1") << QByteArray("id-PACE-ECDH-IM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.1"); - QTest::newRow("053") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.4.4.2") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.2"); - QTest::newRow("054") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.4.4.3") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.3"); - QTest::newRow("055") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.4.4.4") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.4"); - QTest::newRow("056") << KnownOid::ID_PACE_ECDH_CAM << QByteArray("0.4.0.127.0.7.2.2.4.6") << QByteArray("id-PACE-ECDH-CAM") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6"); - QTest::newRow("057") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_128 << QByteArray("0.4.0.127.0.7.2.2.4.6.2") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.2"); - QTest::newRow("058") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_192 << QByteArray("0.4.0.127.0.7.2.2.4.6.3") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.3"); - QTest::newRow("059") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_256 << QByteArray("0.4.0.127.0.7.2.2.4.6.4") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.4"); - - QTest::newRow("060") << KnownOid::ID_RI << QByteArray("0.4.0.127.0.7.2.2.5") << QByteArray("id-RI") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4"); - QTest::newRow("061") << KnownOid::ID_RI_DH << QByteArray("0.4.0.127.0.7.2.2.5.1") << QByteArray("id-RI-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1"); - QTest::newRow("062") << KnownOid::ID_RI_DH_SHA_1 << QByteArray("0.4.0.127.0.7.2.2.5.1.1") << QByteArray("id-RI-DH-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.1"); - QTest::newRow("063") << KnownOid::ID_RI_DH_SHA_224 << QByteArray("0.4.0.127.0.7.2.2.5.1.2") << QByteArray("id-RI-DH-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.2"); - QTest::newRow("064") << KnownOid::ID_RI_DH_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.5.1.3") << QByteArray("id-RI-DH-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.3"); - QTest::newRow("065") << KnownOid::ID_RI_DH_SHA_384 << QByteArray("0.4.0.127.0.7.2.2.5.1.4") << QByteArray("id-RI-DH-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.4"); - QTest::newRow("066") << KnownOid::ID_RI_DH_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.5.1.5") << QByteArray("id-RI-DH-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.5"); - QTest::newRow("067") << KnownOid::ID_RI_ECDH << QByteArray("0.4.0.127.0.7.2.2.5.2") << QByteArray("id-RI-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2"); - QTest::newRow("068") << KnownOid::ID_RI_ECDH_SHA_1 << QByteArray("0.4.0.127.0.7.2.2.5.2.1") << QByteArray("id-RI-ECDH-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.1"); - QTest::newRow("069") << KnownOid::ID_RI_ECDH_SHA_224 << QByteArray("0.4.0.127.0.7.2.2.5.2.2") << QByteArray("id-RI-ECDH-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.2"); - QTest::newRow("070") << KnownOid::ID_RI_ECDH_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.5.2.3") << QByteArray("id-RI-ECDH-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.3"); - QTest::newRow("071") << KnownOid::ID_RI_ECDH_SHA_384 << QByteArray("0.4.0.127.0.7.2.2.5.2.4") << QByteArray("id-RI-ECDH-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.4"); - QTest::newRow("072") << KnownOid::ID_RI_ECDH_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.5.2.5") << QByteArray("id-RI-ECDH-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.5"); - - QTest::newRow("073") << KnownOid::ID_CI << QByteArray("0.4.0.127.0.7.2.2.6") << QByteArray("id-CI") << QByteArray("BSI TR-03110 Part 3 Version 2.21 CardInfo (eIDAS token only) A.1.1.7"); - - QTest::newRow("074") << KnownOid::ID_EID_SECURITY << QByteArray("0.4.0.127.0.7.2.2.7") << QByteArray("id-eIDSecurity") << QByteArray("BSI TR-03110 Part 3 Version 2.21 EIDSecurityInfo (eIDAS token only) A.1.1.8"); - - QTest::newRow("075") << KnownOid::ID_PT << QByteArray("0.4.0.127.0.7.2.2.8") << QByteArray("id-PT") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PrivilegedTerminalInfo (eIDAS token only) A.1.1.9"); - - QTest::newRow("076") << KnownOid::ID_PS << QByteArray("0.4.0.127.0.7.2.2.11") << QByteArray("id-PS") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11"); - QTest::newRow("077") << KnownOid::ID_PSA << QByteArray("0.4.0.127.0.7.2.2.11.1") << QByteArray("id-PSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1"); - QTest::newRow("078") << KnownOid::ID_PSA_ECDH_ECSCHNORR << QByteArray("0.4.0.127.0.7.2.2.11.1.2") << QByteArray("id-PSA-ECDH-ECSchnorr") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2"); - QTest::newRow("079") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_256 << QByteArray("0.4.0.127.0.7.2.2.11.1.2.3") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.3"); - QTest::newRow("080") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_384 << QByteArray("0.4.0.127.0.7.2.2.11.1.2.4") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.4"); - QTest::newRow("081") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_512 << QByteArray("0.4.0.127.0.7.2.2.11.1.2.5") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.5"); - - QTest::newRow("082") << KnownOid::ID_PASSWORDTYPE << QByteArray("0.4.0.127.0.7.2.2.12") << QByteArray("id-PasswordType") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12"); - QTest::newRow("083") << KnownOid::ID_PASSWORDTYPE_MRZ << QByteArray("0.4.0.127.0.7.2.2.12.1") << QByteArray("id-PasswordType-MRZ") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.1"); - QTest::newRow("084") << KnownOid::ID_PASSWORDTYPE_CAN << QByteArray("0.4.0.127.0.7.2.2.12.2") << QByteArray("id-PasswordType-CAN") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.2"); - QTest::newRow("085") << KnownOid::ID_PASSWORDTYPE_PIN << QByteArray("0.4.0.127.0.7.2.2.12.3") << QByteArray("id-PasswordType-PIN") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.3"); - QTest::newRow("086") << KnownOid::ID_PASSWORDTYPE_PUK << QByteArray("0.4.0.127.0.7.2.2.12.4") << QByteArray("id-PasswordType-PUK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.4"); - - QTest::newRow("087") << KnownOid::ID_AUXILIARY_DATA << QByteArray("0.4.0.127.0.7.3.1.4") << QByteArray("id-AuxiliaryData") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Object Identifier A.7.5.1"); - QTest::newRow("088") << KnownOid::ID_DATE_OF_BIRTH << QByteArray("0.4.0.127.0.7.3.1.4.1") << QByteArray("id-DateOfBirth") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Age Verification A.7.5.2"); - QTest::newRow("089") << KnownOid::ID_DATE_OF_EXPIRY << QByteArray("0.4.0.127.0.7.3.1.4.2") << QByteArray("id-DateOfExpiry") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Document Validity Verification A.7.5.3"); - QTest::newRow("090") << KnownOid::ID_MUNICIPALITY_ID << QByteArray("0.4.0.127.0.7.3.1.4.3") << QByteArray("id-MunicipalityID") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Municipality ID Verification A.7.5.4"); - QTest::newRow("091") << KnownOid::ID_PSM_MESSAGE << QByteArray("0.4.0.127.0.7.3.1.4.4") << QByteArray("id-PSM-Message") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Pseudonymous Signature of Messages A.7.5.5"); - - QTest::newRow("092") << KnownOid::ID_SECURITY_OBJECT << QByteArray("0.4.0.127.0.7.3.2.1") << QByteArray("id-SecurityObject") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Signature Format for CardSecurity and ChipSecurity A.1.2.5"); - - QTest::newRow("093") << KnownOid::ID_ROLES << QByteArray("0.4.0.127.0.7.3.1.2") << QByteArray("id-roles") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Applications and Terminals 2"); - QTest::newRow("094") << KnownOid::ID_IS << QByteArray("0.4.0.127.0.7.3.1.2.1") << QByteArray("id-IS") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Authorization 2.1.3.2"); - QTest::newRow("095") << KnownOid::ID_AT << QByteArray("0.4.0.127.0.7.3.1.2.2") << QByteArray("id-AT") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Authorization 2.2.3.2"); - QTest::newRow("096") << KnownOid::ID_ST << QByteArray("0.4.0.127.0.7.3.1.2.3") << QByteArray("id-ST") << QByteArray("BSI TR-03110 Part 3 Version 2.11 Signature Terminals C.4.3"); - - QTest::newRow("097") << KnownOid::ID_EXTENSIONS << QByteArray("0.4.0.127.0.7.3.1.3") << QByteArray("id-extensions") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Certificate Extensions for Terminal Authentication Version 2 C.3"); - QTest::newRow("098") << KnownOid::ID_DESCRIPTION << QByteArray("0.4.0.127.0.7.3.1.3.1") << QByteArray("id-description") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Certificate Description Extension 2.2.6"); - QTest::newRow("099") << KnownOid::ID_PLAIN_FORMAT << QByteArray("0.4.0.127.0.7.3.1.3.1.1") << QByteArray("id-plainFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Plain Text Format 2.2.6.1"); - QTest::newRow("100") << KnownOid::ID_HTML_FORMAT << QByteArray("0.4.0.127.0.7.3.1.3.1.2") << QByteArray("id-htmlFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 HTML Format 2.2.6.2"); - QTest::newRow("101") << KnownOid::ID_PFD_FORMAT << QByteArray("0.4.0.127.0.7.3.1.3.1.3") << QByteArray("id-pdfFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 PDF Format 2.2.6.3"); - QTest::newRow("102") << KnownOid::ID_SECTOR << QByteArray("0.4.0.127.0.7.3.1.3.2") << QByteArray("id-sector") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Restricted Identification C.3.2.1"); - - QTest::newRow("103") << KnownOid::ID_EID_TYPE << QByteArray("0.4.0.127.0.7.3.2.3") << QByteArray("id-eIDType") << QByteArray("Draft Smart-eID"); - QTest::newRow("104") << KnownOid::ID_CARD_EID_TYPE << QByteArray("0.4.0.127.0.7.3.2.3.1") << QByteArray("id-cardEIDType") << QByteArray("Draft Smart-eID - 1"); - QTest::newRow("105") << KnownOid::ID_MOBILE_EID_TYPE << QByteArray("0.4.0.127.0.7.3.2.3.2") << QByteArray("id-mobileEIDType") << QByteArray("Draft Smart-eID - 2"); - QTest::newRow("106") << KnownOid::ID_MOBILE_EID_TYPE_SE_CERTIFIED << QByteArray("0.4.0.127.0.7.3.2.3.2.1") << QByteArray("id-mobileEIDType-SECertified") << QByteArray("Draft Smart-eID - 2.1"); - QTest::newRow("107") << KnownOid::ID_MOBILE_EID_TYPE_SE_ENDORSED << QByteArray("0.4.0.127.0.7.3.2.3.2.2") << QByteArray("id-mobileEIDType-SEEndorsed") << QByteArray("Draft Smart-eID - 2.2"); - QTest::newRow("108") << KnownOid::ID_MOBILE_EID_TYPE_HW_KEYSTORE << QByteArray("0.4.0.127.0.7.3.2.3.2.3") << QByteArray("id-mobileEIDType-HWKeyStore") << QByteArray("Draft Smart-eID - 2.3"); + QTest::newRow("001") << KnownOid::ID_SIGNED_DATA << QByteArray::fromHex("2A864886F70D010702") << QByteArray("1.2.840.113549.1.7.2") << QByteArray("pkcs7-signedData") << QByteArray("pkcs7-signedData"); + + QTest::newRow("002") << KnownOid::EC_PS_PUBLICKEY << QByteArray::fromHex("04007F000701010203") << QByteArray("0.4.0.127.0.7.1.1.2.3") << QByteArray("ecPSPublicKey") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Static keys for Pseudonymous Signatures A.6.1"); + + QTest::newRow("003") << KnownOid::STANDARDIZED_DOMAINPARAMETERS << QByteArray::fromHex("04007F00070102") << QByteArray("0.4.0.127.0.7.1.2") << QByteArray("standardizedDomainParameters") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Standardized Domain Parameters A.2.1.1"); + + QTest::newRow("004") << KnownOid::BSI_DE_PROTOCOLS_SMARTCARD << QByteArray::fromHex("04007F00070202") << QByteArray("0.4.0.127.0.7.2.2") << QByteArray("bsi-de-protocols-smartcard") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Supported Protocols A.1.1"); + + QTest::newRow("005") << KnownOid::ID_PK << QByteArray::fromHex("04007F0007020201") << QByteArray("0.4.0.127.0.7.2.2.1") << QByteArray("id-PK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1"); + QTest::newRow("006") << KnownOid::ID_PK_DH << QByteArray::fromHex("04007F000702020101") << QByteArray("0.4.0.127.0.7.2.2.1.1") << QByteArray("id-PK-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.1"); + QTest::newRow("007") << KnownOid::ID_PK_ECDH << QByteArray::fromHex("04007F000702020102") << QByteArray("0.4.0.127.0.7.2.2.1.2") << QByteArray("id-PK-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.2"); + QTest::newRow("008") << KnownOid::ID_PS_PK << QByteArray::fromHex("04007F000702020103") << QByteArray("0.4.0.127.0.7.2.2.1.3") << QByteArray("id-PS-PK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.3"); + QTest::newRow("009") << KnownOid::ID_PS_PK_ECDH_ESCHNORR << QByteArray::fromHex("04007F00070202010302") << QByteArray("0.4.0.127.0.7.2.2.1.3.2") << QByteArray("id-PS-PK-ECDH-ECSchnorr") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 1.3.2"); + + QTest::newRow("010") << KnownOid::ID_TA << QByteArray::fromHex("04007F0007020202") << QByteArray("0.4.0.127.0.7.2.2.2") << QByteArray("id-TA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3"); + QTest::newRow("011") << KnownOid::ID_TA_RSA << QByteArray::fromHex("04007F000702020201") << QByteArray("0.4.0.127.0.7.2.2.2.1") << QByteArray("id-TA-RSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1"); + QTest::newRow("012") << KnownOid::ID_TA_RSA_V1_5_SHA_1 << QByteArray::fromHex("04007F00070202020101") << QByteArray("0.4.0.127.0.7.2.2.2.1.1") << QByteArray("id-TA-RSA-v1-5-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.1"); + QTest::newRow("013") << KnownOid::ID_TA_RSA_V1_5_SHA_256 << QByteArray::fromHex("04007F00070202020102") << QByteArray("0.4.0.127.0.7.2.2.2.1.2") << QByteArray("id-TA-RSA-v1-5-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.2"); + QTest::newRow("014") << KnownOid::ID_TA_RSA_PSS_SHA_1 << QByteArray::fromHex("04007F00070202020103") << QByteArray("0.4.0.127.0.7.2.2.2.1.3") << QByteArray("id-TA-RSA-PSS-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.3"); + QTest::newRow("015") << KnownOid::ID_TA_RSA_PSS_SHA_256 << QByteArray::fromHex("04007F00070202020104") << QByteArray("0.4.0.127.0.7.2.2.2.1.4") << QByteArray("id-TA-RSA-PSS-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.4"); + QTest::newRow("016") << KnownOid::ID_TA_RSA_V1_5_SHA_512 << QByteArray::fromHex("04007F00070202020105") << QByteArray("0.4.0.127.0.7.2.2.2.1.5") << QByteArray("id-TA-RSA-v1-5-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.5"); + QTest::newRow("017") << KnownOid::ID_TA_RSA_PSS_SHA_512 << QByteArray::fromHex("04007F00070202020106") << QByteArray("0.4.0.127.0.7.2.2.2.1.6") << QByteArray("id-TA-RSA-PSS-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 1.6"); + QTest::newRow("018") << KnownOid::ID_TA_ECDSA << QByteArray::fromHex("04007F000702020202") << QByteArray("0.4.0.127.0.7.2.2.2.2") << QByteArray("id-TA-ECDSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2"); + QTest::newRow("019") << KnownOid::ID_TA_ECDSA_SHA_1 << QByteArray::fromHex("04007F00070202020201") << QByteArray("0.4.0.127.0.7.2.2.2.2.1") << QByteArray("id-TA-ECDSA-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.1"); + QTest::newRow("020") << KnownOid::ID_TA_ECDSA_SHA_224 << QByteArray::fromHex("04007F00070202020202") << QByteArray("0.4.0.127.0.7.2.2.2.2.2") << QByteArray("id-TA-ECDSA-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.2"); + QTest::newRow("021") << KnownOid::ID_TA_ECDSA_SHA_256 << QByteArray::fromHex("04007F00070202020203") << QByteArray("0.4.0.127.0.7.2.2.2.2.3") << QByteArray("id-TA-ECDSA-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.3"); + QTest::newRow("022") << KnownOid::ID_TA_ECDSA_SHA_384 << QByteArray::fromHex("04007F00070202020204") << QByteArray("0.4.0.127.0.7.2.2.2.2.4") << QByteArray("id-TA-ECDSA-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.4"); + QTest::newRow("023") << KnownOid::ID_TA_ECDSA_SHA_512 << QByteArray::fromHex("04007F00070202020205") << QByteArray("0.4.0.127.0.7.2.2.2.2.5") << QByteArray("id-TA-ECDSA-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Authentication A.1.1.3 - 2.5"); + + QTest::newRow("024") << KnownOid::ID_CA << QByteArray::fromHex("04007F0007020203") << QByteArray("0.4.0.127.0.7.2.2.3") << QByteArray("id-CA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3"); + QTest::newRow("025") << KnownOid::ID_CA_DH << QByteArray::fromHex("04007F000702020301") << QByteArray("0.4.0.127.0.7.2.2.3.1") << QByteArray("id-CA-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1"); + QTest::newRow("026") << KnownOid::ID_CA_DH_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202030101") << QByteArray("0.4.0.127.0.7.2.2.3.1.1") << QByteArray("id-CA-DH-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.1"); + QTest::newRow("027") << KnownOid::ID_CA_DH_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202030102") << QByteArray("0.4.0.127.0.7.2.2.3.1.2") << QByteArray("id-CA-DH-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.2"); + QTest::newRow("028") << KnownOid::ID_CA_DH_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202030103") << QByteArray("0.4.0.127.0.7.2.2.3.1.3") << QByteArray("id-CA-DH-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.3"); + QTest::newRow("029") << KnownOid::ID_CA_DH_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202030104") << QByteArray("0.4.0.127.0.7.2.2.3.1.4") << QByteArray("id-CA-DH-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.1.4"); + QTest::newRow("030") << KnownOid::ID_CA_ECDH << QByteArray::fromHex("04007F000702020302") << QByteArray("0.4.0.127.0.7.2.2.3.2") << QByteArray("id-CA-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2"); + QTest::newRow("031") << KnownOid::ID_CA_ECDH_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202030201") << QByteArray("0.4.0.127.0.7.2.2.3.2.1") << QByteArray("id-CA-ECDH-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.1"); + QTest::newRow("032") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202030202") << QByteArray("0.4.0.127.0.7.2.2.3.2.2") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.2"); + QTest::newRow("033") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202030203") << QByteArray("0.4.0.127.0.7.2.2.3.2.3") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.3"); + QTest::newRow("034") << KnownOid::ID_CA_ECDH_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202030204") << QByteArray("0.4.0.127.0.7.2.2.3.2.4") << QByteArray("id-CA-ECDH-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 3.2.4"); + + QTest::newRow("035") << KnownOid::ID_PACE << QByteArray::fromHex("04007F0007020204") << QByteArray("0.4.0.127.0.7.2.2.4") << QByteArray("id-PACE") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4"); + QTest::newRow("036") << KnownOid::ID_PACE_DH_GM << QByteArray::fromHex("04007F000702020401") << QByteArray("0.4.0.127.0.7.2.2.4.1") << QByteArray("id-PACE-DH-GM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1"); + QTest::newRow("037") << KnownOid::ID_PACE_DH_GM_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202040101") << QByteArray("0.4.0.127.0.7.2.2.4.1.1") << QByteArray("id-PACE-DH-GM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.1"); + QTest::newRow("038") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202040102") << QByteArray("0.4.0.127.0.7.2.2.4.1.2") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.2"); + QTest::newRow("039") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202040103") << QByteArray("0.4.0.127.0.7.2.2.4.1.3") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.3"); + QTest::newRow("040") << KnownOid::ID_PACE_DH_GM_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202040104") << QByteArray("0.4.0.127.0.7.2.2.4.1.4") << QByteArray("id-PACE-DH-GM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.1.4"); + QTest::newRow("041") << KnownOid::ID_PACE_ECDH_GM << QByteArray::fromHex("04007F000702020402") << QByteArray("0.4.0.127.0.7.2.2.4.2") << QByteArray("id-PACE-ECDH-GM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2"); + QTest::newRow("042") << KnownOid::ID_PACE_ECDH_GM_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202040201") << QByteArray("0.4.0.127.0.7.2.2.4.2.1") << QByteArray("id-PACE-ECDH-GM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.1"); + QTest::newRow("043") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202040202") << QByteArray("0.4.0.127.0.7.2.2.4.2.2") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.2"); + QTest::newRow("044") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202040203") << QByteArray("0.4.0.127.0.7.2.2.4.2.3") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.3"); + QTest::newRow("045") << KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202040204") << QByteArray("0.4.0.127.0.7.2.2.4.2.4") << QByteArray("id-PACE-ECDH-GM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.2.4"); + QTest::newRow("046") << KnownOid::ID_PACE_DH_IM << QByteArray::fromHex("04007F000702020403") << QByteArray("0.4.0.127.0.7.2.2.4.3") << QByteArray("id-PACE-DH-IM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3"); + QTest::newRow("047") << KnownOid::ID_PACE_DH_IM_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202040301") << QByteArray("0.4.0.127.0.7.2.2.4.3.1") << QByteArray("id-PACE-DH-IM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.1"); + QTest::newRow("048") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202040302") << QByteArray("0.4.0.127.0.7.2.2.4.3.2") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.2"); + QTest::newRow("049") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202040303") << QByteArray("0.4.0.127.0.7.2.2.4.3.3") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.3"); + QTest::newRow("050") << KnownOid::ID_PACE_DH_IM_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202040304") << QByteArray("0.4.0.127.0.7.2.2.4.3.4") << QByteArray("id-PACE-DH-IM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.3.4"); + QTest::newRow("051") << KnownOid::ID_PACE_ECDH_IM << QByteArray::fromHex("04007F000702020404") << QByteArray("0.4.0.127.0.7.2.2.4.4") << QByteArray("id-PACE-ECDH-IM") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4"); + QTest::newRow("052") << KnownOid::ID_PACE_ECDH_IM_3DES_CBC_CBC << QByteArray::fromHex("04007F00070202040401") << QByteArray("0.4.0.127.0.7.2.2.4.4.1") << QByteArray("id-PACE-ECDH-IM-3DES-CBC-CBC") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.1"); + QTest::newRow("053") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202040402") << QByteArray("0.4.0.127.0.7.2.2.4.4.2") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.2"); + QTest::newRow("054") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202040403") << QByteArray("0.4.0.127.0.7.2.2.4.4.3") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.3"); + QTest::newRow("055") << KnownOid::ID_PACE_ECDH_IM_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202040404") << QByteArray("0.4.0.127.0.7.2.2.4.4.4") << QByteArray("id-PACE-ECDH-IM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 4.4.4"); + QTest::newRow("056") << KnownOid::ID_PACE_ECDH_CAM << QByteArray::fromHex("04007F000702020406") << QByteArray("0.4.0.127.0.7.2.2.4.6") << QByteArray("id-PACE-ECDH-CAM") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6"); + QTest::newRow("057") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_128 << QByteArray::fromHex("04007F00070202040602") << QByteArray("0.4.0.127.0.7.2.2.4.6.2") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-128") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.2"); + QTest::newRow("058") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_192 << QByteArray::fromHex("04007F00070202040603") << QByteArray("0.4.0.127.0.7.2.2.4.6.3") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-192") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.3"); + QTest::newRow("059") << KnownOid::ID_PACE_ECDH_CAM_AES_CBC_CMAC_256 << QByteArray::fromHex("04007F00070202040604") << QByteArray("0.4.0.127.0.7.2.2.4.6.4") << QByteArray("id-PACE-ECDH-CAM-AES-CBC-CMAC-256") << QByteArray("BSI TR-03105 Part 5.1 Version 1.5 PACE 7.4 - 6.4"); + + QTest::newRow("060") << KnownOid::ID_RI << QByteArray::fromHex("04007F0007020205") << QByteArray("0.4.0.127.0.7.2.2.5") << QByteArray("id-RI") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4"); + QTest::newRow("061") << KnownOid::ID_RI_DH << QByteArray::fromHex("04007F000702020501") << QByteArray("0.4.0.127.0.7.2.2.5.1") << QByteArray("id-RI-DH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1"); + QTest::newRow("062") << KnownOid::ID_RI_DH_SHA_1 << QByteArray::fromHex("04007F00070202050101") << QByteArray("0.4.0.127.0.7.2.2.5.1.1") << QByteArray("id-RI-DH-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.1"); + QTest::newRow("063") << KnownOid::ID_RI_DH_SHA_224 << QByteArray::fromHex("04007F00070202050102") << QByteArray("0.4.0.127.0.7.2.2.5.1.2") << QByteArray("id-RI-DH-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.2"); + QTest::newRow("064") << KnownOid::ID_RI_DH_SHA_256 << QByteArray::fromHex("04007F00070202050103") << QByteArray("0.4.0.127.0.7.2.2.5.1.3") << QByteArray("id-RI-DH-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.3"); + QTest::newRow("065") << KnownOid::ID_RI_DH_SHA_384 << QByteArray::fromHex("04007F00070202050104") << QByteArray("0.4.0.127.0.7.2.2.5.1.4") << QByteArray("id-RI-DH-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.4"); + QTest::newRow("066") << KnownOid::ID_RI_DH_SHA_512 << QByteArray::fromHex("04007F00070202050105") << QByteArray("0.4.0.127.0.7.2.2.5.1.5") << QByteArray("id-RI-DH-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 1.5"); + QTest::newRow("067") << KnownOid::ID_RI_ECDH << QByteArray::fromHex("04007F000702020502") << QByteArray("0.4.0.127.0.7.2.2.5.2") << QByteArray("id-RI-ECDH") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2"); + QTest::newRow("068") << KnownOid::ID_RI_ECDH_SHA_1 << QByteArray::fromHex("04007F00070202050201") << QByteArray("0.4.0.127.0.7.2.2.5.2.1") << QByteArray("id-RI-ECDH-SHA-1") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.1"); + QTest::newRow("069") << KnownOid::ID_RI_ECDH_SHA_224 << QByteArray::fromHex("04007F00070202050202") << QByteArray("0.4.0.127.0.7.2.2.5.2.2") << QByteArray("id-RI-ECDH-SHA-224") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.2"); + QTest::newRow("070") << KnownOid::ID_RI_ECDH_SHA_256 << QByteArray::fromHex("04007F00070202050203") << QByteArray("0.4.0.127.0.7.2.2.5.2.3") << QByteArray("id-RI-ECDH-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.3"); + QTest::newRow("071") << KnownOid::ID_RI_ECDH_SHA_384 << QByteArray::fromHex("04007F00070202050204") << QByteArray("0.4.0.127.0.7.2.2.5.2.4") << QByteArray("id-RI-ECDH-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.4"); + QTest::newRow("072") << KnownOid::ID_RI_ECDH_SHA_512 << QByteArray::fromHex("04007F00070202050205") << QByteArray("0.4.0.127.0.7.2.2.5.2.5") << QByteArray("id-RI-ECDH-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Restricted Identification A.1.1.4 - 2.5"); + + QTest::newRow("073") << KnownOid::ID_CI << QByteArray::fromHex("04007F0007020206") << QByteArray("0.4.0.127.0.7.2.2.6") << QByteArray("id-CI") << QByteArray("BSI TR-03110 Part 3 Version 2.21 CardInfo (eIDAS token only) A.1.1.7"); + + QTest::newRow("074") << KnownOid::ID_EID_SECURITY << QByteArray::fromHex("04007F0007020207") << QByteArray("0.4.0.127.0.7.2.2.7") << QByteArray("id-eIDSecurity") << QByteArray("BSI TR-03110 Part 3 Version 2.21 EIDSecurityInfo (eIDAS token only) A.1.1.8"); + + QTest::newRow("075") << KnownOid::ID_PT << QByteArray::fromHex("04007F0007020208") << QByteArray("0.4.0.127.0.7.2.2.8") << QByteArray("id-PT") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PrivilegedTerminalInfo (eIDAS token only) A.1.1.9"); + + QTest::newRow("076") << KnownOid::ID_PS << QByteArray::fromHex("04007F000702020B") << QByteArray("0.4.0.127.0.7.2.2.11") << QByteArray("id-PS") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11"); + QTest::newRow("077") << KnownOid::ID_PSA << QByteArray::fromHex("04007F000702020B01") << QByteArray("0.4.0.127.0.7.2.2.11.1") << QByteArray("id-PSA") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1"); + QTest::newRow("078") << KnownOid::ID_PSA_ECDH_ECSCHNORR << QByteArray::fromHex("04007F000702020B0102") << QByteArray("0.4.0.127.0.7.2.2.11.1.2") << QByteArray("id-PSA-ECDH-ECSchnorr") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2"); + QTest::newRow("079") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_256 << QByteArray::fromHex("04007F000702020B010203") << QByteArray("0.4.0.127.0.7.2.2.11.1.2.3") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-256") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.3"); + QTest::newRow("080") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_384 << QByteArray::fromHex("04007F000702020B010204") << QByteArray("0.4.0.127.0.7.2.2.11.1.2.4") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-384") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.4"); + QTest::newRow("081") << KnownOid::ID_PSA_ECDH_ECSCHNORR_SHA_512 << QByteArray::fromHex("04007F000702020B010205") << QByteArray("0.4.0.127.0.7.2.2.11.1.2.5") << QByteArray("id-PSA-ECDH-ECSchnorr-SHA-512") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Chip Authentication A.1.1.2 - 11.1.2.5"); + + QTest::newRow("082") << KnownOid::ID_PASSWORDTYPE << QByteArray::fromHex("04007F000702020C") << QByteArray("0.4.0.127.0.7.2.2.12") << QByteArray("id-PasswordType") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12"); + QTest::newRow("083") << KnownOid::ID_PASSWORDTYPE_MRZ << QByteArray::fromHex("04007F000702020C01") << QByteArray("0.4.0.127.0.7.2.2.12.1") << QByteArray("id-PasswordType-MRZ") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.1"); + QTest::newRow("084") << KnownOid::ID_PASSWORDTYPE_CAN << QByteArray::fromHex("04007F000702020C02") << QByteArray("0.4.0.127.0.7.2.2.12.2") << QByteArray("id-PasswordType-CAN") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.2"); + QTest::newRow("085") << KnownOid::ID_PASSWORDTYPE_PIN << QByteArray::fromHex("04007F000702020C03") << QByteArray("0.4.0.127.0.7.2.2.12.3") << QByteArray("id-PasswordType-PIN") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.3"); + QTest::newRow("086") << KnownOid::ID_PASSWORDTYPE_PUK << QByteArray::fromHex("04007F000702020C04") << QByteArray("0.4.0.127.0.7.2.2.12.4") << QByteArray("id-PasswordType-PUK") << QByteArray("BSI TR-03110 Part 3 Version 2.21 PACE A.1.1.1 - 12.4"); + + QTest::newRow("087") << KnownOid::ID_AUXILIARY_DATA << QByteArray::fromHex("04007F0007030104") << QByteArray("0.4.0.127.0.7.3.1.4") << QByteArray("id-AuxiliaryData") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Object Identifier A.7.5.1"); + QTest::newRow("088") << KnownOid::ID_DATE_OF_BIRTH << QByteArray::fromHex("04007F000703010401") << QByteArray("0.4.0.127.0.7.3.1.4.1") << QByteArray("id-DateOfBirth") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Age Verification A.7.5.2"); + QTest::newRow("089") << KnownOid::ID_DATE_OF_EXPIRY << QByteArray::fromHex("04007F000703010402") << QByteArray("0.4.0.127.0.7.3.1.4.2") << QByteArray("id-DateOfExpiry") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Document Validity Verification A.7.5.3"); + QTest::newRow("090") << KnownOid::ID_MUNICIPALITY_ID << QByteArray::fromHex("04007F000703010403") << QByteArray("0.4.0.127.0.7.3.1.4.3") << QByteArray("id-MunicipalityID") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Municipality ID Verification A.7.5.4"); + QTest::newRow("091") << KnownOid::ID_PSM_MESSAGE << QByteArray::fromHex("04007F000703010404") << QByteArray("0.4.0.127.0.7.3.1.4.4") << QByteArray("id-PSM-Message") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Pseudonymous Signature of Messages A.7.5.5"); + + QTest::newRow("092") << KnownOid::ID_SECURITY_OBJECT << QByteArray::fromHex("04007F0007030201") << QByteArray("0.4.0.127.0.7.3.2.1") << QByteArray("id-SecurityObject") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Signature Format for CardSecurity and ChipSecurity A.1.2.5"); + + QTest::newRow("093") << KnownOid::ID_ROLES << QByteArray::fromHex("04007F0007030102") << QByteArray("0.4.0.127.0.7.3.1.2") << QByteArray("id-roles") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Applications and Terminals 2"); + QTest::newRow("094") << KnownOid::ID_IS << QByteArray::fromHex("04007F000703010201") << QByteArray("0.4.0.127.0.7.3.1.2.1") << QByteArray("id-IS") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Authorization 2.1.3.2"); + QTest::newRow("095") << KnownOid::ID_AT << QByteArray::fromHex("04007F000703010202") << QByteArray("0.4.0.127.0.7.3.1.2.2") << QByteArray("id-AT") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Authorization 2.2.3.2"); + QTest::newRow("096") << KnownOid::ID_ST << QByteArray::fromHex("04007F000703010203") << QByteArray("0.4.0.127.0.7.3.1.2.3") << QByteArray("id-ST") << QByteArray("BSI TR-03110 Part 3 Version 2.11 Signature Terminals C.4.3"); + + QTest::newRow("097") << KnownOid::ID_EXTENSIONS << QByteArray::fromHex("04007F0007030103") << QByteArray("0.4.0.127.0.7.3.1.3") << QByteArray("id-extensions") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Certificate Extensions for Terminal Authentication Version 2 C.3"); + QTest::newRow("098") << KnownOid::ID_DESCRIPTION << QByteArray::fromHex("04007F000703010301") << QByteArray("0.4.0.127.0.7.3.1.3.1") << QByteArray("id-description") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Certificate Description Extension 2.2.6"); + QTest::newRow("099") << KnownOid::ID_PLAIN_FORMAT << QByteArray::fromHex("04007F00070301030101") << QByteArray("0.4.0.127.0.7.3.1.3.1.1") << QByteArray("id-plainFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 Plain Text Format 2.2.6.1"); + QTest::newRow("100") << KnownOid::ID_HTML_FORMAT << QByteArray::fromHex("04007F00070301030102") << QByteArray("0.4.0.127.0.7.3.1.3.1.2") << QByteArray("id-htmlFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 HTML Format 2.2.6.2"); + QTest::newRow("101") << KnownOid::ID_PFD_FORMAT << QByteArray::fromHex("04007F00070301030103") << QByteArray("0.4.0.127.0.7.3.1.3.1.3") << QByteArray("id-pdfFormat") << QByteArray("BSI TR-03110 Part 4 Version 2.21 PDF Format 2.2.6.3"); + QTest::newRow("102") << KnownOid::ID_SECTOR_RI << QByteArray::fromHex("04007F000703010302") << QByteArray("0.4.0.127.0.7.3.1.3.2") << QByteArray("id-sector-ri") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Restricted Identification C.3.2.1"); + QTest::newRow("103") << KnownOid::ID_SECTOR_PS << QByteArray::fromHex("04007F000703010303") << QByteArray("0.4.0.127.0.7.3.1.3.3") << QByteArray("id-sector-ps") << QByteArray("BSI TR-03110 Part 3 Version 2.21 Terminal Sector for Pseudonymous Signatures C.3.2.2"); + + QTest::newRow("104") << KnownOid::ID_EID_TYPE << QByteArray::fromHex("04007F0007030203") << QByteArray("0.4.0.127.0.7.3.2.3") << QByteArray("id-eIDType") << QByteArray("Draft Smart-eID"); + QTest::newRow("105") << KnownOid::ID_CARD_EID_TYPE << QByteArray::fromHex("04007F000703020301") << QByteArray("0.4.0.127.0.7.3.2.3.1") << QByteArray("id-cardEIDType") << QByteArray("Draft Smart-eID - 1"); + QTest::newRow("106") << KnownOid::ID_MOBILE_EID_TYPE << QByteArray::fromHex("04007F000703020302") << QByteArray("0.4.0.127.0.7.3.2.3.2") << QByteArray("id-mobileEIDType") << QByteArray("Draft Smart-eID - 2"); + QTest::newRow("107") << KnownOid::ID_MOBILE_EID_TYPE_SE_CERTIFIED << QByteArray::fromHex("04007F00070302030201") << QByteArray("0.4.0.127.0.7.3.2.3.2.1") << QByteArray("id-mobileEIDType-SECertified") << QByteArray("Draft Smart-eID - 2.1"); + QTest::newRow("108") << KnownOid::ID_MOBILE_EID_TYPE_SE_ENDORSED << QByteArray::fromHex("04007F00070302030202") << QByteArray("0.4.0.127.0.7.3.2.3.2.2") << QByteArray("id-mobileEIDType-SEEndorsed") << QByteArray("Draft Smart-eID - 2.2"); + QTest::newRow("109") << KnownOid::ID_MOBILE_EID_TYPE_HW_KEYSTORE << QByteArray::fromHex("04007F00070302030203") << QByteArray("0.4.0.127.0.7.3.2.3.2.3") << QByteArray("id-mobileEIDType-HWKeyStore") << QByteArray("Draft Smart-eID - 2.3"); mTestAllKnownOids = true; } @@ -339,6 +343,7 @@ class test_Oid void knownOids() { QFETCH(KnownOid, knownOid); + QFETCH(QByteArray, bin); QFETCH(QByteArray, oid); QFETCH(QByteArray, sn); QFETCH(QByteArray, ln); @@ -364,17 +369,12 @@ class test_Oid Oid oidfromObject(objectFromOid); Oid oidFromEnum(knownOid); - Oid oidFromOid(oid); - Oid oidFromSn(sn); - Oid oidFromLn(ln); + Oid oidFromBin = Oid(bin); QVERIFY(oidfromObject == oidFromEnum); - QVERIFY(oidfromObject == oidFromOid); - QVERIFY(oidfromObject == oidFromSn); - QVERIFY(oidfromObject == oidFromLn); + QVERIFY(oidfromObject == oidFromBin); - QVERIFY(oidFromEnum.getData().size() > 0); - QVERIFY(oidFromEnum.operator QByteArray().size() > 0); + QCOMPARE(QByteArray(oidFromEnum), bin); QVERIFY(logSpy.count() == 0); @@ -384,21 +384,21 @@ class test_Oid void logging() { - QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Invalid NID, was not able to create a valid OID for: 9999999$")); + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Invalid NID, was not able to create a valid OID for: 9999999$"_L1)); Oid invalidNid(static_cast(9999999)); - QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Copying failed, was not able to create a valid OID$")); + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Copying failed, was not able to create a valid OID$"_L1)); Oid nullObject(nullptr); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Unknown OID: 1.2.3.4.5.6$")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Unknown OID: 1.2.3.4.5.6$"_L1)); ASN1_OBJECT* obj = OBJ_txt2obj("1.2.3.4.5.6", 0); Oid undefined1(obj); ASN1_OBJECT_free(obj); - QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Invalid text input, was not able to create a valid OID for: \"invalid\"$")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Unknown OID: 2.25.110.118.97.108.105.100$"_L1)); Oid invalid(QByteArray("invalid")); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Unknown OID: 1.2.3.4.5.6$")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Unknown OID: 1.9.46.50.46.51.46.52.46.53.46.54$"_L1)); Oid undefined2(QByteArray("1.2.3.4.5.6")); } diff --git a/test/qt/card/asn1/test_PaceInfo.cpp b/test/qt/card/asn1/test_PaceInfo.cpp index 64107015b..002b773fc 100644 --- a/test/qt/card/asn1/test_PaceInfo.cpp +++ b/test/qt/card/asn1/test_PaceInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_SecurityInfo.cpp b/test/qt/card/asn1/test_SecurityInfo.cpp index cd6ee1e97..e261994ab 100644 --- a/test/qt/card/asn1/test_SecurityInfo.cpp +++ b/test/qt/card/asn1/test_SecurityInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -86,7 +86,7 @@ class test_SecurityInfo QVERIFY(securityInfo != nullptr); QCOMPARE(securityInfo->getOid(), KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128); - QCOMPARE(securityInfo->getOid().getData(), QByteArray::fromHex("04007F00070202040202")); + QCOMPARE(securityInfo->getOid(), Oid(QByteArray::fromHex("04007F00070202040202"))); } diff --git a/test/qt/card/asn1/test_SecurityInfos.cpp b/test/qt/card/asn1/test_SecurityInfos.cpp index 5b4cb3063..30b1c6fb0 100644 --- a/test/qt/card/asn1/test_SecurityInfos.cpp +++ b/test/qt/card/asn1/test_SecurityInfos.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/asn1/test_SignatureChecker.cpp b/test/qt/card/asn1/test_SignatureChecker.cpp index 2ee2ac7b8..a6fd4278e 100644 --- a/test/qt/card/asn1/test_SignatureChecker.cpp +++ b/test/qt/card/asn1/test_SignatureChecker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #include "asn1/ASN1TemplateUtil.h" #include "asn1/CVCertificate.h" +#include "CertificateHelper.h" #include "TestFileHelper.h" #include @@ -22,6 +23,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -30,23 +32,23 @@ class test_SignatureChecker { Q_OBJECT - QVector> cvcs; + QList> cvcs; static QSharedPointer load(const QString& pName) { QByteArray bytes = TestFileHelper::readFile(pName); - return CVCertificate::fromHex(bytes); + return CertificateHelper::fromHex(bytes); } private Q_SLOTS: void init() { cvcs.clear(); - cvcs.append(load(":/card/cvca-DETESTeID00001.hex")); - cvcs.append(load(":/card/cvca-DETESTeID00002_DETESTeID00001.hex")); - cvcs.append(load(":/card/cvca-DETESTeID00004_DETESTeID00002.hex")); - cvcs.append(load(":/card/cvdv-DEDVeIDDPST00035.hex")); - cvcs.append(load(":/card/cvat-DEDEMODEV00038.hex")); + cvcs.append(load(":/card/cvca-DETESTeID00001.hex"_L1)); + cvcs.append(load(":/card/cvca-DETESTeID00002_DETESTeID00001.hex"_L1)); + cvcs.append(load(":/card/cvca-DETESTeID00004_DETESTeID00002.hex"_L1)); + cvcs.append(load(":/card/cvdv-DEDVeIDDPST00035.hex"_L1)); + cvcs.append(load(":/card/cvat-DEDEMODEV00038.hex"_L1)); ERR_clear_error(); } @@ -59,7 +61,7 @@ class test_SignatureChecker void verifyEmptyList() { - QVector> certs; + QList> certs; SignatureChecker checker(certs); QVERIFY(!checker.check()); @@ -68,7 +70,7 @@ class test_SignatureChecker void verifyNotSelfSigned() { - QVector> certs(cvcs); + QList> certs(cvcs); certs.removeAt(0); SignatureChecker checker(certs); @@ -78,7 +80,7 @@ class test_SignatureChecker void verifyNoCertificateWithCurveParameters() { - QVector> certs(cvcs); + QList> certs(cvcs); certs.removeAt(2); certs.removeAt(1); certs.removeAt(0); @@ -90,7 +92,7 @@ class test_SignatureChecker void verifyNoValidChain() { - QVector> certs(cvcs); + QList> certs(cvcs); certs.removeAt(2); SignatureChecker checker(certs); diff --git a/test/qt/card/asn1/test_efCardAccess.cpp b/test/qt/card/asn1/test_efCardAccess.cpp index 36b80fcce..757d4583d 100644 --- a/test/qt/card/asn1/test_efCardAccess.cpp +++ b/test/qt/card/asn1/test_efCardAccess.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TestFileHelper.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_efCardAccess @@ -24,7 +25,7 @@ class test_efCardAccess void parseEFCardAccess() { - QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex")); + QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex"_L1)); auto efCardAccess = EFCardAccess::decode(bytes); diff --git a/test/qt/card/asn1/test_efCardSecurity.cpp b/test/qt/card/asn1/test_efCardSecurity.cpp index 971b6ebcf..e90af776e 100644 --- a/test/qt/card/asn1/test_efCardSecurity.cpp +++ b/test/qt/card/asn1/test_efCardSecurity.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ #include "TestFileHelper.h" @@ -11,6 +11,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -139,8 +140,9 @@ class test_efCardSecurity void parseEFCardSecurity_data() { QTest::addColumn("bytes"); + QTest::addColumn("logging"); - QTest::newRow("file") << QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardSecurity.hex")); + QTest::newRow("file") << QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardSecurity.hex"_L1)) << QByteArray("Parsed EFCardSecurity signed with DocSigner: \"0021\""); QSharedPointer keyCtx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &EVP_PKEY_CTX_free); QVERIFY(keyCtx); @@ -218,14 +220,16 @@ class test_efCardSecurity const int contentSize = i2d_CMS_ContentInfo(cms.data(), &rawContent); const auto contentGuard = qScopeGuard([rawContent] {OPENSSL_free(rawContent);}); - QTest::newRow("constructed") << QByteArray(reinterpret_cast(rawContent), contentSize); + QTest::newRow("constructed") << QByteArray(reinterpret_cast(rawContent), contentSize) << QByteArray("Parsed EFCardSecurity signed with DocSigner: \"\""); } void parseEFCardSecurity() { QFETCH(QByteArray, bytes); + QFETCH(QByteArray, logging); + QTest::ignoreMessage(QtDebugMsg, logging.data()); auto efCardSecurity = EFCardSecurity::decode(bytes); QVERIFY(efCardSecurity); QCOMPARE(efCardSecurity->getSecurityInfos()->getSecurityInfos().size(), 9); @@ -243,6 +247,7 @@ class test_efCardSecurity QTest::ignoreMessage(QtDebugMsg, "Parsed SecurityInfo: 0.4.0.127.0.7.2.2.5.2 (id-RI-ECDH)"); QTest::ignoreMessage(QtDebugMsg, "Parsed SecurityInfo: 0.4.0.127.0.7.2.2.3.2 (id-CA-ECDH)"); QTest::ignoreMessage(QtDebugMsg, "Parsed SecurityInfo: 0.4.0.127.0.7.2.2.1.2 (id-PK-ECDH)"); + QTest::ignoreMessage(QtDebugMsg, "Parsed EFCardSecurity signed with DocSigner: \"0001\""); QVERIFY(EFCardSecurity::fromHex(QByteArray( "3082072f06092a864886f70d010702a08207203082071c020103310f300d060960864801650304020205003082012c06" diff --git a/test/qt/card/base/apdu/test_CommandApdu.cpp b/test/qt/card/base/apdu/test_CommandApdu.cpp index 958eaf06c..891fd434c 100644 --- a/test/qt/card/base/apdu/test_CommandApdu.cpp +++ b/test/qt/card/base/apdu/test_CommandApdu.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_CommandApdu @@ -108,19 +109,19 @@ class test_CommandApdu void test_Ins_unknown_data() { QTest::addColumn("header"); - QTest::addColumn("logMsg"); + QTest::addColumn("logMsg"); - QTest::newRow("00") << QByteArray("00000000") << QString("Unknown INS value, returning UNKNOWN, value: 0x0"); - QTest::newRow("42") << QByteArray("00420000") << QString("Unknown INS value, returning UNKNOWN, value: 0x42"); - QTest::newRow("AA") << QByteArray("00AA0000") << QString("Unknown INS value, returning UNKNOWN, value: 0xaa"); - QTest::newRow("FF") << QByteArray("00FF0000") << QString("Unknown INS value, returning UNKNOWN, value: 0xff"); + QTest::newRow("00") << "00000000"_ba << "Unknown INS value, returning UNKNOWN, value: 0x0"_L1; + QTest::newRow("42") << "00420000"_ba << "Unknown INS value, returning UNKNOWN, value: 0x42"_L1; + QTest::newRow("AA") << "00AA0000"_ba << "Unknown INS value, returning UNKNOWN, value: 0xaa"_L1; + QTest::newRow("FF") << "00FF0000"_ba << "Unknown INS value, returning UNKNOWN, value: 0xff"_L1; } void test_Ins_unknown() { QFETCH(QByteArray, header); - QFETCH(QString, logMsg); + QFETCH(QLatin1String, logMsg); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); @@ -215,39 +216,39 @@ class test_CommandApdu CommandApdu apdu1(QByteArray("aicd"), QByteArray(65536, 'w'), 1); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Command data exceeds maximum of 0xffff")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Command data exceeds maximum of 0xffff"_L1)); CommandApdu apdu2(QByteArray("aicd"), QByteArray("abc"), 65537); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Expected length exceeds maximum value of 0x10000")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Expected length exceeds maximum value of 0x10000"_L1)); } void test_Invalid_data() { QTest::addColumn("data"); - QTest::addColumn("logMessage"); + QTest::addColumn("logMessage"); - QTest::newRow("incomplete header 1") << QByteArray::fromHex("00") << QString("Wrong command header size!"); - QTest::newRow("incomplete header 2") << QByteArray::fromHex("0000") << QString("Wrong command header size!"); - QTest::newRow("incomplete header 3") << QByteArray::fromHex("000000") << QString("Wrong command header size!"); + QTest::newRow("incomplete header 1") << QByteArray::fromHex("00") << "Wrong command header size!"_L1; + QTest::newRow("incomplete header 2") << QByteArray::fromHex("0000") << "Wrong command header size!"_L1; + QTest::newRow("incomplete header 3") << QByteArray::fromHex("000000") << "Wrong command header size!"_L1; - QTest::newRow("unexpected end - short lc - incomplete data") << QByteArray::fromHex("00000000 02 00") << QString("Unexpected end of data"); - QTest::newRow("unexpected end - extended le - incomplete le") << QByteArray::fromHex("00000000 0000") << QString("Unexpected end of data"); - QTest::newRow("unexpected end - extended lc - incomplete data") << QByteArray::fromHex("00000000 000002 00") << QString("Unexpected end of data"); + QTest::newRow("unexpected end - short lc - incomplete data") << QByteArray::fromHex("00000000 02 00") << "Unexpected end of data"_L1; + QTest::newRow("unexpected end - extended le - incomplete le") << QByteArray::fromHex("00000000 0000") << "Unexpected end of data"_L1; + QTest::newRow("unexpected end - extended lc - incomplete data") << QByteArray::fromHex("00000000 000002 00") << "Unexpected end of data"_L1; - QTest::newRow("mixed extended / short length") << QByteArray::fromHex("00000000 00000100 00") << QString("Extended length expected"); + QTest::newRow("mixed extended / short length") << QByteArray::fromHex("00000000 00000100 00") << "Extended length expected"_L1; - QTest::newRow("mixed short / extended length") << QByteArray::fromHex("00000000 0100 0000") << QString("Unexpected additional data: \"00\""); - QTest::newRow("unexpected additional data - short") << QByteArray::fromHex("00000000 0100 00 00") << QString("Unexpected additional data: \"00\""); - QTest::newRow("unexpected additional data - extended") << QByteArray::fromHex("00000000 00000100 0000 00") << QString("Unexpected additional data: \"00\""); + QTest::newRow("mixed short / extended length") << QByteArray::fromHex("00000000 0100 0000") << "Unexpected additional data: \"00\""_L1; + QTest::newRow("unexpected additional data - short") << QByteArray::fromHex("00000000 0100 00 00") << "Unexpected additional data: \"00\""_L1; + QTest::newRow("unexpected additional data - extended") << QByteArray::fromHex("00000000 00000100 0000 00") << "Unexpected additional data: \"00\""_L1; } void test_Invalid() { QFETCH(QByteArray, data); - QFETCH(QString, logMessage); + QFETCH(QLatin1String, logMessage); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); @@ -289,6 +290,12 @@ class test_CommandApdu QTest::newRow("3E 256 0") << 256 << 0 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42); QTest::newRow("3E 65535 0") << 65535 << 0 << true << QByteArray::fromHex("0102030400FFFF") + QByteArray(65535, 0x42); + QTest::newRow("4E 255 257") << 255 << 257 << true << QByteArray::fromHex("010203040000FF") + QByteArray(255, 0x42) + QByteArray::fromHex("0101"); + QTest::newRow("4E 255 65535") << 255 << 65535 << true << QByteArray::fromHex("010203040000FF") + QByteArray(255, 0x42) + QByteArray::fromHex("FFFF"); + QTest::newRow("4E 255 65536") << 255 << 65536 << true << QByteArray::fromHex("010203040000FF") + QByteArray(255, 0x42) + QByteArray::fromHex("0000"); + QTest::newRow("4E 256 1") << 256 << 1 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("0001"); + QTest::newRow("4E 256 255") << 256 << 255 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("00FF"); + QTest::newRow("4E 256 256") << 256 << 256 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("0100"); QTest::newRow("4E 256 257") << 256 << 257 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("0101"); QTest::newRow("4E 256 65535") << 256 << 65535 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("FFFF"); QTest::newRow("4E 256 65536") << 256 << 65536 << true << QByteArray::fromHex("01020304000100") + QByteArray(256, 0x42) + QByteArray::fromHex("0000"); @@ -324,6 +331,20 @@ class test_CommandApdu } + void test_logging() + { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + qDebug() << CommandApdu(QByteArray::fromHex("01020304")); + QCOMPARE(logSpy.count(), 1); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("01020304"_L1)); + + qDebug() << CommandApdu(QByteArray::fromHex("0cb0890000000e970200008e08b4332dac29510ece0000")); + QCOMPARE(logSpy.count(), 1); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("\"0cb0890000~0000\" (23)"_L1)); + } + + }; QTEST_GUILESS_MAIN(test_CommandApdu) diff --git a/test/qt/card/base/apdu/test_FileCommand.cpp b/test/qt/card/base/apdu/test_FileCommand.cpp index bd1ec3cb8..3f9ef7f50 100644 --- a/test/qt/card/base/apdu/test_FileCommand.cpp +++ b/test/qt/card/base/apdu/test_FileCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/base/apdu/test_GeneralAuthenticateResponse.cpp b/test/qt/card/base/apdu/test_GeneralAuthenticateResponse.cpp index cc87b44b9..89326b984 100644 --- a/test/qt/card/base/apdu/test_GeneralAuthenticateResponse.cpp +++ b/test/qt/card/base/apdu/test_GeneralAuthenticateResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/base/apdu/test_PacePinStatus.cpp b/test/qt/card/base/apdu/test_PacePinStatus.cpp index 01af57260..801dbaa1b 100644 --- a/test/qt/card/base/apdu/test_PacePinStatus.cpp +++ b/test/qt/card/base/apdu/test_PacePinStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "apdu/PacePinStatus.h" @@ -15,7 +15,7 @@ class test_PacePinStatus private: bool mTestAllKnownStatusCode; - QVector mStatusCodeToTest; + QList mStatusCodeToTest; private Q_SLOTS: void cleanupTestCase() @@ -56,6 +56,7 @@ class test_PacePinStatus QTest::newRow("NO_CURRENT_DIRECTORY_SELECTED") << StatusCode::NO_CURRENT_DIRECTORY_SELECTED << -1 << false << false; QTest::newRow("DATAFIELD_EXPECTED") << StatusCode::DATAFIELD_EXPECTED << -1 << false << false; QTest::newRow("INVALID_SM_OBJECTS") << StatusCode::INVALID_SM_OBJECTS << -1 << false << false; + QTest::newRow("SW_APPLET_SELECT_FAILED") << StatusCode::SW_APPLET_SELECT_FAILED << -1 << false << false; QTest::newRow("COMMAND_NOT_ALLOWED") << StatusCode::COMMAND_NOT_ALLOWED << -1 << false << false; QTest::newRow("INVALID_DATAFIELD") << StatusCode::INVALID_DATAFIELD << -1 << false << false; QTest::newRow("ALGORITHM_ID") << StatusCode::ALGORITHM_ID << -1 << false << false; diff --git a/test/qt/card/base/apdu/test_ResponseApdu.cpp b/test/qt/card/base/apdu/test_ResponseApdu.cpp index 892c1954e..624ff5834 100644 --- a/test/qt/card/base/apdu/test_ResponseApdu.cpp +++ b/test/qt/card/base/apdu/test_ResponseApdu.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -23,8 +24,8 @@ class test_ResponseApdu Q_OBJECT private: - bool mTestAllKnownStatusCode; - QVector mStatusCodeToTest; + bool mTestAllKnownStatusCode = false; + QList mStatusCodeToTest = {}; private Q_SLOTS: void initTestCase_data() @@ -114,6 +115,7 @@ class test_ResponseApdu QTest::newRow("NO_CURRENT_DIRECTORY_SELECTED") << StatusCode::NO_CURRENT_DIRECTORY_SELECTED << SW1::ERROR_COMMAND_NOT_ALLOWED << static_cast(0x86); QTest::newRow("DATAFIELD_EXPECTED") << StatusCode::DATAFIELD_EXPECTED << SW1::ERROR_COMMAND_NOT_ALLOWED << static_cast(0x87); QTest::newRow("INVALID_SM_OBJECTS") << StatusCode::INVALID_SM_OBJECTS << SW1::ERROR_COMMAND_NOT_ALLOWED << static_cast(0x88); + QTest::newRow("SW_APPLET_SELECT_FAILED") << StatusCode::SW_APPLET_SELECT_FAILED << SW1::ERROR_COMMAND_NOT_ALLOWED << static_cast(0x99); QTest::newRow("COMMAND_NOT_ALLOWED") << StatusCode::COMMAND_NOT_ALLOWED << SW1::ERROR_COMMAND_NOT_ALLOWED << static_cast(0xF0); QTest::newRow("INVALID_DATAFIELD") << StatusCode::INVALID_DATAFIELD << SW1::WRONG_PARAMETERS_P1_P2 << static_cast(0x80); QTest::newRow("ALGORITHM_ID") << StatusCode::ALGORITHM_ID << SW1::WRONG_PARAMETERS_P1_P2 << static_cast(0x81); @@ -241,11 +243,18 @@ class test_ResponseApdu } - public: - test_ResponseApdu() - : mTestAllKnownStatusCode(false) - , mStatusCodeToTest() + + void test_logging() { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + qDebug() << ResponseApdu(StatusCode::ACCESS_DENIED); + QCOMPARE(logSpy.count(), 1); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("6982"_L1)); + + qDebug() << ResponseApdu(StatusCode::SUCCESS, QByteArray::fromHex("010203040506070809")); + QCOMPARE(logSpy.count(), 1); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("\"0102030405~9000\" (11)"_L1)); } diff --git a/test/qt/card/base/apdu/test_SecureMessaging.cpp b/test/qt/card/base/apdu/test_SecureMessaging.cpp index 630814f36..644d5a3da 100644 --- a/test/qt/card/base/apdu/test_SecureMessaging.cpp +++ b/test/qt/card/base/apdu/test_SecureMessaging.cpp @@ -1,11 +1,13 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/SecureMessaging.h" #include "LogHandler.h" #include "SecurityProtocol.h" +#include "apdu/SecureMessagingCommand.h" +#include "asn1/ASN1Util.h" #include #include @@ -40,9 +42,9 @@ class test_SecureMessaging QScopedPointer mCipher; - QVector encryptResponse(const QByteArray& pBuffer, quint32& pSsc) const + QList encryptResponse(const QByteArray& pBuffer, quint32& pSsc) const { - QVector result(4); + QList result(4); ++pSsc; QByteArray ssc = QByteArray(mCipher->getBlockSize() - QByteArray::number(pSsc, 16).size(), 0x00).append(ByteArrayUtil::fromValue(pSsc)); @@ -170,6 +172,31 @@ class test_SecureMessaging } + void testExtendedLengthAfterEcryption() + { + const QByteArray data(250, 0x42); + const CommandApdu command(Ins::MSE_SET, 0x20, 0x30, data, 24); + QCOMPARE(command, QByteArray::fromHex("00222030 fa") + data + QByteArray::fromHex("18")); + + const auto& encryptedCommand = mSecureMessagingTerminal->encrypt(command); + QCOMPARE(encryptedCommand, + QByteArray::fromHex("0c222030 000112" + "87820101 01" + "257c4674cfae012dd0da1d7ae3901cb0acd1789c30d31d6934092bc9db9f01dd7b7d17215a69f02fe4c24e7ad4019113" + "05984da2c4ceca18f41e0e1f55b4bc5d69fa55d73e9eb5c018b6f9edcb07cf171973d5d8612ffc20326e997083592d31" + "c0934f2c28d466535d6f4a024cf7068aa44daad8501a228b5dcba0766c6771b5761085d3f19801f92875b10cf17175f7" + "ec1714e7a9a99714386e518059360910e6d3a6f54111e5aa983f5cdf2d5f5597fc0f1387ab70a06b922fa45cc1d42bbe" + "9f831235d88edd78a14ca9d9abcd02d799161ddc8c231078303d1062b875eaa899a44824ed25e4673706f9d0063872fd" + "6dabca6f1fb03e4d4c1a68dd4c6d7488" + "970118" + "8e08543fdc3e1ff32dfb" + "0000")); + + const auto& decryptedcommand = mSecureMessagingCard->decrypt(encryptedCommand); + QCOMPARE(decryptedcommand, command); + } + + void testSendSequenceCounter() { QByteArray data = QByteArray::fromHex("D0D1D2D3"); @@ -327,6 +354,12 @@ class test_SecureMessaging QTest::newRow("3E 256 0") << 256 << 0; QTest::newRow("3E 65519 0") << 65519 << 0; + QTest::newRow("4E 255 257") << 255 << 257; + QTest::newRow("4E 255 65535") << 255 << 65535; + QTest::newRow("4E 255 65536") << 255 << 65536; + QTest::newRow("4E 256 1") << 256 << 1; + QTest::newRow("4E 256 255") << 256 << 255; + QTest::newRow("4E 256 256") << 256 << 256; QTest::newRow("4E 256 257") << 256 << 257; QTest::newRow("4E 256 65535") << 256 << 65535; QTest::newRow("4E 256 65536") << 256 << 65536; @@ -345,8 +378,13 @@ class test_SecureMessaging QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); const QByteArray data(lc, 0x42); - CommandApdu apdu(QByteArray::fromHex("00010203"), data, le); - QCOMPARE(mSecureMessagingCard->decrypt(mSecureMessagingTerminal->encrypt(apdu)), apdu); + const CommandApdu apdu(QByteArray::fromHex("00010203"), data, le); + const CommandApdu encryptedApdu = mSecureMessagingTerminal->encrypt(apdu); + + SecureMessagingCommand smCmd(encryptedApdu); + QCOMPARE(Asn1OctetStringUtil::getValue(smCmd.mExpectedLength.data()).size(), le > 0 ? CommandApdu::isExtendedLength(data, le) ? 2 : 1 : 0); + + QCOMPARE(mSecureMessagingCard->decrypt(encryptedApdu), apdu); QCOMPARE(logSpy.count(), 0); Env::getSingleton()->reset(); diff --git a/test/qt/card/base/apdu/test_SecureMessagingCommand.cpp b/test/qt/card/base/apdu/test_SecureMessagingCommand.cpp index 2cc6b2081..def1e0919 100644 --- a/test/qt/card/base/apdu/test_SecureMessagingCommand.cpp +++ b/test/qt/card/base/apdu/test_SecureMessagingCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -45,7 +46,7 @@ class test_SecureMessagingCommand QCOMPARE(command.getMac(), QByteArray()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt")); + QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt"_L1)); } @@ -77,11 +78,11 @@ class test_SecureMessagingCommand QCOMPARE(logSpy.count(), 1); if (input.getData().isEmpty()) { - QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt")); + QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt"_L1)); } else { - QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding mac")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding mac"_L1)); } } @@ -94,7 +95,7 @@ class test_SecureMessagingCommand QVERIFY(!command.isValid()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding encrypted data")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding encrypted data"_L1)); } @@ -126,11 +127,11 @@ class test_SecureMessagingCommand QCOMPARE(logSpy.count(), 1); if (input.getData().isEmpty()) { - QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt")); + QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt"_L1)); } else { - QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding mac")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Error on decoding mac"_L1)); } } diff --git a/test/qt/card/base/apdu/test_SecureMessagingResponse.cpp b/test/qt/card/base/apdu/test_SecureMessagingResponse.cpp index bec4fa83a..5077a362e 100644 --- a/test/qt/card/base/apdu/test_SecureMessagingResponse.cpp +++ b/test/qt/card/base/apdu/test_SecureMessagingResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,6 +15,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -49,7 +50,7 @@ class test_SecureMessagingResponse QCOMPARE(response.getSecuredStatusCodeObjectEncoded(), QByteArray()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt")); + QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt"_L1)); } @@ -69,7 +70,7 @@ class test_SecureMessagingResponse QCOMPARE(response.getSecuredStatusCodeObjectEncoded(), QByteArray()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt")); + QVERIFY(logSpy.at(0).at(0).toString().contains("No data to decrypt"_L1)); } diff --git a/test/qt/card/base/command/test_BaseCardCommand.cpp b/test/qt/card/base/command/test_BaseCardCommand.cpp index 6e66a1e67..bace27c17 100644 --- a/test/qt/card/base/command/test_BaseCardCommand.cpp +++ b/test/qt/card/base/command/test_BaseCardCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class BaseCardCommandDummy @@ -56,7 +57,7 @@ class test_BaseCardCommand void commandDone() { - MockReader reader("dummy reader"); + MockReader reader("dummy reader"_L1); BaseCardCommandDummy command(&reader); QCOMPARE(command.getReturnCode(), CardReturnCode::UNKNOWN); diff --git a/test/qt/card/base/command/test_DestroyPaceChannelCommand.cpp b/test/qt/card/base/command/test_DestroyPaceChannelCommand.cpp index 879868bef..4005263e2 100644 --- a/test/qt/card/base/command/test_DestroyPaceChannelCommand.cpp +++ b/test/qt/card/base/command/test_DestroyPaceChannelCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/DestroyPaceChannelCommand.h" @@ -23,13 +23,13 @@ class test_DestroyPaceChannelCommand { QSharedPointer worker1(new MockCardConnectionWorker()); worker1->addPaceCode(CardReturnCode::OK); - DestroyPaceChannelCommand command1(worker1); + DestroyPaceChannelCommand command1(worker1, QStringLiteral("slotname")); command1.internalExecute(); QCOMPARE(command1.getReturnCode(), CardReturnCode::OK); QSharedPointer worker2(new MockCardConnectionWorker()); worker2->addPaceCode(CardReturnCode::UNKNOWN); - DestroyPaceChannelCommand command2(worker2); + DestroyPaceChannelCommand command2(worker2, QStringLiteral("slotname")); command2.internalExecute(); QCOMPARE(command2.getReturnCode(), CardReturnCode::UNKNOWN); } diff --git a/test/qt/card/base/command/test_DidAuthenticateEAC1Command.cpp b/test/qt/card/base/command/test_DidAuthenticateEAC1Command.cpp index b95bf3bc4..e3a4932b5 100644 --- a/test/qt/card/base/command/test_DidAuthenticateEAC1Command.cpp +++ b/test/qt/card/base/command/test_DidAuthenticateEAC1Command.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/DidAuthenticateEAC1Command.h" @@ -11,6 +11,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -45,7 +46,7 @@ class test_DidAuthenticateEAC1Command QCOMPARE(response.getStatusCode(), StatusCode::SUCCESS); QCOMPARE(command.getChallenge(), QByteArray()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Challenge has wrong size. Expect 8 bytes, got")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Challenge has wrong size. Expect 8 bytes, got"_L1)); } @@ -76,7 +77,7 @@ class test_DidAuthenticateEAC1Command QCOMPARE(response1.getStatusCode(), StatusCode::PIN_BLOCKED); QCOMPARE(command1.getChallenge(), QByteArray()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("GetChallenge failed")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("GetChallenge failed"_L1)); ResponseApdu response2(QByteArray::fromHex("19191919191919")); worker->addResponse(CardReturnCode::PROTOCOL_ERROR, response2); @@ -86,7 +87,7 @@ class test_DidAuthenticateEAC1Command QCOMPARE(response2.getStatusCode(), StatusCode::UNKNOWN); QCOMPARE(command2.getChallenge(), QByteArray()); QCOMPARE(logSpy.count(), 3); - QVERIFY(logSpy.at(1).at(0).toString().contains("GetChallenge failed")); + QVERIFY(logSpy.at(1).at(0).toString().contains("GetChallenge failed"_L1)); } diff --git a/test/qt/card/base/command/test_DidAuthenticateEAC2Command.cpp b/test/qt/card/base/command/test_DidAuthenticateEAC2Command.cpp index bc8eab2b8..61944d0b2 100644 --- a/test/qt/card/base/command/test_DidAuthenticateEAC2Command.cpp +++ b/test/qt/card/base/command/test_DidAuthenticateEAC2Command.cpp @@ -1,14 +1,16 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "command/DidAuthenticateEAC2Command.h" +#include "asn1/ASN1Struct.h" +#include "asn1/ASN1Util.h" #include "asn1/CVCertificateChainBuilder.h" +#include "CertificateHelper.h" #include "MockCardConnectionWorker.h" #include "TestFileHelper.h" -#include "asn1/ASN1Util.h" #include #include @@ -16,7 +18,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -32,20 +34,20 @@ class test_DidAuthenticateEAC2Command static QByteArray readFile(const QString& pFileName) { - return TestFileHelper::readFile(QString(":/card/").append(pFileName)); + return TestFileHelper::readFile(QStringLiteral(":/card/").append(pFileName)); } static CVCertificateChain createCVCertificateChain() { - QVector> list; - list << CVCertificate::fromHex(readFile("cvca-DETESTeID00001.hex")); - list << CVCertificate::fromHex(readFile("cvca-DETESTeID00002_DETESTeID00001.hex")); - list << CVCertificate::fromHex(readFile("cvca-DETESTeID00002.hex")); - list << CVCertificate::fromHex(readFile("cvca-DETESTeID00004_DETESTeID00002.hex")); - list << CVCertificate::fromHex(readFile("cvca-DETESTeID00004.hex")); - list << CVCertificate::fromHex(readFile("cvdv-DEDVeIDDPST00035.hex")); - list << CVCertificate::fromHex(readFile("cvat-DEDEMODEV00038.hex")); + QList> list; + list << CertificateHelper::fromHex(readFile("cvca-DETESTeID00001.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvca-DETESTeID00002_DETESTeID00001.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvca-DETESTeID00002.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvca-DETESTeID00004_DETESTeID00002.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvca-DETESTeID00004.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvdv-DEDVeIDDPST00035.hex"_L1)); + list << CertificateHelper::fromHex(readFile("cvat-DEDEMODEV00038.hex"_L1)); CVCertificateChainBuilder builder(list, false); return builder.getChainStartingWith(list.first()); } @@ -53,7 +55,7 @@ class test_DidAuthenticateEAC2Command QByteArray generateEfCardSecurity(const QByteArrayList& pSecurityInfos) { - const auto& data = Asn1Util::encode(V_ASN1_UNIVERSAL, 17, pSecurityInfos.join(), true); + const auto& data = Asn1Util::encode(V_ASN1_UNIVERSAL, ASN1Struct::UNI_SET, pSecurityInfos.join(), true); QSharedPointer bio(BIO_new(BIO_s_mem()), &BIO_free); BIO_write(bio.data(), data.data(), static_cast(data.size())); @@ -231,7 +233,7 @@ class test_DidAuthenticateEAC2Command const CVCertificateChain cvcChain = createCVCertificateChain(); const QByteArray auxData = QByteArray::fromHex("670F0102030405060708090A0B0C0D0E0F"); - DidAuthenticateEAC2Command command(mWorker, cvcChain, QByteArray(), QByteArray(), auxData, QByteArray()); + DidAuthenticateEAC2Command command(mWorker, cvcChain, QByteArray("040506"), QByteArray(), auxData, QByteArray()); mWorker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); // Performing TA MSE:Set DST with CAR "DETESTeID00001" mWorker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); // Performing TA PSO:Verify Certificate with CVC(type=CVCA, car="DETESTeID00001", chr="DETESTeID00001", valid=["2010-08-13","2013-08-13"]=false) @@ -259,7 +261,7 @@ class test_DidAuthenticateEAC2Command } else if (error == 2) { - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Cannot decode ASN.1 object: .*")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Cannot decode ASN.1 object: .*"_L1)); QTest::ignoreMessage(QtCriticalMsg, "No contentInfo"); QTest::ignoreMessage(QtCriticalMsg, "Cannot parse EF.CardSecurity"); } diff --git a/test/qt/card/base/command/test_EstablishPaceChannelCommand.cpp b/test/qt/card/base/command/test_EstablishPaceChannelCommand.cpp index 03eeb2efa..be587bf85 100644 --- a/test/qt/card/base/command/test_EstablishPaceChannelCommand.cpp +++ b/test/qt/card/base/command/test_EstablishPaceChannelCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/EstablishPaceChannelCommand.h" @@ -49,7 +49,7 @@ class test_EstablishPaceChannelCommand void test_InternalExecute() { MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 0, true, true); + CardInfo info(CardType::EID_CARD, FileRef(), QSharedPointer(), 0, true, true); reader.setInfoCardInfo(info); QSharedPointer worker(new MockCardConnectionWorker(&reader)); @@ -104,7 +104,7 @@ class test_EstablishPaceChannelCommand void test_InternalExecutePinNotBlocked() { MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 0, true, true); + CardInfo info(CardType::EID_CARD, FileRef(), QSharedPointer(), 0, true, true); reader.setInfoCardInfo(info); QSharedPointer worker(new MockCardConnectionWorker(&reader)); @@ -118,7 +118,7 @@ class test_EstablishPaceChannelCommand void test_InternalExecuteProtocolError() { MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 0, false, true); + CardInfo info(CardType::EID_CARD, FileRef(), QSharedPointer(), 0, false, true); reader.setInfoCardInfo(info); QSharedPointer worker(new MockCardConnectionWorker(&reader)); @@ -133,7 +133,7 @@ class test_EstablishPaceChannelCommand void test_InternalExecuteOK() { MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 0, false, true); + CardInfo info(CardType::EID_CARD, FileRef(), QSharedPointer(), 0, false, true); reader.setInfoCardInfo(info); QSharedPointer worker(new MockCardConnectionWorker(&reader)); @@ -146,23 +146,6 @@ class test_EstablishPaceChannelCommand } - void test_InternalExecutePukInoperative() - { - MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 0, false, true); - reader.setInfoCardInfo(info); - QSharedPointer worker(new MockCardConnectionWorker(&reader)); - - worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("6900")); - worker->addPaceCode(CardReturnCode::OK); - const QByteArray puk("00000000000"); - EstablishPaceChannelCommand command(worker, PacePasswordId::PACE_PUK, puk, nullptr, nullptr); - command.internalExecute(); - QCOMPARE(command.getReturnCode(), CardReturnCode::PUK_INOPERATIVE); - QVERIFY(worker->getReaderInfo().getCardInfo().isPukInoperative()); - } - - }; QTEST_GUILESS_MAIN(test_EstablishPaceChannelCommand) diff --git a/test/qt/card/base/command/test_ResetRetryCounterCommand.cpp b/test/qt/card/base/command/test_ResetRetryCounterCommand.cpp new file mode 100644 index 000000000..c3c72bc4e --- /dev/null +++ b/test/qt/card/base/command/test_ResetRetryCounterCommand.cpp @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "command/ResetRetryCounterCommand.h" + +#include "MockCardConnectionWorker.h" + +#include +#include +#include + + +using namespace governikus; + + +class test_ResetRetryCounterCommand + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void test_InternalExecute_data() + { + QTest::addColumn("sw1"); + QTest::addColumn("returnCode"); + + QTest::addRow("PUK inoperative") << SW1::ERROR_COMMAND_NOT_ALLOWED << CardReturnCode::PUK_INOPERATIVE; + QTest::addRow("Reset success") << SW1::SUCCESS << CardReturnCode::OK; + } + + + void test_InternalExecute() + { + QFETCH(SW1, sw1); + QFETCH(CardReturnCode, returnCode); + + QSharedPointer worker(new MockCardConnectionWorker()); + QByteArray buffer; + buffer += static_cast(sw1); + buffer += static_cast(0x00); // SW2 - Does not matter for this test + worker->addResponse(CardReturnCode::OK, buffer); + + ResetRetryCounterCommand command(worker); + command.internalExecute(); + + QCOMPARE(command.getReturnCode(), returnCode); + } + + +}; + +QTEST_GUILESS_MAIN(test_ResetRetryCounterCommand) +#include "test_ResetRetryCounterCommand.moc" diff --git a/test/qt/card/base/command/test_SetEidPinCommand.cpp b/test/qt/card/base/command/test_SetEidPinCommand.cpp index 9c6017c33..4ae63b3f6 100644 --- a/test/qt/card/base/command/test_SetEidPinCommand.cpp +++ b/test/qt/card/base/command/test_SetEidPinCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/SetEidPinCommand.h" @@ -38,6 +38,7 @@ class test_SetEidPinCommand worker->addResponse(CardReturnCode::OK, QByteArray::fromHex(("9000"))); worker->addResponse(CardReturnCode::PROTOCOL_ERROR, QByteArray::fromHex("1919")); worker->addResponse(CardReturnCode::PIN_BLOCKED, QByteArray::fromHex("63C0")); + worker->addResponse(CardReturnCode::COMMAND_FAILED, QByteArray()); const QByteArray pin = QByteArrayLiteral("111111"); SetEidPinCommand command(worker, pin, 8); @@ -56,6 +57,10 @@ class test_SetEidPinCommand command.internalExecute(); QCOMPARE(command.getReturnCode(), CardReturnCode::PIN_BLOCKED); QCOMPARE(command.getResponseApdu(), QByteArray::fromHex("63C0")); + + command.internalExecute(); + QCOMPARE(command.getReturnCode(), CardReturnCode::RESPONSE_EMPTY); + QCOMPARE(command.getResponseApdu(), QByteArray()); } diff --git a/test/qt/card/base/command/test_TransmitCommand.cpp b/test/qt/card/base/command/test_TransmitCommand.cpp index 10dd5b335..028644fac 100644 --- a/test/qt/card/base/command/test_TransmitCommand.cpp +++ b/test/qt/card/base/command/test_TransmitCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/TransmitCommand.h" @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -77,7 +78,7 @@ class test_TransmitCommand void test_InternalExecuteOkSingleCommandWithoutAcceptableStatusCode() { - QVector inputApduInfos(1); + QList inputApduInfos(1); QSharedPointer worker(new MockCardConnectionWorker()); worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); @@ -91,7 +92,7 @@ class test_TransmitCommand void test_InternalExecuteOkSingleCommandWithAcceptableStatusCode() { - QVector inputApduInfos(1); + QList inputApduInfos(1); QSharedPointer worker(new MockCardConnectionWorker()); inputApduInfos[0].addAcceptableStatusCode(QByteArray("90")); @@ -108,7 +109,7 @@ class test_TransmitCommand { QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - QVector inputApduInfos(1); + QList inputApduInfos(1); QSharedPointer worker(new MockCardConnectionWorker()); worker->addResponse(CardReturnCode::PROTOCOL_ERROR, QByteArray::fromHex("1919")); @@ -116,21 +117,21 @@ class test_TransmitCommand command1.internalExecute(); QVERIFY(command1.getOutputApduAsHex().isEmpty()); QCOMPARE(command1.getReturnCode(), CardReturnCode::PROTOCOL_ERROR); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code:")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code:"_L1)); worker->addResponse(CardReturnCode::PIN_BLOCKED, QByteArray::fromHex("63C0")); TransmitCommand command2(worker, inputApduInfos, QStringLiteral("slotname")); command2.internalExecute(); QVERIFY(command2.getOutputApduAsHex().isEmpty()); QCOMPARE(command2.getReturnCode(), CardReturnCode::PIN_BLOCKED); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code:")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code:"_L1)); } void test_InternalExecuteUnexpectedStatusSingleCommand() { QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - QVector inputApduInfos(1); + QList inputApduInfos(1); QSharedPointer worker(new MockCardConnectionWorker()); inputApduInfos[0].addAcceptableStatusCode(QByteArray("1010")); @@ -140,13 +141,13 @@ class test_TransmitCommand QCOMPARE(command.getOutputApduAsHex().size(), 1); QCOMPARE(command.getOutputApduAsHex()[0], QByteArray("9000")); QCOMPARE(command.getReturnCode(), CardReturnCode::UNEXPECTED_TRANSMIT_STATUS); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code"_L1)); } void test_InternalExecuteOkMultipleCommand() { - QVector inputApduInfos(2); + QList inputApduInfos(2); QSharedPointer worker(new MockCardConnectionWorker()); worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); @@ -164,7 +165,7 @@ class test_TransmitCommand { QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - QVector inputApduInfos(2); + QList inputApduInfos(2); QSharedPointer worker(new MockCardConnectionWorker()); worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); @@ -174,7 +175,7 @@ class test_TransmitCommand QCOMPARE(command1.getOutputApduAsHex().size(), 1); QCOMPARE(command1.getOutputApduAsHex()[0], QByteArray("9000")); QCOMPARE(command1.getReturnCode(), CardReturnCode::PROTOCOL_ERROR); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code"_L1)); worker->addResponse(CardReturnCode::PROTOCOL_ERROR, QByteArray::fromHex("1919")); worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); @@ -182,7 +183,7 @@ class test_TransmitCommand command2.internalExecute(); QCOMPARE(command2.getOutputApduAsHex().size(), 0); QCOMPARE(command2.getReturnCode(), CardReturnCode::PROTOCOL_ERROR); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. Return code"_L1)); } @@ -190,8 +191,8 @@ class test_TransmitCommand { QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - QVector inputApduInfos1(2); - QVector inputApduInfos2(2); + QList inputApduInfos1(2); + QList inputApduInfos2(2); QSharedPointer worker(new MockCardConnectionWorker()); inputApduInfos1[0].addAcceptableStatusCode(QByteArray("90")); @@ -204,7 +205,7 @@ class test_TransmitCommand QCOMPARE(command1.getOutputApduAsHex()[0], QByteArray("9000")); QCOMPARE(command1.getOutputApduAsHex()[1], QByteArray("9000")); QCOMPARE(command1.getReturnCode(), CardReturnCode::UNEXPECTED_TRANSMIT_STATUS); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code"_L1)); inputApduInfos2[0].addAcceptableStatusCode(QByteArray("1010")); inputApduInfos2[1].addAcceptableStatusCode(QByteArray("9000")); @@ -215,13 +216,13 @@ class test_TransmitCommand QCOMPARE(command2.getOutputApduAsHex().size(), 1); QCOMPARE(command2.getOutputApduAsHex()[0], QByteArray("9000")); QCOMPARE(command2.getReturnCode(), CardReturnCode::UNEXPECTED_TRANSMIT_STATUS); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("Transmit unsuccessful. StatusCode does not start with acceptable status code"_L1)); } void test_SlotHandle() { - QVector inputApduInfos(1); + QList inputApduInfos(1); QSharedPointer worker(new MockCardConnectionWorker()); const QString name = QStringLiteral("slotname"); TransmitCommand command(worker, inputApduInfos, name); @@ -231,7 +232,7 @@ class test_TransmitCommand void test_EmptyResponse() { - QVector inputApduInfos(2); + QList inputApduInfos(2); QSharedPointer worker(new MockCardConnectionWorker()); worker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); diff --git a/test/qt/card/base/command/test_UpdRetryCounterCommand.cpp b/test/qt/card/base/command/test_UpdRetryCounterCommand.cpp index 520eac27c..04b7d0d66 100644 --- a/test/qt/card/base/command/test_UpdRetryCounterCommand.cpp +++ b/test/qt/card/base/command/test_UpdRetryCounterCommand.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "command/UpdateRetryCounterCommand.h" @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -21,7 +22,7 @@ class test_UpdateRetryCounterCommand private Q_SLOTS: void test_InternalExecuteNoCard() { - MockReader reader(QString("name")); + MockReader reader("name"_L1); QSharedPointer worker(new MockCardConnectionWorker(&reader)); UpdateRetryCounterCommand command(worker); command.internalExecute(); @@ -31,8 +32,8 @@ class test_UpdateRetryCounterCommand void test_InternalExecuteWithCard() { - MockReader reader(QStringLiteral("reader")); - CardInfo info(CardType::EID_CARD, QSharedPointer(), 1, true, true); + MockReader reader("reader"_L1); + CardInfo info(CardType::EID_CARD, FileRef(), QSharedPointer(), 1, true, true); reader.setInfoCardInfo(info); QSharedPointer worker(new MockCardConnectionWorker(&reader)); diff --git a/test/qt/card/base/pinpad/test_EstablishPaceChannel.cpp b/test/qt/card/base/pinpad/test_EstablishPaceChannel.cpp index 923d83acd..4c1db9832 100644 --- a/test/qt/card/base/pinpad/test_EstablishPaceChannel.cpp +++ b/test/qt/card/base/pinpad/test_EstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -39,7 +39,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN); - QCOMPARE(builder.createCommandData(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1Struct(), QByteArray::fromHex(hexBytes)); } @@ -52,7 +52,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN); - QCOMPARE(builder.createCommandDataCcid(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1StructCcid(), QByteArray::fromHex(hexBytes)); } @@ -67,7 +67,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN); builder.setPassword(QByteArray("123456")); - QCOMPARE(builder.createCommandData(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1Struct(), QByteArray::fromHex(hexBytes)); } @@ -82,7 +82,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN); builder.setPassword(QByteArray("123456")); - QCOMPARE(builder.createCommandDataCcid().toHex(), QByteArray::fromHex(hexBytes).toHex()); + QCOMPARE(builder.createASN1StructCcid().toHex(), QByteArray::fromHex(hexBytes).toHex()); } @@ -98,7 +98,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN, QByteArray::fromHex(mChatHex)); QCOMPARE(builder.getChat(), QByteArray::fromHex(mChatHex)); - QCOMPARE(builder.createCommandData(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1Struct(), QByteArray::fromHex(hexBytes)); } @@ -114,7 +114,7 @@ class test_EstablishPaceChannel EstablishPaceChannel builder(PacePasswordId::PACE_PIN, QByteArray::fromHex(mChatHex)); QCOMPARE(builder.getChat(), QByteArray::fromHex(mChatHex)); - QCOMPARE(builder.createCommandDataCcid(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1StructCcid(), QByteArray::fromHex(hexBytes)); } @@ -132,7 +132,7 @@ class test_EstablishPaceChannel QCOMPARE(builder.getChat(), QByteArray::fromHex(mChatHex)); QCOMPARE(builder.getCertificateDescription(), QByteArray::fromHex(mCertHex)); - QCOMPARE(builder.createCommandData(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1Struct(), QByteArray::fromHex(hexBytes)); } @@ -151,7 +151,7 @@ class test_EstablishPaceChannel QCOMPARE(builder.getChat(), QByteArray::fromHex(mChatHex)); QCOMPARE(builder.getCertificateDescription(), QByteArray::fromHex(mCertHex)); - QCOMPARE(builder.createCommandDataCcid(), QByteArray::fromHex(hexBytes)); + QCOMPARE(builder.createASN1StructCcid(), QByteArray::fromHex(hexBytes)); } @@ -179,7 +179,7 @@ class test_EstablishPaceChannel const QByteArray certDescription = QByteArray::fromHex(mCertHex); EstablishPaceChannel builder(pinId, chat, certDescription); - const auto buffer = builder.createCommandDataCcid(); + const auto buffer = builder.createASN1StructCcid(); EstablishPaceChannel parser; QVERIFY(parser.fromCcid(buffer)); diff --git a/test/qt/card/base/pinpad/test_EstablishPaceChannelOutput.cpp b/test/qt/card/base/pinpad/test_EstablishPaceChannelOutput.cpp index fb3d34cde..ad8900b28 100644 --- a/test/qt/card/base/pinpad/test_EstablishPaceChannelOutput.cpp +++ b/test/qt/card/base/pinpad/test_EstablishPaceChannelOutput.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -319,7 +319,7 @@ class test_EstablishPaceChannelOutput QTest::newRow("OK_PUK") << CardReturnCode::OK_PUK << QByteArray("00000000"); QTest::newRow("CARD_NOT_FOUND") << CardReturnCode::CARD_NOT_FOUND << QByteArray("020010f0"); - QTest::newRow("RETRY_ALLOWED") << CardReturnCode::RETRY_ALLOWED << QByteArray("020010f0"); + QTest::newRow("RETRY_ALLOWED") << CardReturnCode::RESPONSE_EMPTY << QByteArray("020010f0"); QTest::newRow("INPUT_TIME_OUT") << CardReturnCode::INPUT_TIME_OUT << QByteArray("020020f0"); diff --git a/test/qt/card/base/pinpad/test_LengthValue.cpp b/test/qt/card/base/pinpad/test_LengthValue.cpp index f6153cba2..965b801f3 100644 --- a/test/qt/card/base/pinpad/test_LengthValue.cpp +++ b/test/qt/card/base/pinpad/test_LengthValue.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "pinpad/LengthValue.h" diff --git a/test/qt/card/base/pinpad/test_PinModify.cpp b/test/qt/card/base/pinpad/test_PinModify.cpp index 68658d6e0..0c446c5c6 100644 --- a/test/qt/card/base/pinpad/test_PinModify.cpp +++ b/test/qt/card/base/pinpad/test_PinModify.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include diff --git a/test/qt/card/base/pinpad/test_PinModifyOutput.cpp b/test/qt/card/base/pinpad/test_PinModifyOutput.cpp index 04a7536f4..5495aca25 100644 --- a/test/qt/card/base/pinpad/test_PinModifyOutput.cpp +++ b/test/qt/card/base/pinpad/test_PinModifyOutput.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include diff --git a/test/qt/card/base/test_Card.cpp b/test/qt/card/base/test_Card.cpp new file mode 100644 index 000000000..183869a31 --- /dev/null +++ b/test/qt/card/base/test_Card.cpp @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "VolatileSettings.h" + +#include "Card.h" + +#include + + +using namespace governikus; + + +class test_Card + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + Env::getSingleton()->setMessages(VolatileSettings::Messages( + QStringLiteral("scan started"), + QStringLiteral("scan failed"), + QStringLiteral("scan succeded"), + QStringLiteral("scan progress"))); + } + + + void test_generateProgressMessage_data() + { + QTest::addColumn("sdk"); + QTest::addColumn("message"); + QTest::addColumn("progress"); + QTest::addColumn("expectedMessage"); + + QTest::addRow("Message without Progress") << false << "specific message" << -1 << "specific message"; + QTest::addRow("Message with Progress") << false << "specific message" << 20 << "specific message\n20 %"; + QTest::addRow("No Message but Progress") << false << QString() << 30 << "30 %"; + + QTest::addRow("SDK - Message without Progress") << true << "specific message" << -1 << "scan progress\n0 %"; + QTest::addRow("SDK - Message with Progress") << true << "specific message" << 20 << "scan progress\n20 %"; + QTest::addRow("SDK - No Message but Progress") << true << QString() << 30 << "scan progress\n30 %"; + } + + + void test_generateProgressMessage() + { + QFETCH(bool, sdk); + QFETCH(QString, message); + QFETCH(int, progress); + QFETCH(QString, expectedMessage); + + Env::getSingleton()->setUsedAsSDK(sdk); + const auto result = Card::generateProgressMessage(message, progress); + QCOMPARE(result, expectedMessage); + } + + + void test_generateErrorMessage_data() + { + QTest::addColumn("sdk"); + QTest::addColumn("message"); + QTest::addColumn("expectedMessage"); + + QTest::addRow("Normal message") << false << "specific message" << "specific message"; + QTest::addRow("Null message") << false << QString() << QString(); + QTest::addRow("Empty message") << false << QStringLiteral("") << QStringLiteral(""); + + QTest::addRow("SDK - Normal message") << true << "specific message" << "scan failed"; + QTest::addRow("SDK - Null message") << true << QString() << QString(); + QTest::addRow("SDK - Empty message") << true << QStringLiteral("") << "scan failed"; + } + + + void test_generateErrorMessage() + { + QFETCH(bool, sdk); + QFETCH(QString, message); + QFETCH(QString, expectedMessage); + + Env::getSingleton()->setUsedAsSDK(sdk); + const auto result = Card::generateErrorMessage(message); + QCOMPARE(result, expectedMessage); + } + + +}; + +QTEST_GUILESS_MAIN(test_Card) +#include "test_Card.moc" diff --git a/test/qt/card/base/test_CardConnection.cpp b/test/qt/card/base/test_CardConnection.cpp index 54790240a..0857c2d29 100644 --- a/test/qt/card/base/test_CardConnection.cpp +++ b/test/qt/card/base/test_CardConnection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -45,14 +45,27 @@ class test_CardConnection } + void test_CreateResetRetryCounterCommand() + { + QSharedPointer worker(new MockCardConnectionWorker()); + worker->moveToThread(&workerThread); + CardConnection connection(worker); + ResetRetryCounterCommand* command = connection.createResetRetryCounterCommand(); + command->deleteLater(); + QCOMPARE(command->mCardConnectionWorker, worker); + } + + void test_CreateDestroyPaceChannelCommand() { QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); CardConnection connection(worker); - DestroyPaceChannelCommand* command = connection.createDestroyPaceChannelCommand(); + const QString slotHandle = QStringLiteral("slot handle"); + DestroyPaceChannelCommand* command = connection.createDestroyPaceChannelCommand(slotHandle); command->deleteLater(); QCOMPARE(command->mCardConnectionWorker, worker); + QCOMPARE(command->getSlotHandle(), slotHandle); } @@ -93,12 +106,12 @@ class test_CardConnection QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); CardConnection connection(worker); - const QVector apduInfos; + const QList apduInfos; const QString slotHandle = QStringLiteral("slot handle"); TransmitCommand* command = connection.createTransmitCommand(apduInfos, slotHandle); command->deleteLater(); QCOMPARE(command->mCardConnectionWorker, worker); - QCOMPARE(command->mSlotHandle, slotHandle); + QCOMPARE(command->getSlotHandle(), slotHandle); } diff --git a/test/qt/card/base/test_CardConnectionWorker.cpp b/test/qt/card/base/test_CardConnectionWorker.cpp index 0dc402afe..8941403c8 100644 --- a/test/qt/card/base/test_CardConnectionWorker.cpp +++ b/test/qt/card/base/test_CardConnectionWorker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -25,7 +25,7 @@ class test_CardConnectionWorker void setCard() { - QVector transmitConfigs; + QList transmitConfigs; transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6982"))); transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("9000"))); MockCardConfig cardConfig(transmitConfigs); @@ -141,40 +141,40 @@ class test_CardConnectionWorker void test_readFile_data() { - QTest::addColumn>("responses"); + QTest::addColumn>("responses"); QTest::addColumn("expectedFileContent"); - QTest::newRow("short file - success") << QVector({ + QTest::newRow("short file - success") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(8, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::COMMAND_FAILED, QByteArray()) }) << QByteArray(8, 0); - QTest::newRow("short file - end of file") << QVector({ + QTest::newRow("short file - end of file") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(8, 0) + QByteArray::fromHex("6282")), TransmitConfig(CardReturnCode::COMMAND_FAILED, QByteArray()) }) << QByteArray(8, 0); - QTest::newRow("short file - illegal offset") << QVector({ + QTest::newRow("short file - illegal offset") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(256, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6B00")), TransmitConfig(CardReturnCode::COMMAND_FAILED, QByteArray()) }) << QByteArray(256, 0); - QTest::newRow("long file - success") << QVector({ + QTest::newRow("long file - success") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(256, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray(8, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::COMMAND_FAILED, QByteArray()) }) << QByteArray(264, 0); - QTest::newRow("long file - end of file") << QVector({ + QTest::newRow("long file - end of file") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(256, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray(8, 0) + QByteArray::fromHex("6282")), TransmitConfig(CardReturnCode::COMMAND_FAILED, QByteArray()) }) << QByteArray(264, 0); - QTest::newRow("long file - illegal offset") << QVector({ + QTest::newRow("long file - illegal offset") << QList({ TransmitConfig(CardReturnCode::OK, QByteArray(256, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray(256, 0) + QByteArray::fromHex("9000")), TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6B00")), @@ -185,7 +185,7 @@ class test_CardConnectionWorker void test_readFile() { - QFETCH(QVector, responses); + QFETCH(QList, responses); QFETCH(QByteArray, expectedFileContent); MockCardConfig cardConfig(responses); diff --git a/test/qt/card/base/test_CardInfo.cpp b/test/qt/card/base/test_CardInfo.cpp index 4e5d87713..7a652e37f 100644 --- a/test/qt/card/base/test_CardInfo.cpp +++ b/test/qt/card/base/test_CardInfo.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "CardInfo.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_CardInfo @@ -17,21 +18,21 @@ class test_CardInfo void test_CardTypeString_data() { QTest::addColumn("type"); - QTest::addColumn("output"); + QTest::addColumn("output"); - QTest::newRow("none") << CardType::NONE << QString("not inserted"); - QTest::newRow("unknown") << CardType::UNKNOWN << QString("unknown type"); - QTest::newRow("eid-card") << CardType::EID_CARD << QString("ID card (PA/eAT/eID)"); - QTest::newRow("smart-eid") << CardType::SMART_EID << QString("Smart-eID"); + QTest::newRow("none") << CardType::NONE << "not inserted"_L1; + QTest::newRow("unknown") << CardType::UNKNOWN << "unknown type"_L1; + QTest::newRow("eid-card") << CardType::EID_CARD << "ID card (PA/eAT/eID)"_L1; + QTest::newRow("smart-eid") << CardType::SMART_EID << "Smart-eID"_L1; } void test_CardTypeString() { QFETCH(CardType, type); - QFETCH(QString, output); + QFETCH(QLatin1String, output); - const CardInfo info(type, QSharedPointer(), 3, false, false); + const CardInfo info(type, FileRef(), QSharedPointer(), 3, false, false); QCOMPARE(info.getCardTypeString(), output); } @@ -89,7 +90,7 @@ class test_CardInfo const auto efCardAccess = EFCardAccess::fromHex(efCardAccessBytes); const CardInfo info = efCardAccessBytes.isEmpty() ? CardInfo(cardType) - : CardInfo(cardType, efCardAccess, 3, false, false); + : CardInfo(cardType, FileRef(), efCardAccess, 3, false, false); QCOMPARE(info.getMobileEidType(), expectedResult); } @@ -99,7 +100,7 @@ class test_CardInfo const CardInfo info1(CardType::EID_CARD); QVERIFY(!info1.isRetryCounterDetermined()); - const CardInfo info2(CardType::EID_CARD, QSharedPointer(), 3, false, false); + const CardInfo info2(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, false, false); QVERIFY(info2.isRetryCounterDetermined()); } diff --git a/test/qt/card/base/test_CardInfoFactory.cpp b/test/qt/card/base/test_CardInfoFactory.cpp index e99c18b80..067f64efd 100644 --- a/test/qt/card/base/test_CardInfoFactory.cpp +++ b/test/qt/card/base/test_CardInfoFactory.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "CardInfoFactory.h" diff --git a/test/qt/card/base/test_FileRef.cpp b/test/qt/card/base/test_FileRef.cpp index c7f8a10d8..cfc87c363 100644 --- a/test/qt/card/base/test_FileRef.cpp +++ b/test/qt/card/base/test_FileRef.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "FileRef.h" @@ -7,6 +7,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -26,17 +27,17 @@ class test_FileRef QTest::addColumn("type"); QTest::addColumn("identifier"); QTest::addColumn("shortIdentifier"); - QTest::addColumn("name"); - - QTest::newRow("masterFile") << FileRef::masterFile() << FileRef::TYPE::MASTER_FILE << QByteArray("3F00") << QByteArray() << "MasterFile"; - QTest::newRow("efDir") << FileRef::efDir() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("2F00") << QByteArray("1E") << "ElementaryFile"; - QTest::newRow("efCardAccess") << FileRef::efCardAccess() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("011C") << QByteArray("1C") << "ElementaryFile"; - QTest::newRow("efCardSecurity") << FileRef::efCardSecurity() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("011D") << QByteArray("1D") << "ElementaryFile"; - QTest::newRow("appCIA") << FileRef::appCIA() << FileRef::TYPE::APPLICATION << QByteArray("E828BD080FA000000167455349474E") << QByteArray() << "eSign CIA"; - QTest::newRow("appEId") << FileRef::appEId() << FileRef::TYPE::APPLICATION << QByteArray("E80704007F00070302") << QByteArray() << "eID"; - QTest::newRow("appESign") << FileRef::appESign() << FileRef::TYPE::APPLICATION << QByteArray("A000000167455349474E") << QByteArray() << "eSign"; - QTest::newRow("appPassport") << FileRef::appPassport() << FileRef::TYPE::APPLICATION << QByteArray("A0000002471001") << QByteArray() << "Passport"; - QTest::newRow("appPersosim") << FileRef::appPersosim() << FileRef::TYPE::APPLICATION << QByteArray("F04E66E75C02D8") << QByteArray() << "PersoSim"; + QTest::addColumn("name"); + + QTest::newRow("masterFile") << FileRef::masterFile() << FileRef::TYPE::MASTER_FILE << QByteArray("3F00") << QByteArray() << "MasterFile"_L1; + QTest::newRow("efDir") << FileRef::efDir() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("2F00") << QByteArray("1E") << "ElementaryFile"_L1; + QTest::newRow("efCardAccess") << FileRef::efCardAccess() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("011C") << QByteArray("1C") << "ElementaryFile"_L1; + QTest::newRow("efCardSecurity") << FileRef::efCardSecurity() << FileRef::TYPE::ELEMENTARY_FILE << QByteArray("011D") << QByteArray("1D") << "ElementaryFile"_L1; + QTest::newRow("appCIA") << FileRef::appCIA() << FileRef::TYPE::APPLICATION << QByteArray("E828BD080FA000000167455349474E") << QByteArray() << "eSign CIA"_L1; + QTest::newRow("appEId") << FileRef::appEId() << FileRef::TYPE::APPLICATION << QByteArray("E80704007F00070302") << QByteArray() << "eID"_L1; + QTest::newRow("appESign") << FileRef::appESign() << FileRef::TYPE::APPLICATION << QByteArray("A000000167455349474E") << QByteArray() << "eSign"_L1; + QTest::newRow("appPassport") << FileRef::appPassport() << FileRef::TYPE::APPLICATION << QByteArray("A0000002471001") << QByteArray() << "Passport"_L1; + QTest::newRow("appPersosim") << FileRef::appPersosim() << FileRef::TYPE::APPLICATION << QByteArray("F04E66E75C02D8") << QByteArray() << "PersoSim"_L1; } @@ -46,7 +47,7 @@ class test_FileRef QFETCH(FileRef::TYPE, type); QFETCH(QByteArray, identifier); QFETCH(QByteArray, shortIdentifier); - QFETCH(QString, name); + QFETCH(QLatin1String, name); QCOMPARE(file.getType(), type); QCOMPARE(file.getIdentifier(), QByteArray::fromHex(identifier)); @@ -66,9 +67,9 @@ class test_FileRef void unknownName() { - QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray()).getName(), "Unknown"); - QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray::fromHex("1234")).getName(), "Unknown"); - QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray::fromHex("ABCD")).getName(), "Unknown"); + QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray()).getName(), "Unknown"_L1); + QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray::fromHex("1234")).getName(), "Unknown"_L1); + QCOMPARE(FileRef(FileRef::TYPE::APPLICATION, QByteArray::fromHex("ABCD")).getName(), "Unknown"_L1); } diff --git a/test/qt/card/base/test_Reader.cpp b/test/qt/card/base/test_Reader.cpp index d8c109e81..6bbdd1151 100644 --- a/test/qt/card/base/test_Reader.cpp +++ b/test/qt/card/base/test_Reader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,7 +14,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -23,7 +23,7 @@ class test_Reader { Q_OBJECT QSharedPointer mReader; - QString mReaderName = QString("test reader"); + QString mReaderName = "test reader"_L1; QSharedPointer mWorker; private Q_SLOTS: @@ -60,8 +60,8 @@ class test_Reader void test_UpdateRetryCounterCommandFailed() { - CardInfo cInfo(CardType::UNKNOWN, QSharedPointer(), 3, false, false); - ReaderInfo rInfo(mReaderName, ReaderManagerPlugInType::UNKNOWN, cInfo); + CardInfo cInfo(CardType::UNKNOWN, FileRef(), QSharedPointer(), 3, false, false); + ReaderInfo rInfo(mReaderName, ReaderManagerPluginType::UNKNOWN, cInfo); mReader->setReaderInfo(rInfo); QTest::ignoreMessage(QtCriticalMsg, "Cannot get EF.CardAccess"); @@ -71,10 +71,10 @@ class test_Reader void test_UpdateRetryCounterUnknown() { - QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex")); + QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex"_L1)); auto efCardAccess = EFCardAccess::decode(bytes); - CardInfo cInfo(CardType::UNKNOWN, efCardAccess, 3, false, false); - ReaderInfo rInfo(mReaderName, ReaderManagerPlugInType::UNKNOWN, cInfo); + CardInfo cInfo(CardType::UNKNOWN, FileRef(), efCardAccess, 3, false, false); + ReaderInfo rInfo(mReaderName, ReaderManagerPluginType::UNKNOWN, cInfo); mReader->setReaderInfo(rInfo); mWorker->addResponse(CardReturnCode::UNKNOWN); QCOMPARE(mReader->updateRetryCounter(mWorker), CardReturnCode::UNKNOWN); @@ -83,10 +83,10 @@ class test_Reader void test_UpdateRetryCounter_OK_RetryCounterChanged() { - QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex")); + QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex"_L1)); auto efCardAccess = EFCardAccess::decode(bytes); - CardInfo cInfo(CardType::UNKNOWN, efCardAccess, 2, true, false); - ReaderInfo rInfo(mReaderName, ReaderManagerPlugInType::UNKNOWN, cInfo); + CardInfo cInfo(CardType::UNKNOWN, FileRef(), efCardAccess, 2, true, false); + ReaderInfo rInfo(mReaderName, ReaderManagerPluginType::UNKNOWN, cInfo); mReader->setReaderInfo(rInfo); mWorker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); QSignalSpy spy(mReader.data(), &Reader::fireCardInfoChanged); @@ -112,8 +112,8 @@ class test_Reader " 06 0A 04007F00070202040202" " 02 01 02"); auto efCardAccess = EFCardAccess::fromHex(hexString); - CardInfo cInfo(CardType::UNKNOWN, efCardAccess, 2, true, false); - ReaderInfo rInfo(mReaderName, ReaderManagerPlugInType::UNKNOWN, cInfo); + CardInfo cInfo(CardType::UNKNOWN, FileRef(), efCardAccess, 2, true, false); + ReaderInfo rInfo(mReaderName, ReaderManagerPluginType::UNKNOWN, cInfo); mReader->setReaderInfo(rInfo); mWorker->addResponse(CardReturnCode::OK, QByteArray::fromHex("9000")); QSignalSpy spy(mReader.data(), &Reader::fireCardInfoChanged); @@ -134,10 +134,10 @@ class test_Reader void test_UpdateRetryCounter_InitialPinChanged() { - QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex")); + QByteArray bytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex"_L1)); auto efCardAccess = EFCardAccess::decode(bytes); - CardInfo cInfo(CardType::UNKNOWN, efCardAccess, 3, true, false); - ReaderInfo rInfo(mReaderName, ReaderManagerPlugInType::UNKNOWN, cInfo); + CardInfo cInfo(CardType::UNKNOWN, FileRef(), efCardAccess, 3, true, false); + ReaderInfo rInfo(mReaderName, ReaderManagerPluginType::UNKNOWN, cInfo); mReader->setReaderInfo(rInfo); mWorker->addResponse(CardReturnCode::OK, QByteArray::fromHex("63D3")); QSignalSpy spy(mReader.data(), &Reader::fireCardInfoChanged); @@ -178,7 +178,7 @@ class test_Reader QSignalSpy info(mReader.data(), &Reader::fireCardInfoChanged); QVERIFY(!mReader->getReaderInfo().isInsertable()); - mReader->setInfoCardInfo(CardInfo(type, nullptr, retryCounter)); + mReader->setInfoCardInfo(CardInfo(type, FileRef(), nullptr, retryCounter)); mReader->shelveCard(); QCOMPARE(removed.count(), 0); diff --git a/test/qt/card/base/test_ReaderInfo.cpp b/test/qt/card/base/test_ReaderInfo.cpp index 63c6ef1f3..72b1ec121 100644 --- a/test/qt/card/base/test_ReaderInfo.cpp +++ b/test/qt/card/base/test_ReaderInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -45,7 +45,7 @@ class test_ReaderInfo QFETCH(bool, hasCard); QFETCH(bool, hasEid); - const ReaderInfo info(QStringLiteral("Reader"), ReaderManagerPlugInType::UNKNOWN, CardInfo(type, nullptr, 3, false, false)); + const ReaderInfo info(QStringLiteral("Reader"), ReaderManagerPluginType::UNKNOWN, CardInfo(type, FileRef(), nullptr, 3, false, false)); QCOMPARE(info.getCardType(), type); QCOMPARE(info.hasCard(), hasCard); @@ -75,7 +75,7 @@ class test_ReaderInfo QFETCH(int, length); QFETCH(bool, insufficient); - ReaderInfo info(QStringLiteral("Reader"), ReaderManagerPlugInType::UNKNOWN, CardInfo(CardType::UNKNOWN)); + ReaderInfo info(QStringLiteral("Reader"), ReaderManagerPluginType::UNKNOWN, CardInfo(CardType::UNKNOWN)); QCOMPARE(info.getMaxApduLength(), 500); QVERIFY(!info.insufficientApduLength()); diff --git a/test/qt/card/base/test_ReaderManager.cpp b/test/qt/card/base/test_ReaderManager.cpp index fe048e40e..945ffd42b 100644 --- a/test/qt/card/base/test_ReaderManager.cpp +++ b/test/qt/card/base/test_ReaderManager.cpp @@ -1,18 +1,19 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderManager.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include #include #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(ReaderInfo) @@ -45,7 +46,7 @@ class test_ReaderManager private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -60,7 +61,7 @@ class test_ReaderManager void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } @@ -68,11 +69,11 @@ class test_ReaderManager { QSignalSpy spy(Env::getSingleton(), &ReaderManager::fireReaderAdded); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 4711"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 4711"_L1); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations const auto info = qvariant_cast(spy.takeFirst().at(0)); - QCOMPARE(info.getName(), QString("MockReader 4711")); + QCOMPARE(info.getName(), "MockReader 4711"_L1); } @@ -81,11 +82,11 @@ class test_ReaderManager QSignalSpy spy(Env::getSingleton(), &ReaderManager::fireReaderRemoved); fireReaderAdded(); - MockReaderManagerPlugIn::getInstance().removeReader("MockReader 4711"); + MockReaderManagerPlugin::getInstance().removeReader("MockReader 4711"_L1); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations const auto info = qvariant_cast(spy.takeFirst().at(0)); - QCOMPARE(info.getName(), QString("MockReader 4711")); + QCOMPARE(info.getName(), "MockReader 4711"_L1); } @@ -93,7 +94,7 @@ class test_ReaderManager { CreateCardConnectionCommandSlot commandSlot; - Env::getSingleton()->callCreateCardConnectionCommand("UnknownReader", &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); + Env::getSingleton()->callCreateCardConnectionCommand("UnknownReader"_L1, &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); QTRY_COMPARE(commandSlot.mSlotCalled, true); // clazy:exclude=qstring-allocations QVERIFY(commandSlot.mCardConnection.isNull()); @@ -103,9 +104,9 @@ class test_ReaderManager void fireCreateCardConnection_noCard() { CreateCardConnectionCommandSlot commandSlot; - MockReaderManagerPlugIn::getInstance().addReader("MockReader 4711"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 4711"_L1); - Env::getSingleton()->callCreateCardConnectionCommand("UnknownReader", &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); + Env::getSingleton()->callCreateCardConnectionCommand("UnknownReader"_L1, &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); QTRY_COMPARE(commandSlot.mSlotCalled, true); // clazy:exclude=qstring-allocations QVERIFY(commandSlot.mCardConnection.isNull()); @@ -115,12 +116,12 @@ class test_ReaderManager void fireCreateCardConnection_cardConnectFail() { CreateCardConnectionCommandSlot commandSlot; - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 4711"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 4711"_L1); MockCardConfig cardConfig; cardConfig.mConnect = CardReturnCode::COMMAND_FAILED; reader->setCard(cardConfig); - Env::getSingleton()->callCreateCardConnectionCommand("MockReader 4711", &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); + Env::getSingleton()->callCreateCardConnectionCommand("MockReader 4711"_L1, &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); QTRY_COMPARE(commandSlot.mSlotCalled, true); // clazy:exclude=qstring-allocations QVERIFY(commandSlot.mCardConnection.isNull()); @@ -130,22 +131,42 @@ class test_ReaderManager void fireCreateCardConnection() { CreateCardConnectionCommandSlot commandSlot; - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 4711"); - MockCardConfig cardConfig; + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 4711"_L1); + QList transmitConfigs; + transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6982"))); + transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("9000"))); + MockCardConfig cardConfig(transmitConfigs); cardConfig.mConnect = CardReturnCode::OK; - reader->setCard(cardConfig); + reader->setCard(cardConfig, QSharedPointer(), CardType::EID_CARD, FileRef::appEId()); - Env::getSingleton()->callCreateCardConnectionCommand("MockReader 4711", &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); + Env::getSingleton()->callCreateCardConnectionCommand("MockReader 4711"_L1, &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); QTRY_COMPARE(commandSlot.mSlotCalled, true); // clazy:exclude=qstring-allocations QVERIFY(!commandSlot.mCardConnection.isNull()); } + void fireCreateCardConnectionFailedSelectApplication() + { + CreateCardConnectionCommandSlot commandSlot; + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 4711"_L1); + QList transmitConfigs; + transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6A82"))); + MockCardConfig cardConfig(transmitConfigs); + cardConfig.mConnect = CardReturnCode::OK; + reader->setCard(cardConfig, QSharedPointer(), CardType::EID_CARD, FileRef::appEId()); + + Env::getSingleton()->callCreateCardConnectionCommand("MockReader 4711"_L1, &commandSlot, &CreateCardConnectionCommandSlot::onCardCommandDone); + + QTRY_COMPARE(commandSlot.mSlotCalled, true); // clazy:exclude=qstring-allocations + QVERIFY(commandSlot.mCardConnection.isNull()); + } + + void getInvalidReaderInfo() { - const auto& readerInfo = Env::getSingleton()->getReaderInfo("test dummy"); - QCOMPARE(readerInfo.getPlugInType(), ReaderManagerPlugInType::UNKNOWN); + const auto& readerInfo = Env::getSingleton()->getReaderInfo("test dummy"_L1); + QCOMPARE(readerInfo.getPluginType(), ReaderManagerPluginType::UNKNOWN); QCOMPARE(readerInfo.getName(), QStringLiteral("test dummy")); } @@ -158,12 +179,12 @@ class test_ReaderManager auto readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 0); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 1"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 1"_L1); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 1); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 2"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 2"_L1); QTRY_COMPARE(spy.count(), 2); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 2); @@ -178,12 +199,12 @@ class test_ReaderManager auto readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 0); - MockReaderManagerPlugIn::getInstance().addReader("MockReader same"); + MockReaderManagerPlugin::getInstance().addReader("MockReader same"_L1); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 1); - MockReaderManagerPlugIn::getInstance().addReader("MockReader same"); + MockReaderManagerPlugin::getInstance().addReader("MockReader same"_L1); QTRY_COMPARE(spy.count(), 2); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 1); @@ -192,20 +213,20 @@ class test_ReaderManager void checkTypeReaderFilter_data() { - QTest::addColumn>("types"); + QTest::addColumn>("types"); QTest::addColumn("onceCount"); QTest::addColumn("twiceCount"); - QTest::newRow("0") << QVector({}) << 0 << 0; - QTest::newRow("1_existing") << QVector({ReaderManagerPlugInType::MOCK}) << 1 << 2; - QTest::newRow("1_non_existing") << QVector({ReaderManagerPlugInType::REMOTE_IFD}) << 0 << 0; - QTest::newRow("2_existing_non_existing") << QVector({ReaderManagerPlugInType::MOCK, ReaderManagerPlugInType::PCSC}) << 1 << 2; + QTest::newRow("0") << QList({}) << 0 << 0; + QTest::newRow("1_existing") << QList({ReaderManagerPluginType::MOCK}) << 1 << 2; + QTest::newRow("1_non_existing") << QList({ReaderManagerPluginType::REMOTE_IFD}) << 0 << 0; + QTest::newRow("2_existing_non_existing") << QList({ReaderManagerPluginType::MOCK, ReaderManagerPluginType::PCSC}) << 1 << 2; } void checkTypeReaderFilter() { - QFETCH(QVector, types); + QFETCH(QList, types); QFETCH(int, onceCount); QFETCH(int, twiceCount); @@ -215,12 +236,12 @@ class test_ReaderManager auto readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), 0); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 1"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 1"_L1); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), onceCount); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 2"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 2"_L1); QTRY_COMPARE(spy.count(), 2); // clazy:exclude=qstring-allocations readerInfos = Env::getSingleton()->getReaderInfos(filter); QCOMPARE(readerInfos.count(), twiceCount); @@ -229,7 +250,7 @@ class test_ReaderManager void test_shelve() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader"_L1); reader->setInfoCardInfo(CardInfo(CardType::EID_CARD)); QSignalSpy removed(reader, &Reader::fireCardRemoved); @@ -238,7 +259,7 @@ class test_ReaderManager QVERIFY(reader->getReaderInfo().hasCard()); QVERIFY(!reader->getReaderInfo().isInsertable()); - MockReaderManagerPlugIn::getInstance().shelve(); + MockReaderManagerPlugin::getInstance().shelve(); QCOMPARE(removed.count(), 0); QCOMPARE(properties.count(), 0); QVERIFY(reader->getReaderInfo().hasCard()); @@ -251,7 +272,7 @@ class test_ReaderManager QVERIFY(reader->getReaderInfo().hasCard()); QVERIFY(reader->getReaderInfo().isInsertable()); - MockReaderManagerPlugIn::getInstance().shelve(); + MockReaderManagerPlugin::getInstance().shelve(); QCOMPARE(removed.count(), 1); QCOMPARE(properties.count(), 1); QVERIFY(!reader->getReaderInfo().hasCard()); diff --git a/test/qt/card/base/test_SecurityProtocol.cpp b/test/qt/card/base/test_SecurityProtocol.cpp index d267e7396..c1551706c 100644 --- a/test/qt/card/base/test_SecurityProtocol.cpp +++ b/test/qt/card/base/test_SecurityProtocol.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "SecurityProtocol.h" diff --git a/test/qt/card/base/test_SmartCardDefinitions.cpp b/test/qt/card/base/test_SmartCardDefinitions.cpp index 852250beb..f26afe319 100644 --- a/test/qt/card/base/test_SmartCardDefinitions.cpp +++ b/test/qt/card/base/test_SmartCardDefinitions.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ #include "SmartCardDefinitions.h" diff --git a/test/qt/card/drivers/test_ReaderDetector.cpp b/test/qt/card/drivers/test_ReaderDetector.cpp index 39abff19d..ebeafb601 100644 --- a/test/qt/card/drivers/test_ReaderDetector.cpp +++ b/test/qt/card/drivers/test_ReaderDetector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -52,7 +52,7 @@ class test_ReaderDetector void noAttachedDeviceWithVIDAndPID_noAttachedDevicesFound() { - const QVector pDevIds({}); + const QList pDevIds({}); MockReaderDetector readerDetector(pDevIds); QCOMPARE(readerDetector.getAttachedSupportedDevices().size(), 0); @@ -61,7 +61,7 @@ class test_ReaderDetector void nonSupportedDeviceAttached_noAttachedDevicesFound() { - const QVector pDevIds({UsbId(0x413C, 0x2107)}); + const QList pDevIds({UsbId(0x413C, 0x2107)}); MockReaderDetector readerDetector(pDevIds); QCOMPARE(readerDetector.getAttachedSupportedDevices().size(), 0); @@ -70,7 +70,7 @@ class test_ReaderDetector void supportedDeviceAttachedButNoDriverInstalled_attachedDeviceFound() { - const QVector pDevIds({UsbId(0x0C4B, 0x0501)}); + const QList pDevIds({UsbId(0x0C4B, 0x0501)}); MockReaderDetector readerDetector(pDevIds); const auto devs = readerDetector.getAttachedSupportedDevices(); diff --git a/test/qt/card/pace/test_CipherMAC.cpp b/test/qt/card/pace/test_CipherMAC.cpp index 011f1b511..4f079873a 100644 --- a/test/qt/card/pace/test_CipherMAC.cpp +++ b/test/qt/card/pace/test_CipherMAC.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/CipherMac.h" diff --git a/test/qt/card/pace/test_EcUtil.cpp b/test/qt/card/pace/test_EcUtil.cpp index 53943e7f5..aa3c1f11c 100644 --- a/test/qt/card/pace/test_EcUtil.cpp +++ b/test/qt/card/pace/test_EcUtil.cpp @@ -1,15 +1,18 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/ec/EcUtil.h" #include + #include #include + using namespace governikus; + class test_EcUtil : public QObject { @@ -21,6 +24,36 @@ class test_EcUtil } + void compressPoint_data() + { + QTest::addColumn("input"); + QTest::addColumn("output"); + QTest::addColumn("warning"); + + QTest::newRow("Empty") << QByteArray() << QByteArray() << true; + QTest::newRow("Wrong first byte - no data") << QByteArray("00") << QByteArray("00") << true; + QTest::newRow("Correct first byte - no data") << QByteArray("04") << QByteArray() << false; + QTest::newRow("Wrong first byte - data") << QByteArray("000102") << QByteArray("000102") << true; + QTest::newRow("Correct first byte - data") << QByteArray("040102") << QByteArray("01") << false; + } + + + void compressPoint() + { + QFETCH(QByteArray, input); + QFETCH(QByteArray, output); + QFETCH(bool, warning); + + if (warning) + { + QByteArray message("Unable to apply compression on point: \"DATA\" "); + message.replace("DATA", input); + QTest::ignoreMessage(QtCriticalMsg, message.data()); + } + QCOMPARE(EcUtil::compressPoint(QByteArray::fromHex(input)).toHex(), output); + } + + void createAndFreeEmptyCurve() { EcUtil::create(static_cast(nullptr)); diff --git a/test/qt/card/pace/test_EcdhGenericMapping.cpp b/test/qt/card/pace/test_EcdhGenericMapping.cpp index 5cb825358..4671fc895 100644 --- a/test/qt/card/pace/test_EcdhGenericMapping.cpp +++ b/test/qt/card/pace/test_EcdhGenericMapping.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/ec/EcdhGenericMapping.h" @@ -33,7 +33,7 @@ class test_EcdhGenericMapping auto curve = EcUtil::createCurve(nid); EcdhGenericMapping mapping(curve); QCOMPARE(mapping.getCurve(), curve); - QCOMPARE(mapping.generateTerminalMappingData().isEmpty(), curve.isNull()); + QCOMPARE(mapping.generateLocalMappingData().isEmpty(), curve.isNull()); } diff --git a/test/qt/card/pace/test_EcdhKeyAgreement.cpp b/test/qt/card/pace/test_EcdhKeyAgreement.cpp index 3678fe5f6..05a76c786 100644 --- a/test/qt/card/pace/test_EcdhKeyAgreement.cpp +++ b/test/qt/card/pace/test_EcdhKeyAgreement.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,6 +17,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -29,7 +30,7 @@ class test_EcdhKeyAgreement private Q_SLOTS: void initTestCase() { - auto data = TestFileHelper::readFile(":/card/efCardAccess.hex"); + auto data = TestFileHelper::readFile(":/card/efCardAccess.hex"_L1); mEfCardAccess = EFCardAccess::fromHex(data); } @@ -39,7 +40,7 @@ class test_EcdhKeyAgreement */ void perform_failureOnGetNonce() { - QVector transmitConfigs; + QList transmitConfigs; transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6982"))); QScopedPointer reader(MockReader::createMockReader(transmitConfigs, mEfCardAccess)); QSharedPointer paceInfo = mEfCardAccess->getPaceInfos().at(0); @@ -53,20 +54,16 @@ class test_EcdhKeyAgreement void encodeUncompressedPublicKey() { - QByteArray protocolValue = QByteArray::fromHex("04007F00070202040202"); - QSharedPointer paceInfo = PaceInfo::decode(QByteArray::fromHex("300F060A") + protocolValue + QByteArray::fromHex("020102")); - QSharedPointer ecGroup = EcUtil::create(EC_GROUP_new_by_curve_name(NID_brainpoolP256r1)); - QByteArray ecPointBytes = QByteArray::fromHex("04A9024A1CE8F02DB4463CD359BE3A6946FA24FDBED7D19B04BEA2F0AA2FF63C6D2A05B17A66EDBC15875611A209CB87C972A141263BD0843CC64B8B884C52F725"); - QSharedPointer ecPoint = EcUtil::oct2point(ecGroup, ecPointBytes); - - const QByteArray& result = EcdhKeyAgreement::encodeUncompressedPublicKey(paceInfo, ecGroup, ecPoint); + const Oid oid(KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128); + const QByteArray ecPointBytes = QByteArray::fromHex("04A9024A1CE8F02DB4463CD359BE3A6946FA24FDBED7D19B04BEA2F0AA2FF63C6D2A05B17A66EDBC15875611A209CB87C972A141263BD0843CC64B8B884C52F725"); + const QByteArray& result = EcdhKeyAgreement::encodeUncompressedPublicKey(KnownOid::ID_PACE_ECDH_GM_AES_CBC_CMAC_128, ecPointBytes); QCOMPARE(result.toHex(), // ISO 7816 Format in TR 3111 - 5.1.2 QByteArray("7f49") + QByteArray("4f") + QByteArray("06") + QByteArray("0a") - + protocolValue.toHex() + + QByteArray(oid).toHex() + QByteArray("86") + QByteArray("41") + ecPointBytes.toHex()); diff --git a/test/qt/card/pace/test_KeyDerivationFunction.cpp b/test/qt/card/pace/test_KeyDerivationFunction.cpp index 6097efe74..7e15e96d1 100644 --- a/test/qt/card/pace/test_KeyDerivationFunction.cpp +++ b/test/qt/card/pace/test_KeyDerivationFunction.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/KeyDerivationFunction.h" diff --git a/test/qt/card/pace/test_PaceHandler.cpp b/test/qt/card/pace/test_PaceHandler.cpp index 1bfb71e14..b58d8e4e8 100644 --- a/test/qt/card/pace/test_PaceHandler.cpp +++ b/test/qt/card/pace/test_PaceHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,6 +17,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -29,7 +30,7 @@ class test_PaceHandler private Q_SLOTS: void initTestCase() { - mEfCardAccessBytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex")); + mEfCardAccessBytes = QByteArray::fromHex(TestFileHelper::readFile(":/card/efCardAccess.hex"_L1)); } @@ -42,7 +43,7 @@ class test_PaceHandler void getPaceProtocol() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); paceHandler->initialize(reader->getReaderInfo().getCardInfo().getEfCardAccess()); @@ -65,7 +66,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_GM_3DES_CBC_CBC_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040101")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -77,7 +78,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_GM_AES_CBC_CMAC_128_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040102")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -89,7 +90,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_GM_AES_CBC_CMAC_192_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040103")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -101,7 +102,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_GM_AES_CBC_CMAC_256_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040104")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -113,7 +114,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_ECDH_GM_3DES_CBC_CBC_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040201")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -125,7 +126,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_IM_3DES_CBC_CBC_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040301")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -137,7 +138,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_IM_AES_CBC_CMAC_128_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040302")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -149,7 +150,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_IM_AES_CBC_CMAC_192_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040303")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -161,7 +162,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_DH_IM_AES_CBC_CMAC_256_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040304")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -173,7 +174,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_ECDH_IM_3DES_CBC_CBC_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040401")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -185,7 +186,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_ECDH_IM_AES_CBC_CMAC_128_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040402")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -197,7 +198,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_ECDH_IM_AES_CBC_CMAC_192_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040403")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -209,7 +210,7 @@ class test_PaceHandler void establishPaceChannel_id_PACE_ECDH_IM_AES_CBC_CMAC_256_unsupported() { QByteArray efCardAccess = QByteArray::fromHex(mEfCardAccessBytes.toHex().replace("04007f00070202040202", "04007f00070202040404")); - QScopedPointer reader(MockReader::createMockReader(QVector(), efCardAccess)); + QScopedPointer reader(MockReader::createMockReader(QList(), efCardAccess)); QScopedPointer paceHandler(new PaceHandler(reader->createCardConnectionWorker())); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); @@ -220,32 +221,32 @@ class test_PaceHandler void establishPaceChannel_RetryAllowed() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QSharedPointer worker(new MockCardConnectionWorker(reader.data())); QScopedPointer paceHandler(new PaceHandler(worker)); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); - QCOMPARE(status, CardReturnCode::RETRY_ALLOWED); + QCOMPARE(status, CardReturnCode::RESPONSE_EMPTY); } void establishPaceChannel_KeyAgreementRetryAllowed() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QSharedPointer worker(new MockCardConnectionWorker(reader.data())); QScopedPointer paceHandler(new PaceHandler(worker)); CardReturnCode status = paceHandler->establishPaceChannel(PacePasswordId::PACE_PIN, "123456"); - QCOMPARE(status, CardReturnCode::RETRY_ALLOWED); + QCOMPARE(status, CardReturnCode::RESPONSE_EMPTY); } // testcase TS_PACE_2.5.1c TR-03105 void failureOnMseSetAt() { - QVector transmitConfigs; + QList transmitConfigs; transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("9000"))); // Select file transmitConfigs.append(TransmitConfig(CardReturnCode::OK, QByteArray::fromHex("6A80"))); // MSE:Set AT QScopedPointer reader(MockReader::createMockReader(transmitConfigs, mEfCardAccessBytes)); @@ -259,7 +260,7 @@ class test_PaceHandler void transmitMSESetAT_OK() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QSharedPointer worker(new MockCardConnectionWorker(reader.data())); QScopedPointer paceHandler(new PaceHandler(worker)); QByteArray bytes = QByteArray::fromHex("30 0F" @@ -282,7 +283,7 @@ class test_PaceHandler void transmitMSESetAT_ErrorMseSetAT_PROTOCOL_ERROR() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QSharedPointer worker(new MockCardConnectionWorker(reader.data())); QScopedPointer paceHandler(new PaceHandler(worker)); QByteArray bytes = QByteArray::fromHex("30 0F" @@ -306,7 +307,7 @@ class test_PaceHandler void transmitMSESetAT_ErrorMseSetAT_RETRY_ALLOWED() { - QScopedPointer reader(MockReader::createMockReader(QVector(), mEfCardAccessBytes)); + QScopedPointer reader(MockReader::createMockReader(QList(), mEfCardAccessBytes)); QSharedPointer worker(new MockCardConnectionWorker(reader.data())); QScopedPointer paceHandler(new PaceHandler(worker)); QByteArray bytes = QByteArray::fromHex("30 0F" @@ -318,7 +319,7 @@ class test_PaceHandler worker->addResponse(CardReturnCode::UNDEFINED); QTest::ignoreMessage(QtCriticalMsg, "Error on MSE:Set AT"); - QCOMPARE(paceHandler->transmitMSESetAT(PacePasswordId::PACE_PIN), CardReturnCode::RETRY_ALLOWED); + QCOMPARE(paceHandler->transmitMSESetAT(PacePasswordId::PACE_PIN), CardReturnCode::RESPONSE_EMPTY); } diff --git a/test/qt/card/pace/test_SymmetricCipher.cpp b/test/qt/card/pace/test_SymmetricCipher.cpp index e061c6515..328e81437 100644 --- a/test/qt/card/pace/test_SymmetricCipher.cpp +++ b/test/qt/card/pace/test_SymmetricCipher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "pace/SymmetricCipher.h" diff --git a/test/qt/card/pcsc/test_PcscReader.cpp b/test/qt/card/pcsc/test_PcscReader.cpp index 30c31cc8a..067936b56 100644 --- a/test/qt/card/pcsc/test_PcscReader.cpp +++ b/test/qt/card/pcsc/test_PcscReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -7,6 +7,11 @@ */ #include "PcscReader.h" +#include "PcscUtils.h" + +#if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) + #include "pcscmock.h" +#endif #include @@ -46,6 +51,54 @@ class test_PcscReader } + void test_updateCard_data() + { + QTest::addColumn("mockResult"); + QTest::addColumn("expectedWarnings"); + + QTest::addRow("Success") << static_cast(SCARD_S_SUCCESS) << QStringList(); + QTest::addRow("Timeout") << static_cast(SCARD_E_TIMEOUT) << QStringList(); + QTest::addRow("Unknown Reader") << static_cast(SCARD_E_UNKNOWN_READER) << QStringList({ + QStringLiteral("SCardGetStatusChange: \"Scard_E_Unknown_Reader\""), + QStringLiteral("Reader unknown, stop updating reader information") + }); + QTest::addRow("Other") << static_cast(SCARD_E_CANCELLED) << QStringList({ + QStringLiteral("SCardGetStatusChange: \"Scard_E_Cancelled\""), + QStringLiteral("Cannot update reader") + }); + } + + + void test_updateCard() + { +#if !(defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) && !defined(Q_OS_FREEBSD) + QSKIP("Using LD_PRELOAD is not supported"); +#endif + QFETCH(LONG, mockResult); + QFETCH(QStringList, expectedWarnings); + +#if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) + setResultGetCardStatus(mockResult); +#else + Q_UNUSED(mockResult) +#endif + + QScopedPointer reader(new PcscReader(QStringLiteral("PCSC"))); + + for (const auto& message : expectedWarnings) + { + QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + } + + if (expectedWarnings.isEmpty()) + { + QTest::failOnWarning(QRegularExpression(QStringLiteral(".+"))); + } + + QCOMPARE(reader->init(), pcsc::Scard_S_Success); + } + + }; QTEST_GUILESS_MAIN(test_PcscReader) diff --git a/test/qt/card/pcsc/test_PcscReaderManagerPlugIn.cpp b/test/qt/card/pcsc/test_PcscReaderManagerPlugin.cpp similarity index 65% rename from test/qt/card/pcsc/test_PcscReaderManagerPlugIn.cpp rename to test/qt/card/pcsc/test_PcscReaderManagerPlugin.cpp index c114f645b..345742177 100644 --- a/test/qt/card/pcsc/test_PcscReaderManagerPlugIn.cpp +++ b/test/qt/card/pcsc/test_PcscReaderManagerPlugin.cpp @@ -1,19 +1,19 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref PcscReaderManagerPlugIn + * \brief Unit tests for \ref PcscReaderManagerPlugin */ -#include "PcscReaderManagerPlugIn.h" +#include "PcscReaderManagerPlugin.h" #include using namespace governikus; -class test_PcscReaderManagerPlugIn +class test_PcscReaderManagerPlugin : public QObject { Q_OBJECT @@ -27,11 +27,11 @@ class test_PcscReaderManagerPlugIn const QString readerName = QStringLiteral("PCSC"); - PcscReaderManagerPlugIn plugin; + PcscReaderManagerPlugin plugin; QCOMPARE(plugin.objectName(), QStringLiteral("PcscReaderManager")); QVERIFY(plugin.getReaders().isEmpty()); - QSignalSpy spyAdded(&plugin, &PcscReaderManagerPlugIn::fireReaderAdded); + QSignalSpy spyAdded(&plugin, &PcscReaderManagerPlugin::fireReaderAdded); QTest::ignoreMessage(QtDebugMsg, QStringLiteral("fireReaderAdded: \"%1\" ( 1 reader in total )").arg(readerName).toUtf8().data()); plugin.addReaders({readerName}); QCOMPARE(spyAdded.size(), 1); @@ -41,5 +41,5 @@ class test_PcscReaderManagerPlugIn }; -QTEST_GUILESS_MAIN(test_PcscReaderManagerPlugIn) -#include "test_PcscReaderManagerPlugIn.moc" +QTEST_GUILESS_MAIN(test_PcscReaderManagerPlugin) +#include "test_PcscReaderManagerPlugin.moc" diff --git a/test/qt/card/pcsc/test_PcscUtils.cpp b/test/qt/card/pcsc/test_PcscUtils.cpp index 350aa996d..007a8912f 100644 --- a/test/qt/card/pcsc/test_PcscUtils.cpp +++ b/test/qt/card/pcsc/test_PcscUtils.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "PcscUtils.h" diff --git a/test/qt/card/pcsc/test_pcscReaderFeature.cpp b/test/qt/card/pcsc/test_pcscReaderFeature.cpp index 8710e86cd..82d3102d0 100644 --- a/test/qt/card/pcsc/test_pcscReaderFeature.cpp +++ b/test/qt/card/pcsc/test_pcscReaderFeature.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/card/simulator/test_SimulatorCard.cpp b/test/qt/card/simulator/test_SimulatorCard.cpp index 4653e5c9a..787886604 100644 --- a/test/qt/card/simulator/test_SimulatorCard.cpp +++ b/test/qt/card/simulator/test_SimulatorCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ @@ -41,70 +41,111 @@ class test_SimulatorCard void transmit_data() { + // Fill mChatPACE for PACE + const auto& initPace = QByteArray("0022C1A427800A04007F0007020204020283010384010D7F4C12060904007F0007030102025305000513FF00"); + // Fill mCaKeyId for the chip authentication + const auto& initCa = QByteArray("002241A40F800A04007F00070202030202840129"); + // Fill mRiKeyId for the restricted identification + const auto& initRi = QByteArray("002241A40F800A04007F00070202050203840101"); + // Fill mAuxiliaryData with the community id for verify + const auto& initTa = QByteArray("002281A46D800A04007F00070202020203830E444544454D4F5041413030" + "353239672D7315060904007F000703010402530832303234303330397314" + "060904007F000703010403530702760503150000912001EAEDF8E53EBD73" + "58E56B4A6C2BBB8173CE3EAE8C61CD769C57F0210B24FAA0"); + + QTest::addColumn("init"); QTest::addColumn("command"); - QTest::addColumn("response"); - - QTest::newRow("select existing") << QByteArray::fromHex("00A4020C022F00") << QByteArray::fromHex("9000"); - QTest::newRow("select missing") << QByteArray::fromHex("00A4020C022F01") << QByteArray::fromHex("6A80"); - QTest::newRow("readBinary existing") << QByteArray::fromHex("00B0810000") << QByteArray::fromHex("6104130249449000"); - QTest::newRow("readBinary missing") << QByteArray::fromHex("00B0A10000") << QByteArray::fromHex("6A82"); - QTest::newRow("updatebinary existing") << QByteArray::fromHex("00D6810006610413024944") << QByteArray::fromHex("9000"); - QTest::newRow("updatebinary missing") << QByteArray::fromHex("00D6A10006610413024944") << QByteArray::fromHex("6A82"); - QTest::newRow("getChallenge") << QByteArray::fromHex("0084000008") << QByteArray::fromHex("01020304050607089000"); - QTest::newRow("mseSetAtRi") << QByteArray::fromHex("002241A40F800A04007F00070202050203840101") << QByteArray::fromHex("9000"); - QTest::newRow("mseSetAtTa") << QByteArray::fromHex("002281A41867167314060904007f000703010403530702760503150000") << QByteArray::fromHex("9000"); + QTest::addColumn("response"); + + QTest::newRow("select existing") << QByteArray() << QByteArray("00A4020C022F00") << QStringLiteral("9000"); + QTest::newRow("select missing") << QByteArray() << QByteArray("00A4020C022F01") << QStringLiteral("6A80"); + QTest::newRow("readBinary existing") << QByteArray() << QByteArray("00B0810000") << QStringLiteral("6104130249449000"); + QTest::newRow("readBinary missing") << QByteArray() << QByteArray("00B0A10000") << QStringLiteral("6A82"); + QTest::newRow("updatebinary existing") << QByteArray() << QByteArray("00D6810006610413024944") << QStringLiteral("9000"); + QTest::newRow("updatebinary missing") << QByteArray() << QByteArray("00D6A10006610413024944") << QStringLiteral("6A82"); + QTest::newRow("getChallenge") << QByteArray() << QByteArray("0084000008") << QStringLiteral("01020304050607089000"); + QTest::newRow("mseSetAtPace") << QByteArray() << initPace << QStringLiteral("9000"); + QTest::newRow("mseSetAtRi") << QByteArray() << initRi << QStringLiteral("9000"); + QTest::newRow("mseSetAtTa") << QByteArray() << initTa << QStringLiteral("9000"); + QTest::newRow("generalAuthenticatePace") + << initPace + << QByteArray("10860000027C0000") + << QStringLiteral("7C128010[A-F0-9]{32}9000"); QTest::newRow("generalAuthenticateCa") - << QByteArray::fromHex("00860000457C4380410493ECE64A5A0CA9DF88F34D274DB546BB7AE657B85D269FBAAD2A471" - "95654A4DE136E3A8A92081DD88C578D056EC5607FFA3C53A7B9A652958FDB114757F65B7B00") - << QByteArray::fromHex("7C1481080001020304050607820882F3A9399B5779559000"); + << initCa + << QByteArray("00860000457C4380410493ECE64A5A0CA9DF88F34D274DB546BB7AE657B85D269FBAAD2A471" + "95654A4DE136E3A8A92081DD88C578D056EC5607FFA3C53A7B9A652958FDB114757F65B7B00") + << QStringLiteral("7C1481080001020304050607820882F3A9399B5779559000"); QTest::newRow("generalAuthenticateRi") - << QByteArray::fromHex("008600000001257C820121A082011D060A04007F000702020502038120A9FB57DBA1EEA9BC3E" - "660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF6753041" - "7AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF95" - "8416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1" - "E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D" - "54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E829748" - "56A7864104373CD3BAD6245F6EDEB382E066C57107B84BF5EF2834201AAEA41CC0D472890308" - "3687C8C37C1D005C61BE2C122364101C2CBC41FFC3EC48C96E3F1D4F646ABE8701010100") - << QByteArray::fromHex("7C2281206C877EC6E470BCC1C40F5AAC180D90EDB907AC091E33D402BDD3C99CD0DDE5039000"); + << initRi + << QByteArray("008600000001257C820121A082011D060A04007F000702020502038120A9FB57DBA1EEA9BC3E" + "660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF6753041" + "7AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF95" + "8416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1" + "E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D" + "54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E829748" + "56A7864104373CD3BAD6245F6EDEB382E066C57107B84BF5EF2834201AAEA41CC0D472890308" + "3687C8C37C1D005C61BE2C122364101C2CBC41FFC3EC48C96E3F1D4F646ABE8701010100") + << QStringLiteral("7C2281206C877EC6E470BCC1C40F5AAC180D90EDB907AC091E33D402BDD3C99CD0DDE5039000"); QTest::newRow("generalAuthenticateRi - wrong key") - << QByteArray::fromHex("008600000001257C820121A082011D060A04007F000702020502018120A9FB57DBA1EEA9BC3E" - "660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF6753041" - "7AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF95" - "8416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1" - "E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D" - "54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E829748" - "56A7864104373CD3BAD6245F6EDEB382E066C57107B84BF5EF2834201AAEA41CC0D472890308" - "3687C8C37C1D005C61BE2C122364101C2CBC41FFC3EC48C96E3F1D4F646ABE8701010100") - << QByteArray::fromHex("6981"); - QTest::newRow("verify - existing") << QByteArray::fromHex("802080000B060904007f000703010403") << QByteArray::fromHex("9000"); - QTest::newRow("verify - unknown") << QByteArray::fromHex("802080000B060904007f000703010404") << QByteArray::fromHex("6300"); - QTest::newRow("verify - not proprietary") << QByteArray::fromHex("002080000B060904007f000703010403") << QByteArray::fromHex("6E00"); + << initRi + << QByteArray("008600000001257C820121A082011D060A04007F000702020502018120A9FB57DBA1EEA9BC3E" + "660A909D838D726E3BF623D52620282013481D1F6E537782207D5A0975FC2C3057EEF6753041" + "7AFFE7FB8055C126DC5C6CE94A4B44F330B5D9832026DC5C6CE94A4B44F330B5D9BBD77CBF95" + "8416295CF7E1CE6BCCDC18FF8C07B68441048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1" + "E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D" + "54C72F0469978520A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E829748" + "56A7864104373CD3BAD6245F6EDEB382E066C57107B84BF5EF2834201AAEA41CC0D472890308" + "3687C8C37C1D005C61BE2C122364101C2CBC41FFC3EC48C96E3F1D4F646ABE8701010100") + << QStringLiteral("6981"); + QTest::newRow("verify - existing") + << initTa + << QByteArray("802080000B060904007f000703010403") + << QStringLiteral("9000"); + QTest::newRow("verify - unknown") + << initTa + << QByteArray("802080000B060904007f000703010404") + << QStringLiteral("6300"); + QTest::newRow("verify - not proprietary") + << initTa + << QByteArray("002080000B060904007f000703010403") + << QStringLiteral("6E00"); } void transmit() { + QFETCH(QByteArray, init); QFETCH(QByteArray, command); - QFETCH(QByteArray, response); + QFETCH(QString, response); SimulatorCard card((SimulatorFileSystem())); - // Fill mCaKeyId for the restricted identification - card.transmit(CommandApdu(QByteArray::fromHex("002241A40F800A04007F00070202030202840129"))); + if (!init.isEmpty()) + { + card.transmit(CommandApdu(QByteArray::fromHex(init))); + } - // Fill mRiKeyId for the restricted identification - card.transmit(CommandApdu(QByteArray::fromHex("002241A40F800A04007F00070202050203840101"))); + const auto& [returnCode, responseApdu] = card.transmit(CommandApdu(QByteArray::fromHex(command))); + QCOMPARE(returnCode, CardReturnCode::OK); + + QRegularExpression re(QStringLiteral("^%1$").arg(response.toLower())); + QVERIFY(re.match(QString::fromLatin1(QByteArray(responseApdu).toHex())).hasMatch()); + } - // Fill mAuxiliaryData with the community id for verify - card.transmit(CommandApdu(QByteArray::fromHex("002281A41867167314060904007f000703010403530702760503150000"))); - ResponseApduResult result {CardReturnCode::OK, ResponseApdu(response)}; - QCOMPARE(card.transmit(CommandApdu(command)), result); + void establishPaceChannel_data() + { + QTest::addColumn("isAuthentication"); + + QTest::newRow("ChangePin") << false; + QTest::newRow("Authentication") << true; } void establishPaceChannel() { + QFETCH(bool, isAuthentication); + SimulatorFileSystem fileSystem; SimulatorCard card(fileSystem); @@ -112,9 +153,14 @@ class test_SimulatorCard output.setPaceReturnCode(CardReturnCode::OK); output.setStatusMseSetAt(QByteArray::fromHex("9000")); output.setEfCardAccess(fileSystem.getEfCardAccess()); - output.setCarCurr(QByteArray("DETESTeID00005")); - output.setIdIcc(QByteArray::fromHex("0102030405060708900A0B0C0D0E0F1011121314")); - QCOMPARE(card.establishPaceChannel(PacePasswordId::PACE_PIN, 6, QByteArray(), QByteArray(), 60), output); + if (isAuthentication) + { + output.setCarCurr(QByteArray("DETESTeID00005")); + output.setIdIcc(QByteArray::fromHex("0102030405060708900A0B0C0D0E0F1011121314")); + } + + const QByteArray data(isAuthentication ? "Chat/CertificateDescription" : ""); + QCOMPARE(card.establishPaceChannel(PacePasswordId::PACE_PIN, 6, data, data), output); } diff --git a/test/qt/card/simulator/test_SimulatorFileSystem.cpp b/test/qt/card/simulator/test_SimulatorFileSystem.cpp index 64be8ef22..cc0756bdc 100644 --- a/test/qt/card/simulator/test_SimulatorFileSystem.cpp +++ b/test/qt/card/simulator/test_SimulatorFileSystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -33,7 +34,7 @@ class test_SimulatorFileSystem ResourceLoader::getInstance().init(); QTest::newRow("Default") << SimulatorFileSystem(); - const QByteArray bytes = TestFileHelper::readFile(":/card/simulatorFiles.json"); + const QByteArray bytes = TestFileHelper::readFile(":/card/simulatorFiles.json"_L1); const auto& files = QJsonDocument::fromJson(bytes).object(); QTest::newRow("Json") << SimulatorFileSystem(files); } @@ -69,7 +70,7 @@ class test_SimulatorFileSystem QTest::ignoreMessage(QtWarningMsg, R"(Skipping file entry. Expected JSON object, got QJsonValue(array, QJsonArray([{"fileId":"0101","shortFileId":"01"}])))"); QTest::ignoreMessage(QtWarningMsg, R"(Skipping file entry. Expected JSON object with 'fileId', 'shortFileId' and 'content', got QJsonObject({"fileId":"0101","shortFileId":"01"}))"); QTest::ignoreMessage(QtWarningMsg, R"(Skipping key entry. Expected JSON object, got QJsonValue(array, QJsonArray([{"id":1}])))"); - QTest::ignoreMessage(QtWarningMsg, R"(Skipping key entry. Expected JSON object with 'id' and 'private', got QJsonObject({"id":1}))"); + QTest::ignoreMessage(QtWarningMsg, R"(Skipping key entry. Expected JSON object with 'id' and 'content', got QJsonObject({"id":1}))"); SimulatorFileSystem fs(doc.object()); } diff --git a/test/qt/card/smart/test_MockSmartEidRestClient.cpp b/test/qt/card/smart/test_MockSmartEidRestClient.cpp index 4ac7b786e..edadcc481 100644 --- a/test/qt/card/smart/test_MockSmartEidRestClient.cpp +++ b/test/qt/card/smart/test_MockSmartEidRestClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "mock/MockSmartEidRestClient.h" @@ -16,6 +16,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -48,7 +49,7 @@ class test_MockSmartEidRestClient void test_preserveUrlPath() { - QVERIFY(qputenv(SMART_EID_MOCK_URL, mServer.getAddress("/foo").toString().toUtf8())); + QVERIFY(qputenv(SMART_EID_MOCK_URL, mServer.getAddress("/foo"_L1).toString().toUtf8())); MockSmartEidRestClient restInterface; QCOMPARE(restInterface.isEnabled(), true); diff --git a/test/qt/card/smart/test_SmartCard.cpp b/test/qt/card/smart/test_SmartCard.cpp index 4fa3826c5..c3348565a 100644 --- a/test/qt/card/smart/test_SmartCard.cpp +++ b/test/qt/card/smart/test_SmartCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include diff --git a/test/qt/card/smart/test_SmartManager.cpp b/test/qt/card/smart/test_SmartManager.cpp index 4560809e7..a33939b0c 100644 --- a/test/qt/card/smart/test_SmartManager.cpp +++ b/test/qt/card/smart/test_SmartManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -26,7 +26,7 @@ class test_SmartManager private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/card/smart/test_SmartReader.cpp b/test/qt/card/smart/test_SmartReader.cpp index 9f471a879..a24469c1a 100644 --- a/test/qt/card/smart/test_SmartReader.cpp +++ b/test/qt/card/smart/test_SmartReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include @@ -20,7 +20,7 @@ class test_SmartReader private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/card/smart/test_SmartReaderManagerPlugIn.cpp b/test/qt/card/smart/test_SmartReaderManagerPlugin.cpp similarity index 83% rename from test/qt/card/smart/test_SmartReaderManagerPlugIn.cpp rename to test/qt/card/smart/test_SmartReaderManagerPlugin.cpp index 5a962dd5e..488b593e3 100644 --- a/test/qt/card/smart/test_SmartReaderManagerPlugIn.cpp +++ b/test/qt/card/smart/test_SmartReaderManagerPlugin.cpp @@ -1,10 +1,10 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "AppSettings.h" #include "ReaderManager.h" -#include "SmartReaderManagerPlugIn.h" +#include "SmartReaderManagerPlugin.h" #include #include @@ -16,7 +16,7 @@ using namespace governikus; Q_DECLARE_METATYPE(ReaderInfo) -class test_SmartReaderManagerPlugIn +class test_SmartReaderManagerPlugin : public QObject { Q_OBJECT @@ -24,7 +24,7 @@ class test_SmartReaderManagerPlugIn private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -40,7 +40,7 @@ class test_SmartReaderManagerPlugIn void initialization() { Env::getSingleton()->callExecute([]{ - SmartReaderManagerPlugIn plugin; + SmartReaderManagerPlugin plugin; plugin.init(); QCOMPARE(plugin.getInfo().isAvailable(), false); QCOMPARE(plugin.getReaders().size(), 0); @@ -52,11 +52,11 @@ class test_SmartReaderManagerPlugIn void availableChanged() { Env::getSingleton()->callExecute([]{ - SmartReaderManagerPlugIn plugin; + SmartReaderManagerPlugin plugin; - QSignalSpy readerAddedSpy(&plugin, &SmartReaderManagerPlugIn::fireReaderAdded); - QSignalSpy readerUpdatedSpy(&plugin, &SmartReaderManagerPlugIn::fireReaderPropertiesUpdated); - QSignalSpy readerRemovedSpy(&plugin, &SmartReaderManagerPlugIn::fireReaderRemoved); + QSignalSpy readerAddedSpy(&plugin, &SmartReaderManagerPlugin::fireReaderAdded); + QSignalSpy readerUpdatedSpy(&plugin, &SmartReaderManagerPlugin::fireReaderPropertiesUpdated); + QSignalSpy readerRemovedSpy(&plugin, &SmartReaderManagerPlugin::fireReaderRemoved); auto& settings = Env::getSingleton()->getGeneralSettings(); QCOMPARE(plugin.getReaders().size(), 0); @@ -95,5 +95,5 @@ class test_SmartReaderManagerPlugIn }; -QTEST_GUILESS_MAIN(test_SmartReaderManagerPlugIn) -#include "test_SmartReaderManagerPlugIn.moc" +QTEST_GUILESS_MAIN(test_SmartReaderManagerPlugin) +#include "test_SmartReaderManagerPlugin.moc" diff --git a/test/qt/card/smart/test_eid_applet_service.cpp b/test/qt/card/smart/test_eid_applet_service.cpp index 25913ab08..4549c8e46 100644 --- a/test/qt/card/smart/test_eid_applet_service.cpp +++ b/test/qt/card/smart/test_eid_applet_service.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "eid_applet_interface.h" diff --git a/test/qt/configuration/test_ProviderConfiguration.cpp b/test/qt/configuration/test_ProviderConfiguration.cpp index 8d6ccff67..8f71e4b91 100644 --- a/test/qt/configuration/test_ProviderConfiguration.cpp +++ b/test/qt/configuration/test_ProviderConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(ProviderConfigurationInfo) @@ -30,33 +31,36 @@ class test_ProviderConfiguration void testProviderUrls() { - const ProviderConfigurationInfo provider1( - /* short name */ QString(), - /* long name */ QString(), - /* long description */ QString(), - /* address */ QStringLiteral("ftp://homepage.com/form"), - /* homepage */ QStringLiteral("ftp://www.homepage.de/bla/bla1") - ); + const ProviderConfigurationInfo provider1({ + /* short name */ QString(), + /* long name */ QString(), + /* long description */ QString(), + /* address */ QStringLiteral("ftp://homepage.com/form"), + /* homepage */ QStringLiteral("ftp://www.homepage.de/bla/bla1"), + QString(), QString(), QString(), QString(), QString(), QString(), {}, QString(), QString() + }); QCOMPARE(provider1.getAddressDomain(), QStringLiteral("homepage.com")); QCOMPARE(provider1.getHomepageBase(), QStringLiteral("www.homepage.de")); - const ProviderConfigurationInfo provider2( - /* short name */ QString(), - /* long name */ QString(), - /* long description */ QString(), - /* address */ QStringLiteral("https://homepage.com/form"), - /* homepage */ QStringLiteral("https://www.homepage.de/bla/bla1") - ); + const ProviderConfigurationInfo provider2({ + /* short name */ QString(), + /* long name */ QString(), + /* long description */ QString(), + /* address */ QStringLiteral("https://homepage.com/form"), + /* homepage */ QStringLiteral("https://www.homepage.de/bla/bla1"), + QString(), QString(), QString(), QString(), QString(), QString(), {}, QString(), QString() + }); QCOMPARE(provider2.getAddressDomain(), QStringLiteral("homepage.com")); QCOMPARE(provider2.getHomepageBase(), QStringLiteral("www.homepage.de")); - const ProviderConfigurationInfo provider3( - /* short name */ QString(), - /* long name */ QString(), - /* long description */ QString(), - /* address */ QStringLiteral("homepage.com/form"), - /* homepage */ QStringLiteral("www.homepage.de/bla/bla1") - ); + const ProviderConfigurationInfo provider3({ + /* short name */ QString(), + /* long name */ QString(), + /* long description */ QString(), + /* address */ QStringLiteral("homepage.com/form"), + /* homepage */ QStringLiteral("www.homepage.de/bla/bla1"), + QString(), QString(), QString(), QString(), QString(), QString(), {}, QString(), QString() + }); QCOMPARE(provider3.getAddressDomain(), QStringLiteral("homepage.com")); QCOMPARE(provider3.getHomepageBase(), QStringLiteral("www.homepage.de")); @@ -69,20 +73,21 @@ class test_ProviderConfiguration void testProviderFields() { // Add image and icon. - const ProviderConfigurationInfo provider( - /* short name */ QStringLiteral("Provider 1"), - /* long name */ QStringLiteral("Provider 1 - long name"), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryA"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}) - ); + const ProviderConfigurationInfo provider({ + /* short name */ QStringLiteral("Provider 1"), + /* long name */ QStringLiteral("Provider 1 - long name"), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryA"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); QCOMPARE(provider.getShortName().toString(), QStringLiteral("Provider 1")); QCOMPARE(provider.getLongName().toString(), QStringLiteral("Provider 1 - long name")); @@ -93,43 +98,47 @@ class test_ProviderConfiguration QCOMPARE(provider.getPhone(), QStringLiteral("0421 123456")); QCOMPARE(provider.getEMail(), QStringLiteral("abc@def.de")); QCOMPARE(provider.getPostalAddress(), QStringLiteral("Am Fallturm 9\n28359 Bremen")); - QVERIFY(provider.getIcon()->lookupPath().endsWith("/CategoryA_button.svg")); - QVERIFY(provider.getImage()->lookupPath().endsWith("/CategoryA_bg.svg")); + QVERIFY(provider.getIcon()->lookupPath().endsWith("/CategoryA_button.svg"_L1)); + QVERIFY(provider.getImage()->lookupPath().endsWith("/CategoryA_bg.svg"_L1)); QCOMPARE(provider.getSubjectUrls(), QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")})); } void checkName() { - const ProviderConfigurationInfo providerEmptyLongname( - /* short name */ QStringLiteral("Provider 1"), - /* long name */ QString(QLatin1String("")), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryA"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")})); + const ProviderConfigurationInfo providerEmptyLongname({ + /* short name */ QStringLiteral("Provider 1"), + /* long name */ QString(QLatin1String("")), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryA"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); QCOMPARE(providerEmptyLongname.getLongName().toString(), QString()); - const ProviderConfigurationInfo providerWithoutShortname( - /* short name */ QString(), - /* long name */ QStringLiteral("Provider 1"), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryA"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")})); + const ProviderConfigurationInfo providerWithoutShortname({ + /* short name */ QString(), + /* long name */ QStringLiteral("Provider 1"), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryA"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); QCOMPARE(providerWithoutShortname.getShortName().toString(), QStringLiteral("Provider 1")); } @@ -140,14 +149,14 @@ class test_ProviderConfiguration const auto& providers = Env::getSingleton()->getProviderConfigurationInfos(); for (const auto& provider : providers) { - QVERIFY(provider.getPhone().isEmpty() || provider.getPhone().startsWith("+49 ")); + QVERIFY(provider.getPhone().isEmpty() || provider.getPhone().startsWith("+49 "_L1)); } } void checkCallCost_data() { - QTest::addColumn("phone"); + QTest::addColumn("phone"); QTest::addColumn("notNull"); QTest::addColumn("freeSeconds"); QTest::addColumn("landlineCentsPerMinute"); @@ -155,33 +164,36 @@ class test_ProviderConfiguration QTest::addColumn("mobileCentsPerMinute"); QTest::addColumn("mobileCentsPerCall"); - QTest::newRow("delimiter") << "+49 1-8/05-123456789" << true << 0 << 14.0 << 0.0 << 42.0 << 0.0; - QTest::newRow("notExisting") << "+49 123456" << false << 0 << 0.0 << 0.0 << 0.0 << 0.0; - QTest::newRow("01") << "+49 1371" << true << 0 << 0.0 << 14.0 << 0.0 << 0.0; - QTest::newRow("02") << "+49 1372" << true << 0 << 14.0 << 0.0 << 0.0 << 0.0; - QTest::newRow("03") << "+49 1376" << true << 0 << 0.0 << 25.0 << 0.0 << 0.0; - QTest::newRow("04") << "+49 1377" << true << 0 << 0.0 << 100.0 << 0.0 << 0.0; - QTest::newRow("05") << "+49 1378" << true << 0 << 0.0 << 50.0 << 0.0 << 0.0; - QTest::newRow("06") << "+49 1801" << true << 0 << 3.9 << 0.0 << 42.0 << 0.0; - QTest::newRow("07") << "+49 1802" << true << 0 << 0.0 << 6.0 << 42.0 << 0.0; - QTest::newRow("08") << "+49 1803" << true << 0 << 9.0 << 0.0 << 42.0 << 0.0; - QTest::newRow("09") << "+49 1804" << true << 0 << 0.0 << 20.0 << 42.0 << 0.0; - QTest::newRow("10") << "+49 1805" << true << 0 << 14.0 << 0.0 << 42.0 << 0.0; - QTest::newRow("11") << "+49 1806" << true << 0 << 0.0 << 20.0 << 0.0 << 60.0; - QTest::newRow("12") << "+49 1807" << true << 30 << 14.0 << 0.0 << 42.0 << 0.0; + QTest::newRow("delimiter") << "+49 1-8/05-123456789"_L1 << true << 0 << 14.0 << 0.0 << 42.0 << 0.0; + QTest::newRow("notExisting") << "+49 123456"_L1 << false << 0 << 0.0 << 0.0 << 0.0 << 0.0; + QTest::newRow("01") << "+49 1371"_L1 << true << 0 << 0.0 << 14.0 << 0.0 << 0.0; + QTest::newRow("02") << "+49 1372"_L1 << true << 0 << 14.0 << 0.0 << 0.0 << 0.0; + QTest::newRow("03") << "+49 1376"_L1 << true << 0 << 0.0 << 25.0 << 0.0 << 0.0; + QTest::newRow("04") << "+49 1377"_L1 << true << 0 << 0.0 << 100.0 << 0.0 << 0.0; + QTest::newRow("05") << "+49 1378"_L1 << true << 0 << 0.0 << 50.0 << 0.0 << 0.0; + QTest::newRow("06") << "+49 1801"_L1 << true << 0 << 3.9 << 0.0 << 42.0 << 0.0; + QTest::newRow("07") << "+49 1802"_L1 << true << 0 << 0.0 << 6.0 << 42.0 << 0.0; + QTest::newRow("08") << "+49 1803"_L1 << true << 0 << 9.0 << 0.0 << 42.0 << 0.0; + QTest::newRow("09") << "+49 1804"_L1 << true << 0 << 0.0 << 20.0 << 42.0 << 0.0; + QTest::newRow("10") << "+49 1805"_L1 << true << 0 << 14.0 << 0.0 << 42.0 << 0.0; + QTest::newRow("11") << "+49 1806"_L1 << true << 0 << 0.0 << 20.0 << 0.0 << 60.0; + QTest::newRow("12") << "+49 1807"_L1 << true << 30 << 14.0 << 0.0 << 42.0 << 0.0; } void checkCallCost() { - QFETCH(QString, phone); + QFETCH(QLatin1String, phone); QFETCH(bool, notNull); QFETCH(int, freeSeconds); QFETCH(double, landlineCentsPerMinute); QFETCH(double, landlineCentsPerCall); QFETCH(double, mobileCentsPerMinute); QFETCH(double, mobileCentsPerCall); - const ProviderConfigurationInfo provider(QString(), QString(), QString(), QString(), QString(), QString(""), phone); + const ProviderConfigurationInfo provider({ + QString(), QString(), QString(), QString(), QString(), ""_L1, phone, + QString(), QString(), QString(), QString(), {}, QString(), QString() + }); const CallCost& callCost = Env::getSingleton()->getCallCost(provider); QVERIFY(notNull || callCost.isNull()); @@ -212,11 +224,11 @@ class test_ProviderConfiguration const auto& address = QUrl(provider.getAddress()); QVERIFY(!address.host().isEmpty()); - QCOMPARE(address.scheme(), QString("https")); + QCOMPARE(address.scheme(), "https"_L1); const auto& homepage = QUrl(provider.getHomepage()); QVERIFY(!homepage.host().isEmpty()); - QCOMPARE(homepage.scheme(), QString("https")); + QCOMPARE(homepage.scheme(), "https"_L1); const auto& subjectUrls = provider.getSubjectUrls(); for (const auto& url : subjectUrls) @@ -225,7 +237,7 @@ class test_ProviderConfiguration { const auto& subjectUrl = QUrl(url); QVERIFY(!subjectUrl.host().isEmpty()); - QCOMPARE(subjectUrl.scheme(), QString("https")); + QCOMPARE(subjectUrl.scheme(), "https"_L1); } } } @@ -233,50 +245,53 @@ class test_ProviderConfiguration void testProvidersAreEqual() { - const ProviderConfigurationInfo provider1( - /* short name */ QStringLiteral("Provider"), - /* long name */ QStringLiteral("Provider - long name"), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryA"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}) - ); - - const ProviderConfigurationInfo provider2( - /* short name */ QStringLiteral("Provider"), - /* long name */ QStringLiteral("Provider - long name"), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryB"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}) - ); - - const ProviderConfigurationInfo provider3( - /* short name */ QStringLiteral("Provider"), - /* long name */ QStringLiteral("Provider - long name"), - /* long description */ QStringLiteral("Provider description long"), - /* address */ QStringLiteral("https://www.homepage.com/form/"), - /* homepage */ QStringLiteral("https://www.homepage.com/"), - /* category */ QStringLiteral("CategoryB"), - /* phone */ QStringLiteral("0421 123456"), - /* email */ QStringLiteral("abc@def.de"), - /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), - /* icon */ QString(), - /* image */ QString(), - /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}) - ); + const ProviderConfigurationInfo provider1({ + /* short name */ QStringLiteral("Provider"), + /* long name */ QStringLiteral("Provider - long name"), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryA"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); + + const ProviderConfigurationInfo provider2({ + /* short name */ QStringLiteral("Provider"), + /* long name */ QStringLiteral("Provider - long name"), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryB"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); + + const ProviderConfigurationInfo provider3({ + /* short name */ QStringLiteral("Provider"), + /* long name */ QStringLiteral("Provider - long name"), + /* long description */ QStringLiteral("Provider description long"), + /* address */ QStringLiteral("https://www.homepage.com/form/"), + /* homepage */ QStringLiteral("https://www.homepage.com/"), + /* category */ QStringLiteral("CategoryB"), + /* phone */ QStringLiteral("0421 123456"), + /* email */ QStringLiteral("abc@def.de"), + /* postal address */ QStringLiteral("Am Fallturm 9\n28359 Bremen"), + /* icon */ QString(), + /* image */ QString(), + /* subjectUrls */ QStringList({QStringLiteral("https://www.autentapp.de/bla1"), QStringLiteral("https://www.autentapp.de/bla1")}), + QString(), QString() + }); QVERIFY(provider1 == provider1); QVERIFY(!(provider1 == provider2)); @@ -302,7 +317,7 @@ class test_ProviderConfiguration } } - QCOMPARE(attachedEidCounter, 19); + QCOMPARE(attachedEidCounter, 20); } @@ -329,7 +344,7 @@ class test_ProviderConfiguration { QUrl url(urlString); QVERIFY(url.isValid()); - QCOMPARE(urlString, QString("https://%1").arg(url.host())); + QCOMPARE(urlString, QStringLiteral("https://%1").arg(url.host())); subjectUrls += urlString; subjectUrlCounter++; @@ -346,25 +361,25 @@ class test_ProviderConfiguration for (const auto& provider : providers) { QVERIFY(QUrl(provider.getAddress()).isValid()); - QVERIFY(!provider.getAddress().endsWith('/')); - QVERIFY(!provider.getAddress().endsWith('#')); + QVERIFY(!provider.getAddress().endsWith('/'_L1)); + QVERIFY(!provider.getAddress().endsWith('#'_L1)); QVERIFY(QUrl(provider.getHomepage()).isValid()); - QVERIFY(!provider.getHomepage().endsWith('/')); - QVERIFY(!provider.getHomepage().endsWith('#')); + QVERIFY(!provider.getHomepage().endsWith('/'_L1)); + QVERIFY(!provider.getHomepage().endsWith('#'_L1)); } } void testInternalIds() { - const QStringList internalIds = {"pinResetService"}; + const QStringList internalIds = {}; const auto& providerConfiguration = Env::getSingleton(); const ProviderConfigurationInfo empty; QVERIFY(providerConfiguration->getProviderInfo(QStringLiteral("nonExistentId")) == empty); for (const auto& id : internalIds) { - QVERIFY2(providerConfiguration->getProviderInfo(id) != empty, qPrintable(QString("Internal ID %1 is not present").arg(id))); + QVERIFY2(providerConfiguration->getProviderInfo(id) != empty, qPrintable(QStringLiteral("Internal ID %1 is not present").arg(id))); } for (const auto& info : providerConfiguration->getProviderConfigurationInfos()) @@ -372,7 +387,7 @@ class test_ProviderConfiguration const auto& id = info.getInternalId(); if (!id.isEmpty()) { - QVERIFY2(internalIds.contains(id), qPrintable(QString("Internal ID %1 is not known to test").arg(id))); + QVERIFY2(internalIds.contains(id), qPrintable(QStringLiteral("Internal ID %1 is not known to test").arg(id))); } } } @@ -388,7 +403,7 @@ class test_ProviderConfiguration const auto& id = info.getInternalId(); if (!id.isEmpty()) { - QVERIFY2(!internalIds.contains(id), qPrintable(QString("Internal IDs must be unique, %1 already present").arg(id))); + QVERIFY2(!internalIds.contains(id), qPrintable(QStringLiteral("Internal IDs must be unique, %1 already present").arg(id))); internalIds << id; } } diff --git a/test/qt/configuration/test_ProviderConfigurationParser.cpp b/test/qt/configuration/test_ProviderConfigurationParser.cpp index 67f3da3f3..6727eff95 100644 --- a/test/qt/configuration/test_ProviderConfigurationParser.cpp +++ b/test/qt/configuration/test_ProviderConfigurationParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -88,16 +89,16 @@ class test_ProviderConfigurationParser auto provider = providers[0]; QCOMPARE(provider.getLongName().toString(), QStringLiteral(":::(bit)kasten")); - LanguageLoader::getInstance().mUsedLocale = QLocale("om"); + LanguageLoader::getInstance().mUsedLocale = QLocale("om"_L1); QCOMPARE(provider.getLongName().toString(), QStringLiteral(":::(bit)kasten")); - LanguageLoader::getInstance().mUsedLocale = QLocale("de"); + LanguageLoader::getInstance().mUsedLocale = QLocale("de"_L1); QCOMPARE(provider.getLongName().toString(), QStringLiteral(":::(bit)-de-kasten")); - LanguageLoader::getInstance().mUsedLocale = QLocale("fr"); + LanguageLoader::getInstance().mUsedLocale = QLocale("fr"_L1); QCOMPARE(provider.getLongName().toString(), QStringLiteral(":::(bit)-fr-kasten")); - LanguageLoader::getInstance().mUsedLocale = QLocale("fr_FR"); + LanguageLoader::getInstance().mUsedLocale = QLocale("fr_FR"_L1); QCOMPARE(provider.getLongName().toString(), QStringLiteral(":::(bit)-fr-kasten")); QCOMPARE(provider.getShortName().toString(), QStringLiteral(":::(bit)-fr-kasten")); @@ -108,8 +109,8 @@ class test_ProviderConfigurationParser QCOMPARE(provider.getEMail(), QString()); QCOMPARE(provider.getPostalAddress(), QString()); QCOMPARE(provider.getCategory(), QStringLiteral("other")); - QVERIFY(provider.getIcon()->lookupPath().endsWith("/other_button.svg")); - QVERIFY(provider.getImage()->lookupPath().endsWith("/other_bg.svg")); + QVERIFY(provider.getIcon()->lookupPath().endsWith("/other_button.svg"_L1)); + QVERIFY(provider.getImage()->lookupPath().endsWith("/other_bg.svg"_L1)); provider = providers[1]; QCOMPARE(provider.getShortName().toString(), QStringLiteral("Selbstauskunft")); @@ -121,8 +122,8 @@ class test_ProviderConfigurationParser QCOMPARE(provider.getEMail(), QStringLiteral("support@ausweisapp.de")); QCOMPARE(provider.getPostalAddress(), QStringLiteral("Governikus GmbH & Co. KG
      - im Auftrag des Bundesamtes fuer Sicherheit in der Informationstechnik -
      Hochschulring 4
      D-28359 Bremen")); QCOMPARE(provider.getCategory(), QStringLiteral("citizen")); - QVERIFY(provider.getIcon()->lookupPath().endsWith("/citizen_button.svg")); - QVERIFY(provider.getImage()->lookupPath().endsWith("/citizen_bg.svg")); + QVERIFY(provider.getIcon()->lookupPath().endsWith("/citizen_button.svg"_L1)); + QVERIFY(provider.getImage()->lookupPath().endsWith("/citizen_bg.svg"_L1)); QVERIFY(provider.getInternalId().isEmpty()); provider = providers[2]; @@ -152,13 +153,13 @@ class test_ProviderConfigurationParser QCOMPARE(providers.size(), 1); auto provider = providers[0]; - QCOMPARE(provider.getShortName().toString(), QString(":::(bit)kasten")); - QCOMPARE(provider.getLongName().toString(), QString(":::(bit)kasten")); - QCOMPARE(provider.getAddress(), QString("https://www.bitkasten.de/")); - QCOMPARE(provider.getPhone(), QString("")); - QCOMPARE(provider.getEMail(), QString("")); - QCOMPARE(provider.getPostalAddress(), QString("")); - QCOMPARE(provider.getCategory(), QString("other")); + QCOMPARE(provider.getShortName().toString(), ":::(bit)kasten"_L1); + QCOMPARE(provider.getLongName().toString(), ":::(bit)kasten"_L1); + QCOMPARE(provider.getAddress(), "https://www.bitkasten.de/"_L1); + QCOMPARE(provider.getPhone(), QString()); + QCOMPARE(provider.getEMail(), QString()); + QCOMPARE(provider.getPostalAddress(), QString()); + QCOMPARE(provider.getCategory(), "other"_L1); } @@ -200,7 +201,7 @@ class test_ProviderConfigurationParser void defaultProviders() { - QByteArray data = TestFileHelper::readFile(QStringLiteral(":/updatable-files/supported-providers.json")); + QByteArray data = TestFileHelper::readFile(":/updatable-files/supported-providers.json"_L1); const auto providers = ProviderConfigurationParser::parseProvider(data); @@ -210,7 +211,7 @@ class test_ProviderConfigurationParser void parseCallCosts() { - QByteArray data = TestFileHelper::readFile(QStringLiteral(":/updatable-files/supported-providers.json")); + QByteArray data = TestFileHelper::readFile(":/updatable-files/supported-providers.json"_L1); const auto callCosts = ProviderConfigurationParser::parseCallCosts(data); @@ -224,8 +225,8 @@ class test_ProviderConfigurationParser QTest::addColumn("majorVersion"); QTest::addColumn("count"); - const int all = 122; - const int withEidSupport = 100; + const int all = 130; + const int withEidSupport = 108; QTest::newRow("win") << QOperatingSystemVersion::Windows << -1 << all; QTest::newRow("mac") << QOperatingSystemVersion::MacOS << -1 << all; QTest::newRow("linux") << QOperatingSystemVersion::Unknown << -1 << all; @@ -242,7 +243,7 @@ class test_ProviderConfigurationParser QFETCH(int, majorVersion); QFETCH(int, count); - QByteArray data = TestFileHelper::readFile(QStringLiteral(":/updatable-files/supported-providers.json")); + QByteArray data = TestFileHelper::readFile(":/updatable-files/supported-providers.json"_L1); const auto providers = ProviderConfigurationParser::parseProvider(data, QOperatingSystemVersion(osType, majorVersion)); QCOMPARE(providers.size(), count); } diff --git a/test/qt/configuration/test_ReaderConfiguration.cpp b/test/qt/configuration/test_ReaderConfiguration.cpp index 3c8453820..6c9ae1572 100644 --- a/test/qt/configuration/test_ReaderConfiguration.cpp +++ b/test/qt/configuration/test_ReaderConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,6 +18,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -39,7 +40,7 @@ class test_ReaderConfiguration private: static const int cCardReadersInConfigurationFile; - QVector mUsbIds; + QList mUsbIds; MockReaderDetector mMockReaderDetector; void checkPlatformsMinMax(const QJsonObject& pObject, const QLatin1String& pValue) @@ -82,14 +83,13 @@ class test_ReaderConfiguration void checkDefaultReader() { #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"); + const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"_L1); #else - const ReaderConfigurationInfo readerSettingsInfo = Env::getSingleton()->getReaderConfigurationInfo("crap"); + const ReaderConfigurationInfo readerSettingsInfo = Env::getSingleton()->getReaderConfigurationInfo("crap"_L1); #endif - QCOMPARE(readerSettingsInfo.getName(), QString("crap")); - QCOMPARE(readerSettingsInfo.getIcon()->getName(), QString("default_reader.png")); - QCOMPARE(readerSettingsInfo.getIconWithNPA()->getName(), QString("default_reader_mit_ausweis.png")); - QCOMPARE(readerSettingsInfo.getPattern(), QString("")); + QCOMPARE(readerSettingsInfo.getName(), "crap"_L1); + QCOMPARE(readerSettingsInfo.getIcon()->getName(), "default_reader.png"_L1); + QCOMPARE(readerSettingsInfo.getPattern(), QString()); } @@ -112,14 +112,17 @@ class test_ReaderConfiguration QTest::newRow("REINER SCT cyberJack RFID komfort FON") << UsbId(0x0C4B, 0x2007) << "REINER SCT cyberJack RFID komfort FON" << "REINER SCT cyberJack RFID komfort FON" << "img_Reiner_SCT_cyberjack_RFID_komfort" << "^REINER SCT cyberJack RFID komfort FON"; QTest::newRow("REINER SCT cyberJack RFID standard") << UsbId(0x0C4B, 0x0500) << "REINER SCT cyberJack RFID standard" << "REINER SCT cyberJack RFID standard" << "img_Reiner_SCT_cyberjack_RFID_standard" << "REINER SCT cyberJack RFID standard"; QTest::newRow("REINER SCT cyberJack RFID basis") << UsbId(0x0C4B, 0x9102) << "REINER SCT cyberJack RFID basis" << "REINER SCT cyberJack RFID basis" << "img_Reiner_SCT_cyberjack_RFID_basis" << "REINER SCT cyberJack RFID basis"; - QTest::newRow("REINER SCT cyberJack wave") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave" << "REINER SCT cyberJack wave" << "img_cyberjack_wave" << "REINER SCT cyberJack wave( USB)?( \\d{1,1})?$"; + QTest::newRow("REINER SCT cyberJack wave") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave" << "REINER SCT cyberJack wave" << "img_cyberjack_wave" << "REINER SCT cyberJack wave"; - QTest::newRow("KOBIL IDToken") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken" << "KOBIL IDToken" << "img_KOBIL_ID_Token" << "^KOBIL (Systems )?IDToken( \\d{1,1})?$"; + QTest::newRow("KOBIL IDToken") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken" << "KOBIL IDToken" << "img_KOBIL_ID_Token" << "^KOBIL (Systems )?IDToken"; - QTest::newRow("Identiv SDI011") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader" << "img_Identive_SDI011" << "^(SCM Microsystems Inc. )?SDI011G? ((Contactless Reader( 0)?)|((USB Smart Card|Contactless) Reader\\([12]\\)))$"; + QTest::newRow("Identiv SDI011B") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader" << "img_Identive_SDI011" << "^(SCM Microsystems Inc. )?SDI011G? ((Contactless Reader( 0)?)|((USB Smart Card|Contactless) Reader\\([12]\\)))$"; + QTest::newRow("Identiv SDI011C") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader" << "img_Identive_SDI011" << "^(SCM Microsystems Inc. )?SDI011G? ((Contactless Reader( 0)?)|((USB Smart Card|Contactless) Reader\\([12]\\)))$"; QTest::newRow("Identiv SCL011") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader" << "img_Identive_SCL011" << "^(SCM Microsystems Inc. )?SCL011G? Contactless Reader( 0)?$"; - QTest::newRow("ACS-ACR1281U") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader" << "ACS ACR1281U" << "img_ACS_ACR1281U" << "ACS ACR1281 PICC Reader( 0)?"; + QTest::newRow("ACS ACR1281U") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader" << "ACS ACR1281U" << "img_ACS_ACR1281U" << "ACS ACR1281 PICC Reader( 0)?"; + QTest::newRow("ACS ACR1281U-C1") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader PICC 0" << "ACS ACR1281U-C1" << "img_ACS_ACR1281U" << "ACS ACR1281 1S Dual Reader (PICC 0|\\(1\\))"; + QTest::newRow("ACS-ACR1581U-C1") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader PICC" << "ACS ACR1581U-C1" << "img_ACS_ACR1581U-C1" << "ACS ACR1581 1S Dual Reader (PICC|\\(1\\))( 0)?"; QTest::newRow("HID OMNIKEY 5021") << UsbId(0x076B, 0x5340) << "OMNIKEY CardMan 5x21-CL 0" << "HID OMNIKEY 5021-CL" << "img_HID_Omnikey_Mobile_Reader_502X_CL" << "OMNIKEY CardMan 5x21-CL 0|OMNIKEY CardMan \\(076B:5340\\) 5021 CL"; QTest::newRow("HID OMNIKEY 5022") << UsbId(0x076B, 0x5022) << "HID Global OMNIKEY 5022 Smart Card Reader 0" << "HID OMNIKEY 5022-CL" << "img_HID_Omnikey_Mobile_Reader_502X_CL" << "HID Global OMNIKEY 5022 Smart Card Reader( 0)?$"; @@ -133,14 +136,14 @@ class test_ReaderConfiguration QTest::newRow("Gemalto-Prox-SU") << UsbId(0x08E6, 0x5504) << "Gemalto Prox-SU Contactless_" << "Gemalto Prox-SU Contactless" << "img_Gemalto_Prox_SU" << R"(Gemalto Prox( |-)SU( Contactless_| USB PC LinkReader(\(1\)|\(2\))))"; QTest::newRow("Identiv-SCL-3711") << UsbId(0x04E6, 0x5591) << "SCM Microsystems SCL3711 reader & NFC device 0" << "Identiv SCL3711" << "img_Identive_SCL3711" << "(SCM Microsystems SCL3711 reader & NFC device 0|SCL3711 Reader and NFC device)"; - QTest::newRow("Identiv-3700-F") << UsbId(0x04E6, 0x5790) << "Identiv CLOUD 3700 F Contactless Reader 0" << "Identiv 3700 F" << "img_Identive_XXXX_F" << "^Identiv (uTrust|cloud|CLOUD) 3700 F (Contactless|CL) Reader( 0)?$"; + QTest::newRow("Identiv-3700-F") << UsbId(0x04E6, 0x5790) << "Identiv CLOUD 3700 F Contactless Reader 0" << "Identiv 3700 F" << "img_Identive_XXXX_F" << "^Identiv[e]? (uTrust|cloud|CLOUD) 3700 F (Contactless|CL) Reader( 0)?$"; QTest::newRow("Identiv 3720 F") << UsbId(0x04E6, 0x5612) << "Identiv uTrust 3720 Contactless Reader 0" << "Identiv 3720 F" << "img_Identive_XXXX_F" << "^Identiv (uTrust|cloud|CLOUD) 3720 (Contactless|CL) Reader( 0|\\(1\\))$"; QTest::newRow("Identiv 3721 F") << UsbId(0x04E6, 0x5613) << "Identiv uTrust 3721 Contactless Reader 0" << "Identiv 3721 F" << "img_Identive_XXXX_F" << "^Identiv (uTrust|cloud|CLOUD) 3721 (Contactless|CL) Reader( 0|\\(1\\))$"; QTest::newRow("Identiv-Cloud-4700-F") << UsbId(0x04E6, 0x5720) << "Identive CLOUD 4700 F Contactless Reader 1" << "Identiv Cloud 4700 F" << "img_Identive_Cloud_4700_F" << "(Identive CLOUD 4700 F Contactless Reader( 0| 1)|Identiv uTrust 4700 F Dual Interface Reader\\(2\\))"; QTest::newRow("Identiv 4701 F") << UsbId(0x04E6, 0x5724) << "Identiv CLOUD 4701 F Contactless Reader 0" << "Identiv 4701 F" << "img_Identive_4701_F" << "^Identiv (uTrust|cloud|CLOUD) 4701 F (Contactless|CL|Dual Interface) Reader( 0| 1|\\(1\\)|\\(2\\))?$"; QTest::newRow("Cherry-TC-1200-data") << UsbId(0x046A, 0x0091) << "Cherry TC 1200" << "Cherry TC-1200" << "img_Cherry_TC_1200" << "(Cherry TC 1200($|[^-])|TC 12xx-CL 0|Cherry SC Reader \\(046A:0091\\))"; - QTest::newRow("Cherry-TC-1300-data") << UsbId(0x046A, 0x0092) << "Cherry TC 1300" << "Cherry TC-1300" << "img_Cherry_TC_1300" << "(Cherry TC 1300|Cherry Smartcard Terminal TC 13xx-CL 0|Cherry SC Reader \\(046A:0092\\))"; + QTest::newRow("Cherry-TC-1300-data") << UsbId(0x046A, 0x0092) << "Cherry SC Reader (046A:0092)(1)" << "Cherry TC-1300" << "img_Cherry_TC_1300" << "(Cherry Smartcard Terminal TC 13xx-CL 0|Cherry SC Reader \\(046A:0092\\))"; QTest::newRow("Cherry-ST-1275-data") << UsbId(0x046A, 0x0072) << "Cherry SmartTerminal XX7X-RF 0" << "Cherry ST-1275" << "img_Cherry_ST_1275" << "(Cherry ST-1275|Cherry SmartTerminal XX7X-RF 0)"; QTest::newRow("Cherry-sercure Board") << UsbId(0x046A, 0x01A2) << "Cherry GmbH CHERRY SECURE BOARD 1.0" << "Cherry Secure Board 1.0" << "img_Cherry_secure_board" << "Cherry GmbH CHERRY SECURE BOARD 1.0( 0)?$"; @@ -158,13 +161,12 @@ class test_ReaderConfiguration mUsbIds += usbId; #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"); + const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"_L1); #else const ReaderConfigurationInfo readerSettingsInfo = Env::getSingleton()->getReaderConfigurationInfo(readerName); #endif QCOMPARE(readerSettingsInfo.getName(), readerViewName); - QCOMPARE(readerSettingsInfo.getIcon()->getName(), readerIcon + ".png"); - QCOMPARE(readerSettingsInfo.getIconWithNPA()->getName(), readerIcon + "_mit_ausweis.png"); + QCOMPARE(readerSettingsInfo.getIcon()->getName(), readerIcon + ".png"_L1); QCOMPARE(readerSettingsInfo.getPattern(), readerPattern); } @@ -174,8 +176,6 @@ class test_ReaderConfiguration QTest::addColumn("usbId"); QTest::addColumn("readerName"); QTest::addColumn("readerViewName"); - QTest::addColumn("readerIcon"); - QTest::addColumn("readerPattern"); QTest::newRow("UU") << UsbId(0xFFFF, 0xFFFF) << "crap" << "crap"; @@ -186,93 +186,123 @@ class test_ReaderConfiguration QTest::newRow("Simulator") << UsbId(0x0000, 0x0002) << "Simulator" << "Simulator"; - QTest::newRow("REINER SCT cyberJack RFID komfort-windows-7-10") << UsbId(0x0C4B, 0x0501) << "REINER SCT cyberJack RFID komfort USB 1" << "REINER SCT cyberJack RFID komfort"; - QTest::newRow("REINER SCT cyberJack RFID komfort-macosx-10.13-11.0") << UsbId(0x0C4B, 0x0501) << "REINER SCT cyberJack RFID komfort" << "REINER SCT cyberJack RFID komfort"; + QTest::newRow("REINER SCT cyberJack RFID komfort-windows-10-11") << UsbId(0x0C4B, 0x0501) << "REINER SCT cyberJack RFID komfort USB 1" << "REINER SCT cyberJack RFID komfort"; + QTest::newRow("REINER SCT cyberJack RFID komfort-macosx-12-15") << UsbId(0x0C4B, 0x0501) << "REINER SCT cyberJack RFID komfort" << "REINER SCT cyberJack RFID komfort"; QTest::newRow("REINER SCT cyberJack RFID komfort-FON-windows-7-10") << UsbId(0x0C4B, 0x2007) << "REINER SCT cyberJack RFID komfort FON USB 52" << "REINER SCT cyberJack RFID komfort FON"; QTest::newRow("REINER SCT cyberJack RFID komfort-FON-macosx-10.13-11.0") << UsbId(0x0C4B, 0x2007) << "REINER SCT cyberJack RFID komfort FON" << "REINER SCT cyberJack RFID komfort FON"; - QTest::newRow("REINER SCT cyberJack RFID standard-windows-7-10") << UsbId(0x0C4B, 0x0500) << "REINER SCT cyberJack RFID standard USB 1" << "REINER SCT cyberJack RFID standard"; - QTest::newRow("REINER SCT cyberJack RFID standard-macosx-10.13-11.0") << UsbId(0x0C4B, 0x0500) << "REINER SCT cyberJack RFID standard" << "REINER SCT cyberJack RFID standard"; + QTest::newRow("REINER SCT cyberJack RFID standard-windows-10-11") << UsbId(0x0C4B, 0x0500) << "REINER SCT cyberJack RFID standard USB 1" << "REINER SCT cyberJack RFID standard"; + QTest::newRow("REINER SCT cyberJack RFID standard-macosx-12-15") << UsbId(0x0C4B, 0x0500) << "REINER SCT cyberJack RFID standard" << "REINER SCT cyberJack RFID standard"; - QTest::newRow("REINER SCT cyberJack RFID basis-windows-7-10") << UsbId(0x0C4B, 0x9102) << "REINER SCT cyberJack RFID basis 0" << "REINER SCT cyberJack RFID basis"; - QTest::newRow("REINER SCT cyberJack RFID basis-macosx-10.13-11.0") << UsbId(0x0C4B, 0x9102) << "REINER SCT cyberJack RFID basis" << "REINER SCT cyberJack RFID basis"; + QTest::newRow("REINER SCT cyberJack RFID basis-windows-10-11") << UsbId(0x0C4B, 0x9102) << "REINER SCT cyberJack RFID basis 0" << "REINER SCT cyberJack RFID basis"; + QTest::newRow("REINER SCT cyberJack RFID basis-macosx-11-15") << UsbId(0x0C4B, 0x9102) << "REINER SCT cyberJack RFID basis" << "REINER SCT cyberJack RFID basis"; QTest::newRow("REINER SCT cyberJack wave-windows-10-11-1") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave 0" << "REINER SCT cyberJack wave"; QTest::newRow("REINER SCT cyberJack wave-windows-10-11-1") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave 1" << "REINER SCT cyberJack wave"; QTest::newRow("REINER SCT cyberJack wave-windows-10-11-2") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave USB 1" << "REINER SCT cyberJack wave"; - QTest::newRow("REINER SCT cyberJack wave-macosx-11-13") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave" << "REINER SCT cyberJack wave"; - - QTest::newRow("KOBIL IDToken-windows-7-10-1") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 0" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-windows-7-10-2") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 1" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-windows-7-10-3") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 2" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-windows-7-10-4") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-macosx-10.13-11.0-1") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-macosx-10.13-11.0-2") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken 0" << "KOBIL IDToken"; - QTest::newRow("KOBIL IDToken-macosx-10.13-11.0-3") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken 1" << "KOBIL IDToken"; - - QTest::newRow("Identiv SDI011-windows-10-11-1") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-windows-10-11-2") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Smart Card Reader 0" << "SCM Microsystems Inc. SDI011 Smart Card Reader 0"; - QTest::newRow("Identiv SDI011-windows-10-11-3") << UsbId(0x04E6, 0x512B) << "SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-windows-10-11-4") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011G Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-windows-10-11-5") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011G Smart Card Reader 0" << "SCM Microsystems Inc. SDI011G Smart Card Reader 0"; - QTest::newRow("Identiv SDI011-macosx-11-13") << UsbId(0x04E6, 0x512B) << "SDI011 USB Smart Card Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-macosx-11-13") << UsbId(0x04E6, 0x512B) << "SDI011 USB Smart Card Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-macosx-11-13-1") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; - QTest::newRow("Identiv SDI011-macosx-11-13-2") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("REINER SCT cyberJack wave-macosx-12-15") << UsbId(0x0C4B, 0x0505) << "REINER SCT cyberJack wave" << "REINER SCT cyberJack wave"; + + QTest::newRow("KOBIL IDToken-windows-10-11-1") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 0" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-windows-10-11-2") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 1" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-windows-10-11-3") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken 2" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-windows-10-11-4") << UsbId(0x0D46, 0x301D) << "KOBIL IDToken" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-macosx-12-14-1") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-macosx-12-14-2") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken 0" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-macosx-12-14-3") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken 1" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-unknown-1") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken (NS1252PT18716) 01 00" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-unknown-2") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken (NS1228PT186BD) 01 00" << "KOBIL IDToken"; + QTest::newRow("KOBIL IDToken-unknown-3") << UsbId(0x0D46, 0x301D) << "KOBIL Systems IDToken (0123456789ABCD) 02 01" << "KOBIL IDToken"; + + QTest::newRow("Identiv SDI011B-windows-10-11-1") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-windows-10-11-2") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Smart Card Reader 0" << "SCM Microsystems Inc. SDI011 Smart Card Reader 0"; + QTest::newRow("Identiv SDI011B-windows-10-11-3") << UsbId(0x04E6, 0x512B) << "SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-windows-10-11-4") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011G Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-windows-10-11-5") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011G Smart Card Reader 0" << "SCM Microsystems Inc. SDI011G Smart Card Reader 0"; + QTest::newRow("Identiv SDI011B-macosx-12-14") << UsbId(0x04E6, 0x512B) << "SDI011 USB Smart Card Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-macosx-12-14") << UsbId(0x04E6, 0x512B) << "SDI011 USB Smart Card Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-macosx-12-14-1") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011B-macosx-12-14-2") << UsbId(0x04E6, 0x512B) << "SCM Microsystems Inc. SDI011 Contactless Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + + QTest::newRow("Identiv SDI011C-windows-10-11-1") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011 Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-windows-10-11-2") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011 Smart Card Reader 0" << "SCM Microsystems Inc. SDI011 Smart Card Reader 0"; + QTest::newRow("Identiv SDI011C-windows-10-11-3") << UsbId(0x04E6, 0x512C) << "SDI011 Contactless Reader" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-windows-10-11-4") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011G Contactless Reader 0" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-windows-10-11-5") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011G Smart Card Reader 0" << "SCM Microsystems Inc. SDI011G Smart Card Reader 0"; + QTest::newRow("Identiv SDI011C-macosx-12-14") << UsbId(0x04E6, 0x512C) << "SDI011 USB Smart Card Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-macosx-12-14") << UsbId(0x04E6, 0x512C) << "SDI011 USB Smart Card Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-macosx-12-14-1") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011 Contactless Reader(1)" << "Identiv SDI011 Dual Interface Smart Card Reader"; + QTest::newRow("Identiv SDI011C-macosx-12-14-2") << UsbId(0x04E6, 0x512C) << "SCM Microsystems Inc. SDI011 Contactless Reader(2)" << "Identiv SDI011 Dual Interface Smart Card Reader"; QTest::newRow("Identiv SCL011-windows-10-11-1") << UsbId(0x04E6, 0x5292) << "SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader"; QTest::newRow("Identiv SCL011-windows-10-11-2") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL010 Contactless Reader" << "SCM Microsystems Inc. SCL010 Contactless Reader"; QTest::newRow("Identiv SCL011-windows-10-11-3") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL011 Contactless Reader 0" << "Identiv SCL01x Contactless Smart Card Reader"; QTest::newRow("Identiv SCL011-windows-10-11-4") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL011G Contactless Reader 0" << "Identiv SCL01x Contactless Smart Card Reader"; - QTest::newRow("Identiv SCL011-macosx-11-13-1") << UsbId(0x04E6, 0x5292) << "SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader"; - QTest::newRow("Identiv SCL011-macosx-11-13-2") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader"; - - QTest::newRow("ACS-ACR1281U-windows-7-10") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader 0" << "ACS ACR1281U"; - QTest::newRow("ACS-ACR1281U-macosx-10.13-11.0") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader" << "ACS ACR1281U"; + QTest::newRow("Identiv SCL011-macosx-12-14-1") << UsbId(0x04E6, 0x5292) << "SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader"; + QTest::newRow("Identiv SCL011-macosx-12-14-2") << UsbId(0x04E6, 0x5292) << "SCM Microsystems Inc. SCL011 Contactless Reader" << "Identiv SCL01x Contactless Smart Card Reader"; + + QTest::newRow("ACS-ACR1281U-windows-10-11") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader 0" << "ACS ACR1281U"; + QTest::newRow("ACS-ACR1281U-macosx-12-14") << UsbId(0x072F, 0x0901) << "ACS ACR1281 PICC Reader" << "ACS ACR1281U"; + + QTest::newRow("ACS-ACR1281U-C1-windows-10-11-1") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader PICC 0" << "ACS ACR1281U-C1"; + QTest::newRow("ACS-ACR1281U-C1-windows-10-11-2") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader ICC 0" << "ACS ACR1281 1S Dual Reader ICC 0"; + QTest::newRow("ACS-ACR1281U-C1-windows-10-11-3") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader SAM 0" << "ACS ACR1281 1S Dual Reader SAM 0"; + QTest::newRow("ACS-ACR1281U-C1-macosx-12-14-1") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader (1)" << "ACS ACR1281U-C1"; + QTest::newRow("ACS-ACR1281U-C1-macosx-12-14-2") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader (2)" << "ACS ACR1281 1S Dual Reader (2)"; + QTest::newRow("ACS-ACR1281U-C1-macosx-12-14-3") << UsbId(0x072F, 0x2224) << "ACS ACR1281 1S Dual Reader (3)" << "ACS ACR1281 1S Dual Reader (3)"; + + QTest::newRow("ACS-ACR1581-windows-10-11-1") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader PICC 0" << "ACS ACR1581U-C1"; + QTest::newRow("ACS-ACR1581-windows-10-11-2") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader ICC 0" << "ACS ACR1581 1S Dual Reader ICC 0"; + QTest::newRow("ACS-ACR1581-windows-10-11-3") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader SAM 0" << "ACS ACR1581 1S Dual Reader SAM 0"; + QTest::newRow("ACS-ACR1581-macosx-12-13-1") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader (1)" << "ACS ACR1581U-C1"; + QTest::newRow("ACS-ACR1581-macosx-12-13-2") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader (2)" << "ACS ACR1581 1S Dual Reader (2)"; + QTest::newRow("ACS-ACR1581-macosx-12-13-3") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader (3)" << "ACS ACR1581 1S Dual Reader (3)"; + QTest::newRow("ACS-ACR1581-macosx-14-1") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader PICC" << "ACS ACR1581U-C1"; + QTest::newRow("ACS-ACR1581-macosx-14-2") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader ICC" << "ACS ACR1581 1S Dual Reader ICC"; + QTest::newRow("ACS-ACR1581-macosx-14-3") << UsbId(0x072F, 0x2301) << "ACS ACR1581 1S Dual Reader SAM" << "ACS ACR1581 1S Dual Reader SAM"; QTest::newRow("HID OMNIKEY 5021-windows-10-11") << UsbId(0x076B, 0x5340) << "OMNIKEY CardMan 5x21-CL 0" << "HID OMNIKEY 5021-CL"; - QTest::newRow("HID OMNIKEY 5021-macosx-11-13") << UsbId(0x076B, 0x5340) << "OMNIKEY CardMan (076B:5340) 5021 CL" << "HID OMNIKEY 5021-CL"; + QTest::newRow("HID OMNIKEY 5021-macosx-12-14") << UsbId(0x076B, 0x5340) << "OMNIKEY CardMan (076B:5340) 5021 CL" << "HID OMNIKEY 5021-CL"; QTest::newRow("HID OMNIKEY 5022-windows-10-11") << UsbId(0x076B, 0x5022) << "HID Global OMNIKEY 5022 Smart Card Reader 0" << "HID OMNIKEY 5022-CL"; - QTest::newRow("HID OMNIKEY 5022-macosx-11-13") << UsbId(0x076B, 0x5022) << "HID Global OMNIKEY 5022 Smart Card Reader" << "HID OMNIKEY 5022-CL"; + QTest::newRow("HID OMNIKEY 5022-macosx-12-14") << UsbId(0x076B, 0x5022) << "HID Global OMNIKEY 5022 Smart Card Reader" << "HID OMNIKEY 5022-CL"; QTest::newRow("HID OMNIKEY 5321 v2-windows-10-11-1") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan 5x21 0" << "OMNIKEY CardMan 5x21 0"; QTest::newRow("HID OMNIKEY 5321 v2-windows-10-11-2") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan 5x21-CL 0" << "HID OMNIKEY 5321 v2"; - QTest::newRow("HID OMNIKEY 5321 v2-macosx-11-14-1") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan (076B:5321) 5321(1)" << "HID OMNIKEY 5321 v2"; - QTest::newRow("HID OMNIKEY 5321 v2-macosx-11-14-2") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan (076B:5321) 5321(2)" << "HID OMNIKEY 5321 v2"; + QTest::newRow("HID OMNIKEY 5321 v2-macosx-12-14-1") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan (076B:5321) 5321(1)" << "HID OMNIKEY 5321 v2"; + QTest::newRow("HID OMNIKEY 5321 v2-macosx-12-14-2") << UsbId(0x076B, 0x5321) << "OMNIKEY CardMan (076B:5321) 5321(2)" << "HID OMNIKEY 5321 v2"; QTest::newRow("HID OMNIKEY 5421-windows-10-11-1") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan 5x21 0" << "OMNIKEY CardMan 5x21 0"; QTest::newRow("HID OMNIKEY 5421-windows-10-11-2") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan 5x21-CL 0" << "HID OMNIKEY 5421"; QTest::newRow("HID OMNIKEY 5421-windows-10-11-3") << UsbId(0x076B, 0x5421) << "OMNIKEY Smart Card Reader USB 0" << "HID OMNIKEY 5421"; - QTest::newRow("HID OMNIKEY 5421-macosx-11-13-1") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan (076B:5421) 5421(1)" << "HID OMNIKEY 5421"; - QTest::newRow("HID OMNIKEY 5421-macosx-11-13-2") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan (076B:5421) 5421(2)" << "HID OMNIKEY 5421"; + QTest::newRow("HID OMNIKEY 5421-macosx-12-14-1") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan (076B:5421) 5421(1)" << "HID OMNIKEY 5421"; + QTest::newRow("HID OMNIKEY 5421-macosx-12-14-2") << UsbId(0x076B, 0x5421) << "OMNIKEY CardMan (076B:5421) 5421(2)" << "HID OMNIKEY 5421"; QTest::newRow("HID OMNIKEY 5422-windows-10-11-1") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY 5422 Smartcard Reader 0" << "HID Global OMNIKEY 5422 Smartcard Reader 0"; QTest::newRow("HID OMNIKEY 5422-windows-10-11-2") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY 5422CL Smartcard Reader 0" << "HID OMNIKEY 5422"; - QTest::newRow("HID OMNIKEY 5422-macosx-11-13-1") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader (1)" << "HID OMNIKEY 5422"; - QTest::newRow("HID OMNIKEY 5422-macosx-11-13-2") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader (2)" << "HID OMNIKEY 5422"; - QTest::newRow("HID OMNIKEY 5422-macosx-11-13-3") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader(1)" << "HID OMNIKEY 5422"; - QTest::newRow("HID OMNIKEY 5422-macosx-11-13-4") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader(2)" << "HID OMNIKEY 5422"; + QTest::newRow("HID OMNIKEY 5422-macosx-12-14-1") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader (1)" << "HID OMNIKEY 5422"; + QTest::newRow("HID OMNIKEY 5422-macosx-12-14-2") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader (2)" << "HID OMNIKEY 5422"; + QTest::newRow("HID OMNIKEY 5422-macosx-12-14-3") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader(1)" << "HID OMNIKEY 5422"; + QTest::newRow("HID OMNIKEY 5422-macosx-12-14-4") << UsbId(0x076B, 0x5422) << "HID Global OMNIKEY Smartcard Reader(2)" << "HID OMNIKEY 5422"; - QTest::newRow("FEIG OBID myAXXESS RFID-Reader-windows-7-10") << UsbId(0x0AB1, 0x0003) << "FEIG ELECTRONIC GmbH OBID myAXXESS basic Slot:CL 358334430" << "OBID RFID-Reader"; + QTest::newRow("FEIG OBID myAXXESS RFID-Reader-windows-10-11") << UsbId(0x0AB1, 0x0003) << "FEIG ELECTRONIC GmbH OBID myAXXESS basic Slot:CL 358334430" << "OBID RFID-Reader"; - QTest::newRow("Gemalto-Prox-DU-windows-7-10-1") << UsbId(0x08E6, 0x5503) << "Gemalto Prox-DU Contactless_10900383 0" << "Gemalto Prox-DU HID"; - QTest::newRow("Gemalto-Prox-DU-windows-7-10-2") << UsbId(0x08E6, 0x5503) << "Gemalto Prox-DU Contact_10900383 0" << "Gemalto Prox-DU Contact_10900383 0"; - QTest::newRow("Gemalto-Prox-DU-windows-macosx-10.13-11.0-1") << UsbId(0x08E6, 0x5503) << "Gemalto Prox Dual USB PC Link Reader(1)" << "Gemalto Prox-DU HID"; - QTest::newRow("Gemalto-Prox-DU-windows-macosx-10.13-11.0-2") << UsbId(0x08E6, 0x5503) << "Gemalto Prox Dual USB PC Link Reader(2)" << "Gemalto Prox-DU HID"; + QTest::newRow("Gemalto-Prox-DU-windows-10-11-1") << UsbId(0x08E6, 0x5503) << "Gemalto Prox-DU Contactless_10900383 0" << "Gemalto Prox-DU HID"; + QTest::newRow("Gemalto-Prox-DU-windows-10-11-2") << UsbId(0x08E6, 0x5503) << "Gemalto Prox-DU Contact_10900383 0" << "Gemalto Prox-DU Contact_10900383 0"; + QTest::newRow("Gemalto-Prox-DU-windows-macosx-12-14-1") << UsbId(0x08E6, 0x5503) << "Gemalto Prox Dual USB PC Link Reader(1)" << "Gemalto Prox-DU HID"; + QTest::newRow("Gemalto-Prox-DU-windows-macosx-12-14-2") << UsbId(0x08E6, 0x5503) << "Gemalto Prox Dual USB PC Link Reader(2)" << "Gemalto Prox-DU HID"; - QTest::newRow("Gemalto-Prox-SU-windows-7-10-1") << UsbId(0x08E6, 0x5504) << "Gemalto Prox-SU Contactless_10800004 0" << "Gemalto Prox-SU Contactless"; - QTest::newRow("Gemalto-Prox-SU-windows-7-10-2") << UsbId(0x08E6, 0x5504) << "Gemalto Prox-SU Contact_10800004 0" << "Gemalto Prox-SU Contact_10800004 0"; - QTest::newRow("Gemalto-Prox-SU-windows-macosx-10.13-11.0-1") << UsbId(0x08E6, 0x5504) << "Gemalto Prox SU USB PC LinkReader(1)" << "Gemalto Prox-SU Contactless"; - QTest::newRow("Gemalto-Prox-SU-windows-macosx-10.13-11.0-2") << UsbId(0x08E6, 0x5504) << "Gemalto Prox SU USB PC LinkReader(2)" << "Gemalto Prox-SU Contactless"; + QTest::newRow("Gemalto-Prox-SU-windows-10-11-1") << UsbId(0x08E6, 0x5504) << "Gemalto Prox-SU Contactless_10800004 0" << "Gemalto Prox-SU Contactless"; + QTest::newRow("Gemalto-Prox-SU-windows-10-11-2") << UsbId(0x08E6, 0x5504) << "Gemalto Prox-SU Contact_10800004 0" << "Gemalto Prox-SU Contact_10800004 0"; + QTest::newRow("Gemalto-Prox-SU-windows-macosx-12-14-1") << UsbId(0x08E6, 0x5504) << "Gemalto Prox SU USB PC LinkReader(1)" << "Gemalto Prox-SU Contactless"; + QTest::newRow("Gemalto-Prox-SU-windows-macosx-12-14-2") << UsbId(0x08E6, 0x5504) << "Gemalto Prox SU USB PC LinkReader(2)" << "Gemalto Prox-SU Contactless"; QTest::newRow("Identiv-SCL-3711-windows-10-11") << UsbId(0x04E6, 0x5591) << "SCM Microsystems SCL3711 reader & NFC device 0" << "Identiv SCL3711"; - QTest::newRow("Identiv-SCL-3711--F-macosx-11-13") << UsbId(0x04E6, 0x5591) << "SCL3711 Reader and NFC device" << "Identiv SCL3711"; - QTest::newRow("Identiv-SCL-3711--F-macosx-11-13") << UsbId(0x04E6, 0x5591) << "SCL3711 Reader and NFC device" << "Identiv SCL3711"; + QTest::newRow("Identiv-SCL-3711--F-macosx-12-14") << UsbId(0x04E6, 0x5591) << "SCL3711 Reader and NFC device" << "Identiv SCL3711"; + QTest::newRow("Identiv-SCL-3711--F-macosx-12-14") << UsbId(0x04E6, 0x5591) << "SCL3711 Reader and NFC device" << "Identiv SCL3711"; QTest::newRow("Identiv-3700-F-windows-10-11") << UsbId(0x04E6, 0x5790) << "Identiv CLOUD 3700 F Contactless Reader 0" << "Identiv 3700 F"; - QTest::newRow("Identiv-3700-F-macosx-11-13") << UsbId(0x04E6, 0x5790) << "Identiv uTrust 3700 F CL Reader" << "Identiv 3700 F"; + QTest::newRow("Identiv-3700-F-macosx-12-14") << UsbId(0x04E6, 0x5790) << "Identiv uTrust 3700 F CL Reader" << "Identiv 3700 F"; QTest::newRow("Identiv-3700-F-generic-1") << UsbId(0x04E6, 0x5790) << "Identiv uTrust 3700 F CL Reader 0" << "Identiv 3700 F"; QTest::newRow("Identiv-3700-F-generic-2") << UsbId(0x04E6, 0x5790) << "Identiv cloud 3700 F Contactless Reader 0" << "Identiv 3700 F"; QTest::newRow("Identiv-3700-F-generic-3") << UsbId(0x04E6, 0x5790) << "Identiv uTrust 3700 F Contactless Reader 0" << "Identiv 3700 F"; @@ -280,7 +310,7 @@ class test_ReaderConfiguration QTest::newRow("Identiv-3700-F-generic-5") << UsbId(0x04E6, 0x5790) << "Identiv cloud 3700 F CL Reader" << "Identiv 3700 F"; QTest::newRow("Identiv-3720-F-windows-10-11") << UsbId(0x04E6, 0x5612) << "Identiv uTrust 3720 Contactless Reader 0" << "Identiv 3720 F"; - QTest::newRow("Identiv-3720-F-macosx-11-13") << UsbId(0x04E6, 0x5612) << "Identiv uTrust 3720 Contactless Reader(1)" << "Identiv 3720 F"; + QTest::newRow("Identiv-3720-F-macosx-12-14") << UsbId(0x04E6, 0x5612) << "Identiv uTrust 3720 Contactless Reader(1)" << "Identiv 3720 F"; QTest::newRow("Identiv-3720-F-generic-1") << UsbId(0x04E6, 0x5612) << "Identiv cloud 3720 Contactless Reader 0" << "Identiv 3720 F"; QTest::newRow("Identiv-3720-F-generic-2") << UsbId(0x04E6, 0x5612) << "Identiv cloud 3720 Contactless Reader(1)" << "Identiv 3720 F"; QTest::newRow("Identiv-3720-F-generic-3") << UsbId(0x04E6, 0x5612) << "Identiv cloud 3720 CL Reader 0" << "Identiv 3720 F"; @@ -293,7 +323,7 @@ class test_ReaderConfiguration QTest::newRow("Identiv-3720-F-generic-10") << UsbId(0x04E6, 0x5612) << "Identiv uTrust 3720 CL Reader(1)" << "Identiv 3720 F"; QTest::newRow("Identiv-uTrust-3721-F-windows-10-11") << UsbId(0x04E6, 0x5613) << "Identiv uTrust 3721 Contactless Reader 0" << "Identiv 3721 F"; - QTest::newRow("Identiv-uTrust-3721-F-macosx-11-13") << UsbId(0x04E6, 0x5613) << "Identiv uTrust 3721 Contactless Reader(1)" << "Identiv 3721 F"; + QTest::newRow("Identiv-uTrust-3721-F-macosx-12-14") << UsbId(0x04E6, 0x5613) << "Identiv uTrust 3721 Contactless Reader(1)" << "Identiv 3721 F"; QTest::newRow("Identiv-3721-F-generic-1") << UsbId(0x04E6, 0x5613) << "Identiv cloud 3721 Contactless Reader 0" << "Identiv 3721 F"; QTest::newRow("Identiv-3721-F-generic-2") << UsbId(0x04E6, 0x5613) << "Identiv cloud 3721 Contactless Reader(1)" << "Identiv 3721 F"; QTest::newRow("Identiv-3721-F-generic-3") << UsbId(0x04E6, 0x5613) << "Identiv cloud 3721 CL Reader 0" << "Identiv 3721 F"; @@ -308,8 +338,8 @@ class test_ReaderConfiguration QTest::newRow("Identiv-Cloud-4700-F-windows-10-11-1") << UsbId(0x04E6, 0x5720) << "Identive CLOUD 4700 F Contact Reader 0" << "Identive CLOUD 4700 F Contact Reader 0"; QTest::newRow("Identiv-Cloud-4700-F-windows-10-11-2") << UsbId(0x04E6, 0x5720) << "Identive CLOUD 4700 F Contactless Reader 0" << "Identiv Cloud 4700 F"; QTest::newRow("Identiv-Cloud-4700-F-windows-10-11-3") << UsbId(0x04E6, 0x5720) << "Identive CLOUD 4700 F Contactless Reader 1" << "Identiv Cloud 4700 F"; - QTest::newRow("Identiv-Cloud-4700-F-macosx-11-13-1") << UsbId(0x04E6, 0x5720) << "Identiv uTrust 4700 F Dual Interface Reader(2)" << "Identiv Cloud 4700 F"; - QTest::newRow("Identiv-Cloud-4700-F-macosx-11-13-2") << UsbId(0x04E6, 0x5720) << "Identiv uTrust 4700 F Dual Interface Reader(1)" << "Identiv uTrust 4700 F Dual Interface Reader(1)"; + QTest::newRow("Identiv-Cloud-4700-F-macosx-12-14-1") << UsbId(0x04E6, 0x5720) << "Identiv uTrust 4700 F Dual Interface Reader(2)" << "Identiv Cloud 4700 F"; + QTest::newRow("Identiv-Cloud-4700-F-macosx-12-14-2") << UsbId(0x04E6, 0x5720) << "Identiv uTrust 4700 F Dual Interface Reader(1)" << "Identiv uTrust 4700 F Dual Interface Reader(1)"; QTest::newRow("Identiv-4701-F-windows-10-11-1") << UsbId(0x04E6, 0x5724) << "Identiv CLOUD 4701 F Contact Reader 0" << "Identiv CLOUD 4701 F Contact Reader 0"; QTest::newRow("Identiv-4701-F-windows-10-11-2") << UsbId(0x04E6, 0x5724) << "Identiv CLOUD 4701 F Contactless Reader 1" << "Identiv 4701 F"; @@ -317,23 +347,26 @@ class test_ReaderConfiguration QTest::newRow("Identiv-4701-F-windows-10-11-4") << UsbId(0x04E6, 0x5724) << "Identiv cloud 4701 F Contactless Reader 1" << "Identiv 4701 F"; QTest::newRow("Identiv-4701-F-windows-10-11-5") << UsbId(0x04E6, 0x5724) << "Identiv cloud 4701 F Contactless Reader 0" << "Identiv 4701 F"; QTest::newRow("Identiv-4701-F-windows-10-11-6") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F CL Reader 0" << "Identiv 4701 F"; - QTest::newRow("Identiv-4701-F-macosx-11-13-1") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader(1)" << "Identiv 4701 F"; - QTest::newRow("Identiv-4701-F-macosx-11-13-2") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader(2)" << "Identiv 4701 F"; - QTest::newRow("Identiv-4701-F-macosx-11-13-3") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader" << "Identiv 4701 F"; + QTest::newRow("Identiv-4701-F-macosx-12-14-1") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader(1)" << "Identiv 4701 F"; + QTest::newRow("Identiv-4701-F-macosx-12-14-2") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader(2)" << "Identiv 4701 F"; + QTest::newRow("Identiv-4701-F-macosx-12-14-3") << UsbId(0x04E6, 0x5724) << "Identiv uTrust 4701 F Dual Interface Reader" << "Identiv 4701 F"; - QTest::newRow("Cherry-TC-1200-windows-7-10-1") << UsbId(0x046A, 0x0091) << "Cherry Smartcard Terminal TC 12xx-CL 0" << "Cherry TC-1200"; - QTest::newRow("Cherry-TC-1200-windows-10") << UsbId(0x046A, 0x0091) << "Cherry Smartcard Terminal TC 12xx 0" << "Cherry Smartcard Terminal TC 12xx 0"; - QTest::newRow("Cherry-TC-1200-macosx-10.13-11.0") << UsbId(0x046A, 0x0091) << "Cherry SC Reader (046A:0091)" << "Cherry TC-1200"; + QTest::newRow("Cherry-TC-1200-windows-10-11-1") << UsbId(0x046A, 0x0091) << "Cherry Smartcard Terminal TC 12xx-CL 0" << "Cherry TC-1200"; + QTest::newRow("Cherry-TC-1200-windows-10-11-2") << UsbId(0x046A, 0x0091) << "Cherry Smartcard Terminal TC 12xx 0" << "Cherry Smartcard Terminal TC 12xx 0"; + QTest::newRow("Cherry-TC-1200-macosx-12-14") << UsbId(0x046A, 0x0091) << "Cherry SC Reader (046A:0091)" << "Cherry TC-1200"; QTest::newRow("Cherry-TC-1200-linux") << UsbId(0x046A, 0x0091) << "Cherry TC 1200" << "Cherry TC-1200"; - QTest::newRow("Cherry-TC-1300-windows-7-10-1") << UsbId(0x046A, 0x0092) << "Cherry Smartcard Terminal TC 13xx-CL 0" << "Cherry TC-1300"; - QTest::newRow("Cherry-TC-1300-windows-7-10-2") << UsbId(0x046A, 0x0092) << "Cherry Smartcard Terminal TC 13xx 0" << "Cherry Smartcard Terminal TC 13xx 0"; - QTest::newRow("Cherry-TC-1300-macosx-10.13-11.0-1") << UsbId(0x046A, 0x0092) << "Cherry SC Reader (046A:0092)(1)" << "Cherry TC-1300"; - QTest::newRow("Cherry-TC-1300-macosx-10.13-11.0-2") << UsbId(0x046A, 0x0092) << "Cherry SC Reader (046A:0092)(2)" << "Cherry TC-1300"; - QTest::newRow("Cherry-TC-1300-linux") << UsbId(0x046A, 0x0092) << "Cherry TC 1300" << "Cherry TC-1300"; + QTest::newRow("Cherry-TC-1300-windows-10-11-1") << UsbId(0x046A, 0x0092) << "Cherry Smartcard Terminal TC 13xx-CL 0" << "Cherry TC-1300"; + QTest::newRow("Cherry-TC-1300-windows-10-11-2") << UsbId(0x046A, 0x0092) << "Cherry Smartcard Terminal TC 13xx 0" << "Cherry Smartcard Terminal TC 13xx 0"; + QTest::newRow("Cherry-TC-1300-windows-10") << UsbId(0x046A, 0x0092) << "Cherry Smart Card Reader USB 0" << "Cherry Smart Card Reader USB 0"; + QTest::newRow("Cherry-TC-1300-macosx-12-14-1") << UsbId(0x046A, 0x0092) << "Cherry SC Reader (046A:0092)(1)" << "Cherry TC-1300"; + QTest::newRow("Cherry-TC-1300-macosx-12-14-2") << UsbId(0x046A, 0x0092) << "Cherry SC Reader (046A:0092)(2)" << "Cherry TC-1300"; + QTest::newRow("Cherry-TC-1300-macosx-14") << UsbId(0x046A, 0x0092) << "Cherry Smart Card Reader USB" << "Cherry Smart Card Reader USB"; - QTest::newRow("Cherry-ST-1275-windows-7-10-1") << UsbId(0x046A, 0x0072) << "Cherry SmartTerminal XX7X 0" << "Cherry SmartTerminal XX7X 0"; - QTest::newRow("Cherry-ST-1275-windows-7-10-2") << UsbId(0x046A, 0x0072) << "Cherry SmartTerminal XX7X-RF 0" << "Cherry ST-1275"; + QTest::newRow("Cherry-TC-1300-linux-macosx-12-13") << UsbId(0x046A, 0x0092) << "Cherry TC 1300" << "Cherry TC 1300"; + + QTest::newRow("Cherry-ST-1275-windows-10-11-1") << UsbId(0x046A, 0x0072) << "Cherry SmartTerminal XX7X 0" << "Cherry SmartTerminal XX7X 0"; + QTest::newRow("Cherry-ST-1275-windows-10-11-2") << UsbId(0x046A, 0x0072) << "Cherry SmartTerminal XX7X-RF 0" << "Cherry ST-1275"; QTest::newRow("Cherry-sercure Board-windows-7-10-1") << UsbId(0x046A, 0x01A2) << "Cherry GmbH CHERRY SECURE BOARD 1.0 0" << "Cherry Secure Board 1.0"; QTest::newRow("Cherry-sercure Board-macosx-10.13-11.0-1") << UsbId(0x046A, 0x01A2) << "Cherry GmbH CHERRY SECURE BOARD 1.0" << "Cherry Secure Board 1.0"; @@ -351,7 +384,7 @@ class test_ReaderConfiguration mUsbIds += usbId; #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"); + const ReaderConfigurationInfo readerSettingsInfo = ReaderConfigurationInfo("crap"_L1); #else const ReaderConfigurationInfo readerSettingsInfo = Env::getSingleton()->getReaderConfigurationInfo(readerName); #endif @@ -370,19 +403,6 @@ class test_ReaderConfiguration } - void checkIconNames() - { - for (const auto& readerSettingsInfo : std::as_const(Env::getSingleton()->getReaderConfigurationInfos())) - { - const auto& iconName = readerSettingsInfo.getIcon()->getName(); - const auto& iconNameWithNPA = readerSettingsInfo.getIconWithNPA()->getName(); - QString iconNameWithoutPng = iconName.mid(0, iconName.size() - 4); - QVERIFY2(iconNameWithNPA.startsWith(iconNameWithoutPng), - qPrintable(QString("%1 does not starts with: %2").arg(iconNameWithNPA, iconNameWithoutPng))); - } - } - - void checkOsVersion() { ResourceLoader::getInstance().init(); @@ -391,14 +411,14 @@ class test_ReaderConfiguration const QJsonDocument& json = QJsonDocument::fromJson(data, &jsonError); QVERIFY(jsonError.error == QJsonParseError::NoError); QJsonObject doc = json.object(); - const QJsonArray& array = doc[QLatin1String("SupportedDevices")].toArray(); + const QJsonArray& array = doc["SupportedDevices"_L1].toArray(); for (const QJsonValueConstRef entry : array) { QVERIFY(entry.isObject()); auto object = entry.toObject(); - checkPlatformsMinMax(object, QLatin1String("Drivers")); - checkPlatformsMinMax(object, QLatin1String("Information")); + checkPlatformsMinMax(object, "Drivers"_L1); + checkPlatformsMinMax(object, "Information"_L1); } } @@ -406,7 +426,7 @@ class test_ReaderConfiguration }; -const int test_ReaderConfiguration::cCardReadersInConfigurationFile = 31; +const int test_ReaderConfiguration::cCardReadersInConfigurationFile = 33; QTEST_GUILESS_MAIN(test_ReaderConfiguration) #include "test_ReaderConfiguration.moc" diff --git a/test/qt/configuration/test_ReaderConfigurationEntryParser.cpp b/test/qt/configuration/test_ReaderConfigurationEntryParser.cpp index 5ea70600a..b9fecc96b 100644 --- a/test/qt/configuration/test_ReaderConfigurationEntryParser.cpp +++ b/test/qt/configuration/test_ReaderConfigurationEntryParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/configuration/test_ReaderConfigurationParser.cpp b/test/qt/configuration/test_ReaderConfigurationParser.cpp index f2c49ed9a..252ade71a 100644 --- a/test/qt/configuration/test_ReaderConfigurationParser.cpp +++ b/test/qt/configuration/test_ReaderConfigurationParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -44,29 +45,31 @@ class test_ReaderConfigurationParser QStringList incompleteKeyValuePairs(int skipIndex, bool skipOnlyValue) { const QStringList keys = { - "VendorId", "ProductIds", "Name", "Drivers" + "VendorId"_L1, "ProductIds"_L1, "Name"_L1, "Drivers"_L1 }; const QStringList vals = { - "\"0x0C4B\"", "[\"0x0501\"]", - "\"REINER SCT cyberJack RFID komfort\"", - " [\n" - " {\n" - " \"Platforms\": [{\"os\": \"win\"}],\n" - " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=Windows&productGroup=77304735&product=77304822&q=driver#choice5\"\n" - " },\n" - " {\n" - " \"Platforms\": [{\"os\": \"mac\", \"max\": \"10.10\"}],\n" - " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304822&q=driver#choice5\"\n" - " },\n" - " {\n" - " \"Platforms\": [{\"os\": \"mac\", \"min\": \"10.11\"}],\n" - " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304822&q=driver#choice5\"\n" - " },\n" - " {\n" - " \"Platforms\": [{\"os\": \"unknown\"}],\n" - " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=Linux&productGroup=77304735&product=77304822&q=driver#choice5\"\n" - " }\n" - " ]\n" + "\"0x0C4B\""_L1, "[\"0x0501\"]"_L1, + "\"REINER SCT cyberJack RFID komfort\""_L1, + QLatin1StringView( + " [\n" + " {\n" + " \"Platforms\": [{\"os\": \"win\"}],\n" + " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=Windows&productGroup=77304735&product=77304822&q=driver#choice5\"\n" + " },\n" + " {\n" + " \"Platforms\": [{\"os\": \"mac\", \"max\": \"10.10\"}],\n" + " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304822&q=driver#choice5\"\n" + " },\n" + " {\n" + " \"Platforms\": [{\"os\": \"mac\", \"min\": \"10.11\"}],\n" + " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=MacOS&productGroup=77304735&product=77304822&q=driver#choice5\"\n" + " },\n" + " {\n" + " \"Platforms\": [{\"os\": \"unknown\"}],\n" + " \"URL\": \"https://www.reiner-sct.com/support/support-anfrage/?os=Linux&productGroup=77304735&product=77304822&q=driver#choice5\"\n" + " }\n" + " ]\n" + ) }; QStringList result; for (int index = 0; index < keys.size(); index++) @@ -75,7 +78,7 @@ class test_ReaderConfigurationParser { const QString key = keys.at(index); const QString val = index != skipIndex ? vals.at(index) : QStringLiteral("\"\""); - result += QString("\"%1\": %2\n").arg(key, val); + result += "\"%1\": %2\n"_L1.arg(key, val); } } @@ -379,7 +382,7 @@ class test_ReaderConfigurationParser " }\n" " ]\n" "}"); - const QVector infos = ReaderConfigurationParser::parse(data); + const QList infos = ReaderConfigurationParser::parse(data); QCOMPARE(infos.at(0).getProductIds(), QSet({static_cast(0x0501)})); @@ -407,7 +410,7 @@ class test_ReaderConfigurationParser " ]\n" "}"); - const QVector infos = ReaderConfigurationParser::parse(data); + const QList infos = ReaderConfigurationParser::parse(data); const QSet ids = {static_cast(0x0502), static_cast(0x0503)}; QCOMPARE(infos.at(0).getProductIds(), ids); @@ -445,7 +448,7 @@ class test_ReaderConfigurationParser " }\n" " ]\n" "}"); - const QVector infos = ReaderConfigurationParser::parse(data); + const QList infos = ReaderConfigurationParser::parse(data); QCOMPARE(infos.size(), 0); } diff --git a/test/qt/configuration/test_ReleaseInformation.cpp b/test/qt/configuration/test_ReleaseInformation.cpp index 9c990e6fe..e2321aeea 100644 --- a/test/qt/configuration/test_ReleaseInformation.cpp +++ b/test/qt/configuration/test_ReleaseInformation.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_ReleaseInformation @@ -20,7 +21,7 @@ class test_ReleaseInformation private Q_SLOTS: void init() { - QCoreApplication::setApplicationVersion("1.2.3"); + QCoreApplication::setApplicationVersion("1.2.3"_L1); } @@ -40,8 +41,8 @@ class test_ReleaseInformation void test_explicitVersionNumber() { - ReleaseInformation information(VersionNumber("1.2.4")); - QCOMPARE(information.versionNumber(), VersionNumber("1.2.4")); + ReleaseInformation information(VersionNumber("1.2.4"_L1)); + QCOMPARE(information.versionNumber(), VersionNumber("1.2.4"_L1)); } @@ -54,14 +55,14 @@ class test_ReleaseInformation void test_pathReleaseNotesForExplicitVersion() { - ReleaseInformation information(VersionNumber("1.2.4")); + ReleaseInformation information(VersionNumber("1.2.4"_L1)); QCOMPARE(information.pathReleaseNotes().size(), 5); } void test_pathReleaseNotesForExplicitVersionOnly() { - ReleaseInformation information(VersionNumber("1.2.4"), true); + ReleaseInformation information(VersionNumber("1.2.4"_L1), true); QCOMPARE(information.pathReleaseNotes().size(), 1); } diff --git a/test/qt/configuration/test_ReleaseInformationConfiguration.cpp b/test/qt/configuration/test_ReleaseInformationConfiguration.cpp index 9c67bfd4d..ef2d41996 100644 --- a/test/qt/configuration/test_ReleaseInformationConfiguration.cpp +++ b/test/qt/configuration/test_ReleaseInformationConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_ReleaseInformationConfiguration @@ -39,7 +40,7 @@ class test_ReleaseInformationConfiguration void init() { Env::setCreator(std::function([] { - auto* mock = new MockReleaseInformation(VersionNumber("1.2.3"), false); + auto* mock = new MockReleaseInformation(VersionNumber("1.2.3"_L1), false); return mock; })); Env::setCreator(std::function([](const VersionNumber& pVersion, bool pConsiderOnlyThisVersion){ @@ -61,7 +62,7 @@ class test_ReleaseInformationConfiguration QCOMPARE(spyCurrentInformationChanged.count(), 1); QCOMPARE(spyUpdateInformationChanged.count(), 0); - mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4")); + mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4"_L1)); QCOMPARE(getUpdateInfoUpdateCallcount(), 1); QCOMPARE(spyCurrentInformationChanged.count(), 1); @@ -87,7 +88,7 @@ class test_ReleaseInformationConfiguration QCOMPARE(spyCurrentInformationChanged.count(), 1); QCOMPARE(spyUpdateInformationChanged.count(), 0); - mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4")); + mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4"_L1)); QCOMPARE(getUpdateInfoUpdateCallcount(), 1); QCOMPARE(spyUpdateInformationChanged.count(), 1); @@ -110,7 +111,7 @@ class test_ReleaseInformationConfiguration QCOMPARE(spyCurrentInformationChanged.count(), 1); QCOMPARE(spyUpdateInformationChanged.count(), 0); - mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.4.2")); + mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.4.2"_L1)); QCOMPARE(spyCurrentInformationChanged.count(), 1); QCOMPARE(spyUpdateInformationChanged.count(), 1); diff --git a/test/qt/core/test_AppController.cpp b/test/qt/core/test_AppController.cpp index eabc32dea..ac4724b28 100644 --- a/test/qt/core/test_AppController.cpp +++ b/test/qt/core/test_AppController.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/AppController.h" @@ -32,7 +32,7 @@ class test_AppController { qRegisterMetaType>("QSharedPointer"); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/diagnosis/test_DiagnosisAntivirusDetection.cpp b/test/qt/diagnosis/test_DiagnosisAntivirusDetection.cpp index ee8bd3355..e3fe5a658 100644 --- a/test/qt/diagnosis/test_DiagnosisAntivirusDetection.cpp +++ b/test/qt/diagnosis/test_DiagnosisAntivirusDetection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DiagnosisAntivirusDetection @@ -28,10 +29,10 @@ class test_DiagnosisAntivirusDetection const QByteArray rawData = TestFileHelper::readFile(filePath); QString stringData = QString::fromUtf8(rawData); - Q_ASSERT(stringData.count("\r\n") == 0); - const qsizetype linebreaks = stringData.count('\n'); - stringData.replace('\n', "\r\n"); - Q_ASSERT(stringData.count("\r\n") == linebreaks); + Q_ASSERT(stringData.count("\r\n"_L1) == 0); + const qsizetype linebreaks = stringData.count('\n'_L1); + stringData.replace('\n'_L1, "\r\n"_L1); + Q_ASSERT(stringData.count("\r\n"_L1) == linebreaks); return stringData; } @@ -54,7 +55,7 @@ class test_DiagnosisAntivirusDetection QSignalSpy spy(mAntivirusDetection.data(), &DiagnosisAntivirusDetection::fireAntivirusInformationChanged); QVERIFY(mAntivirusDetection->getAntivirusInformations().empty()); QCOMPARE(spy.count(), 0); - mAntivirusDetection->parseAntivirInfos(""); + mAntivirusDetection->parseAntivirInfos(QString()); QVERIFY(mAntivirusDetection->getAntivirusInformations().empty()); QCOMPARE(spy.count(), 1); } @@ -70,9 +71,9 @@ class test_DiagnosisAntivirusDetection mAntivirusDetection->parseAntivirInfos(fileContent); auto antivirusInfos = mAntivirusDetection->getAntivirusInformations(); QVERIFY(!antivirusInfos.empty()); - QCOMPARE(antivirusInfos[0]->getDisplayName(), QString("Windows Defender")); - QCOMPARE(antivirusInfos[0]->getLastUpdate(), QString("Mon, 26 Nov 2018 10:34:23 GMT")); - QCOMPARE(antivirusInfos[0]->getExePath(), QString("windowsdefender://")); + QCOMPARE(antivirusInfos[0]->getDisplayName(), "Windows Defender"_L1); + QCOMPARE(antivirusInfos[0]->getLastUpdate(), "Mon, 26 Nov 2018 10:34:23 GMT"_L1); + QCOMPARE(antivirusInfos[0]->getExePath(), "windowsdefender://"_L1); QCOMPARE(spy.count(), 1); } @@ -87,9 +88,9 @@ class test_DiagnosisAntivirusDetection mAntivirusDetection->parseAntivirInfos(fileContent); auto antivirusInfos = mAntivirusDetection->getAntivirusInformations(); QVERIFY(!antivirusInfos.empty()); - QCOMPARE(antivirusInfos[0]->getDisplayName(), QString("Windows Defender")); - QCOMPARE(antivirusInfos[0]->getLastUpdate(), QString("")); - QCOMPARE(antivirusInfos[0]->getExePath(), QString("windowsdefender://")); + QCOMPARE(antivirusInfos[0]->getDisplayName(), "Windows Defender"_L1); + QCOMPARE(antivirusInfos[0]->getLastUpdate(), QString()); + QCOMPARE(antivirusInfos[0]->getExePath(), "windowsdefender://"_L1); QCOMPARE(spy.count(), 1); } @@ -104,12 +105,12 @@ class test_DiagnosisAntivirusDetection mAntivirusDetection->parseAntivirInfos(fileContent); auto antivirusInfos = mAntivirusDetection->getAntivirusInformations(); QVERIFY(!antivirusInfos.empty()); - QCOMPARE(antivirusInfos[0]->getDisplayName(), QString("BullGuard Antivirus")); - QCOMPARE(antivirusInfos[0]->getLastUpdate(), QString("Fri, 30 Nov 2018 15:04:13 GMT")); - QCOMPARE(antivirusInfos[0]->getExePath(), QString("C:\\Program Files\\BullGuard Ltd\\BullGuard\\BullGuard.exe")); - QCOMPARE(antivirusInfos[1]->getDisplayName(), QString("Windows Defender")); - QCOMPARE(antivirusInfos[1]->getLastUpdate(), QString("Mon, 26 Nov 2018 10:34:23 GMT")); - QCOMPARE(antivirusInfos[1]->getExePath(), QString("windowsdefender://")); + QCOMPARE(antivirusInfos[0]->getDisplayName(), "BullGuard Antivirus"_L1); + QCOMPARE(antivirusInfos[0]->getLastUpdate(), "Fri, 30 Nov 2018 15:04:13 GMT"_L1); + QCOMPARE(antivirusInfos[0]->getExePath(), "C:\\Program Files\\BullGuard Ltd\\BullGuard\\BullGuard.exe"_L1); + QCOMPARE(antivirusInfos[1]->getDisplayName(), "Windows Defender"_L1); + QCOMPARE(antivirusInfos[1]->getLastUpdate(), "Mon, 26 Nov 2018 10:34:23 GMT"_L1); + QCOMPARE(antivirusInfos[1]->getExePath(), "windowsdefender://"_L1); QCOMPARE(spy.count(), 1); } diff --git a/test/qt/diagnosis/test_DiagnosisConnectionTest.cpp b/test/qt/diagnosis/test_DiagnosisConnectionTest.cpp index 7cb3b5523..ab2bbfe54 100644 --- a/test/qt/diagnosis/test_DiagnosisConnectionTest.cpp +++ b/test/qt/diagnosis/test_DiagnosisConnectionTest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DiagnosisConnectionTest @@ -53,18 +54,9 @@ class test_DiagnosisConnectionTest void test_OnSocketConnectionTestWithProxyDone() { mTest->onSocketConnectionTestWithProxyDone(); - QVERIFY(mTest->mConnectionTestWithProxySuccessful); - QVERIFY(mTest->mConnectionTestWithProxyDone); - QCOMPARE(mTest->mTcpSocketWithProxy.state(), QAbstractSocket::UnconnectedState); - } - - - void test_OnSocketConnectionTestWithProxyError() - { - QTest::ignoreMessage(QtDebugMsg, "Could not connect to test server with proxy: QAbstractSocket::NetworkError"); - mTest->onSocketConnectionTestWithProxyError(QAbstractSocket::NetworkError); QVERIFY(!mTest->mConnectionTestWithProxySuccessful); QVERIFY(mTest->mConnectionTestWithProxyDone); + QVERIFY(mTest->mReplyWithProxy.isNull()); } @@ -73,7 +65,7 @@ class test_DiagnosisConnectionTest mTest->onSocketConnectionTestWithoutProxyDone(); QVERIFY(mTest->mConnectionTestWithoutProxySuccessful); QVERIFY(mTest->mConnectionTestWithoutProxyDone); - QCOMPARE(mTest->mTcpSocketWithProxy.state(), QAbstractSocket::UnconnectedState); + QVERIFY(mTest->mReplyWithProxy.isNull()); } @@ -116,7 +108,7 @@ class test_DiagnosisConnectionTest QNetworkProxy::Capabilities caps = {QNetworkProxy::TunnelingCapability, QNetworkProxy::ListeningCapability, QNetworkProxy::UdpTunnelingCapability, QNetworkProxy::CachingCapability, QNetworkProxy::HostNameLookupCapability, QNetworkProxy::SctpTunnelingCapability, QNetworkProxy::SctpListeningCapability}; - QCOMPARE(mTest->getProxyCapabilitiesAsQString(caps), QString("Tunnel, Listen, UDP, Caching, NameLookup, SctpTunnel, SctpListen")); + QCOMPARE(mTest->getProxyCapabilitiesAsQString(caps), "Tunnel, Listen, UDP, Caching, NameLookup, SctpTunnel, SctpListen"_L1); } @@ -149,18 +141,18 @@ class test_DiagnosisConnectionTest mTest->startConnectionTest(); QVERIFY(mTest->mIsProxySet); QCOMPARE(mTest->mProxyHostName, QString()); - QCOMPARE(mTest->mProxyPort, QString("0")); - QCOMPARE(mTest->mProxyType, QString("HttpProxy")); - QCOMPARE(mTest->mProxyType, QString("HttpProxy")); + QCOMPARE(mTest->mProxyPort, "0"_L1); + QCOMPARE(mTest->mProxyType, "HttpProxy"_L1); + QCOMPARE(mTest->mProxyType, "HttpProxy"_L1); QCOMPARE(mTest->mPingSocketToProxy.proxy(), QNetworkProxy::NoProxy); QCOMPARE(mTest->mPingSocketToProxy.state(), QAbstractSocket::SocketState::HostLookupState); - QCOMPARE(mTest->mTcpSocketWithProxy.proxy(), testProxy); - QCOMPARE(mTest->mTcpSocketWithProxy.state(), QAbstractSocket::SocketState::ConnectingState); + QVERIFY(!mTest->mReplyWithProxy.isNull()); + QVERIFY(mTest->mReplyWithProxy->isRunning()); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations QVERIFY(mTest->mProxyPingDone); QVERIFY(mTest->mConnectionTestWithProxyDone); - QCOMPARE(mTest->mTcpSocketWithProxy.state(), QAbstractSocket::SocketState::UnconnectedState); + QVERIFY(mTest->mReplyWithProxy.isNull()); } diff --git a/test/qt/diagnosis/test_DiagnosisContext.cpp b/test/qt/diagnosis/test_DiagnosisContext.cpp index 5e6ffb50e..c3718627a 100644 --- a/test/qt/diagnosis/test_DiagnosisContext.cpp +++ b/test/qt/diagnosis/test_DiagnosisContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "context/DiagnosisContext.h" @@ -40,7 +40,7 @@ class test_DiagnosisContext const QString name2 = QStringLiteral("name2"); ReaderInfo info1(name1); ReaderInfo info2(name2); - QVector infoVector({info1, info2}); + QList infoVector({info1, info2}); QSignalSpy spy(&context, &DiagnosisContext::readerInfosChanged); context.setReaderInfos(infoVector); @@ -57,8 +57,8 @@ class test_DiagnosisContext { DiagnosisContext context; const QString version = QStringLiteral("version"); - QVector components({DiagnosisContext::ComponentInfo()}); - QVector drivers({DiagnosisContext::ComponentInfo()}); + QList components({DiagnosisContext::ComponentInfo()}); + QList drivers({DiagnosisContext::ComponentInfo()}); QSignalSpy spy(&context, &DiagnosisContext::pcscInfoChanged); context.setPcscInfo(version, components, drivers); diff --git a/test/qt/diagnosis/test_DiagnosisController.cpp b/test/qt/diagnosis/test_DiagnosisController.cpp new file mode 100644 index 000000000..42125573a --- /dev/null +++ b/test/qt/diagnosis/test_DiagnosisController.cpp @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "controller/DiagnosisController.h" + +#include "ReaderManager.h" +#include "ResourceLoader.h" +#include "context/DiagnosisContext.h" + +#include "MockReaderDetector.h" +#include "MockReaderManagerPlugin.h" + +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) + +class test_DiagnosisController + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + ResourceLoader::getInstance().init(); + auto* readerManager = Env::getSingleton(); + QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); + readerManager->init(); + QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations + } + + + void cleanupTestCase() + { + Env::getSingleton()->shutdown(); + } + + + void cleanup() + { + MockReaderManagerPlugin::getInstance().removeAllReader(); + } + + + void testOnReaderEvent() + { + const QList devIds({UsbId(0x0C4B, 0x9102), UsbId(0x076B, 0x5022)}); // cyberJack and OMNIKEY 5022 + MockReaderDetector readerDetector(devIds); + Env::set(ReaderDetector::staticMetaObject, &readerDetector); + + auto context = QSharedPointer::create(); + DiagnosisController controller(context); + + MockReaderManagerPlugin::getInstance().addReader(u"REINER SCT cyberJack RFID basis"_s); + QCOMPARE(context->getReaderInfos().size(), 1); // cyberJack detected + QCOMPARE(context->getReaderInfosNoDriver().size(), 1); // OMNIKEY 5022 not detected + + MockReaderManagerPlugin::getInstance().addReader(u"Simulator"_s); + QCOMPARE(context->getReaderInfos().size(), 2); + QCOMPARE(context->getReaderInfosNoDriver().size(), 1); // OMNIKEY 5022 not detected + + MockReaderManagerPlugin::getInstance().addReader(u"HID Global OMNIKEY 5022 Smart Card Reader"_s); + QCOMPARE(context->getReaderInfos().size(), 3); + QCOMPARE(context->getReaderInfosNoDriver().size(), 0); + } + + +}; + +QTEST_GUILESS_MAIN(test_DiagnosisController) +#include "test_DiagnosisController.moc" diff --git a/test/qt/diagnosis/test_DiagnosisFirewallDetection.cpp b/test/qt/diagnosis/test_DiagnosisFirewallDetection.cpp index 9df856a33..c60c90211 100644 --- a/test/qt/diagnosis/test_DiagnosisFirewallDetection.cpp +++ b/test/qt/diagnosis/test_DiagnosisFirewallDetection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DiagnosisFirewallDetection @@ -28,10 +29,10 @@ class test_DiagnosisFirewallDetection const QByteArray rawData = TestFileHelper::readFile(filePath); QString stringData = QString::fromUtf8(rawData); - Q_ASSERT(stringData.count("\r\n") == 0); - const qsizetype linebreaks = stringData.count('\n'); - stringData.replace('\n', "\r\n"); - Q_ASSERT(stringData.count("\r\n") == linebreaks); + Q_ASSERT(stringData.count("\r\n"_L1) == 0); + const qsizetype linebreaks = stringData.count('\n'_L1); + stringData.replace('\n'_L1, "\r\n"_L1); + Q_ASSERT(stringData.count("\r\n"_L1) == linebreaks); return stringData; } @@ -166,11 +167,11 @@ class test_DiagnosisFirewallDetection QCOMPARE(firewallProfileInfos.size(), size); if (size > 0) { - QCOMPARE(firewallProfileInfos[0]->getName(), "Domain"); + QCOMPARE(firewallProfileInfos[0]->getName(), "Domain"_L1); QCOMPARE(firewallProfileInfos[0]->getEnabled(), enabledDomain); - QCOMPARE(firewallProfileInfos[1]->getName(), "Private"); + QCOMPARE(firewallProfileInfos[1]->getName(), "Private"_L1); QCOMPARE(firewallProfileInfos[1]->getEnabled(), enabledPrivate); - QCOMPARE(firewallProfileInfos[2]->getName(), "Public"); + QCOMPARE(firewallProfileInfos[2]->getName(), "Public"_L1); QCOMPARE(firewallProfileInfos[2]->getEnabled(), enabledPublic); } @@ -181,18 +182,18 @@ class test_DiagnosisFirewallDetection void test_parsingFirewallSoftwareParameter_data() { QTest::addColumn("filename"); - QTest::addColumn("name"); + QTest::addColumn("name"); - QTest::newRow("kaspersky") << QStringLiteral("firewallSoftwareParametersKaspersky.txt") << QString("Kaspersky Internet Security"); - QTest::newRow("bullguard") << QStringLiteral("firewallSoftwareParametersBullguard.txt") << QString("BullGuard Firewall"); - QTest::newRow("missing") << QStringLiteral("emptyResponse.txt") << QString(""); + QTest::newRow("kaspersky") << QStringLiteral("firewallSoftwareParametersKaspersky.txt") << "Kaspersky Internet Security"_L1; + QTest::newRow("bullguard") << QStringLiteral("firewallSoftwareParametersBullguard.txt") << "BullGuard Firewall"_L1; + QTest::newRow("missing") << QStringLiteral("emptyResponse.txt") << ""_L1; } void test_parsingFirewallSoftwareParameter() { QFETCH(QString, filename); - QFETCH(QString, name); + QFETCH(QLatin1String, name); QSignalSpy spy(mFirewallDetection.data(), &DiagnosisFirewallDetection::fireFirewallInformationReady); QVERIFY(mFirewallDetection->getDetectedFirewalls().empty()); diff --git a/test/qt/diagnosis/test_DiagnosisModel.cpp b/test/qt/diagnosis/test_DiagnosisModel.cpp index 525746c52..d4906fe06 100644 --- a/test/qt/diagnosis/test_DiagnosisModel.cpp +++ b/test/qt/diagnosis/test_DiagnosisModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DiagnosisModel @@ -27,17 +28,17 @@ class test_DiagnosisModel const QByteArray rawData = TestFileHelper::readFile(filePath); QString stringData = QString::fromUtf8(rawData); - Q_ASSERT(stringData.count("\r\n") == 0); - const qsizetype linebreaks = stringData.count('\n'); - stringData.replace('\n', "\r\n"); - Q_ASSERT(stringData.count("\r\n") == linebreaks); + Q_ASSERT(stringData.count("\r\n"_L1) == 0); + const qsizetype linebreaks = stringData.count('\n'_L1); + stringData.replace('\n'_L1, "\r\n"_L1); + Q_ASSERT(stringData.count("\r\n"_L1) == linebreaks); return stringData; } bool verifyOrder(const QSharedPointer& pSection, - const QVector>& pOrder) + const QList>& pOrder) { const auto& content = pSection->mContentItems; qsizetype offset = 0; @@ -72,18 +73,18 @@ class test_DiagnosisModel QCOMPARE(mModel->rowCount(), mModel->mSections.size()); QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::GENERAL), QCoreApplication::applicationName()); - QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::READER), QString("Card reader")); - QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::NETWORK), QString("Network")); - QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::SECURITY), QString("Antivirus and firewall")); + QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::READER), "Card reader"_L1); + QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::NETWORK), "Network"_L1); + QCOMPARE(mModel->getSectionName(DiagnosisModel::Section::SECURITY), "Antivirus and firewall"_L1); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::GENERAL]->mContentItems.last().mTitle, QString("Time of diagnosis")); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::GENERAL]->mContentItems.last().mTitle, "Time of diagnosis"_L1); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(0).mTitle, QString("Paired smartphones")); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(1).mContent, QString("No devices paired.")); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(2).mTitle, QString("Card reader")); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(3).mContent, QString("Diagnosis is running...")); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(4).mTitle, QString("PC/SC driver information")); - QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(5).mContent, QString("Diagnosis is running...")); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(0).mTitle, "Paired smartphones"_L1); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(1).mContent, "No devices paired."_L1); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(2).mTitle, "Card reader"_L1); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(3).mContent, "Diagnosis is running..."_L1); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(4).mTitle, "PC/SC driver information"_L1); + QCOMPARE(mModel->mSections[DiagnosisModel::Section::READER]->mContentItems.at(5).mContent, "Diagnosis is running..."_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::READER], {mModel->mRemoteDeviceSection, mModel->mCardReaderSection, mModel->mPcscSection})); @@ -98,27 +99,27 @@ class test_DiagnosisModel { mModel->onReaderInfosChanged(); QCOMPARE(mModel->mCardReaderSection.size(), 2); - QCOMPARE(mModel->mCardReaderSection.at(1).mContent, QString("No supported reader found.")); + QCOMPARE(mModel->mCardReaderSection.at(1).mContent, "No supported reader found."_L1); ReaderInfo defaultInfo; - ReaderInfo infoEidCard(QString("testInfo"), ReaderManagerPlugInType::PCSC, CardInfo(CardType::EID_CARD)); - ReaderInfo comfortReaderInfo(QString("name"), ReaderManagerPlugInType::REMOTE_IFD, CardInfo(CardType::UNKNOWN)); + ReaderInfo infoEidCard("testInfo"_L1, ReaderManagerPluginType::PCSC, CardInfo(CardType::EID_CARD)); + ReaderInfo comfortReaderInfo("name"_L1, ReaderManagerPluginType::REMOTE_IFD, CardInfo(CardType::UNKNOWN)); comfortReaderInfo.setBasicReader(false); - const QVector readerInfos = {defaultInfo, infoEidCard, comfortReaderInfo}; + const QList readerInfos = {defaultInfo, infoEidCard, comfortReaderInfo}; mModel->mContext->setReaderInfos(readerInfos); mModel->onReaderInfosChanged(); QCOMPARE(mModel->mCardReaderSection.size(), 4); - QCOMPARE(mModel->mCardReaderSection.at(0).mTitle, QString("Connected Card readers")); + QCOMPARE(mModel->mCardReaderSection.at(0).mTitle, "Connected Card readers"_L1); QCOMPARE(mModel->mCardReaderSection.at(1).mTitle, QString()); - QCOMPARE(mModel->mCardReaderSection.at(2).mTitle, QString("testInfo")); - QCOMPARE(mModel->mCardReaderSection.at(3).mTitle, QString("name")); + QCOMPARE(mModel->mCardReaderSection.at(2).mTitle, "testInfo"_L1); + QCOMPARE(mModel->mCardReaderSection.at(3).mTitle, "name"_L1); QCOMPARE(mModel->mCardReaderSection.at(0).mContent, QString()); - QCOMPARE(mModel->mCardReaderSection.at(1).mContent, QString("Type: Basic card reader\nCard: not inserted")); - QCOMPARE(mModel->mCardReaderSection.at(2).mContent, QString("Type: Basic card reader\nCard: ID card (PA/eAT/eID)\nRetry counter: -1")); - QCOMPARE(mModel->mCardReaderSection.at(3).mContent, QString("Type: Standard / comfort card reader\nCard: unknown type")); + QCOMPARE(mModel->mCardReaderSection.at(1).mContent, "Type: Basic card reader\nCard: not inserted"_L1); + QCOMPARE(mModel->mCardReaderSection.at(2).mContent, "Type: Basic card reader\nCard: ID card (PA/eAT/eID)\nRetry counter: -1"_L1); + QCOMPARE(mModel->mCardReaderSection.at(3).mContent, "Type: Standard / comfort card reader\nCard: unknown type"_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::READER], { mModel->mRemoteDeviceSection, @@ -131,8 +132,8 @@ class test_DiagnosisModel { mModel->onRemoteInfosChanged(); QCOMPARE(mModel->mRemoteDeviceSection.size(), 2); - QCOMPARE(mModel->mRemoteDeviceSection.at(0).mTitle, QString("Paired smartphones")); - QCOMPARE(mModel->mRemoteDeviceSection.at(1).mContent, QString("No devices paired.")); + QCOMPARE(mModel->mRemoteDeviceSection.at(0).mTitle, "Paired smartphones"_L1); + QCOMPARE(mModel->mRemoteDeviceSection.at(1).mContent, "No devices paired."_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::READER], { mModel->mRemoteDeviceSection, mModel->mCardReaderSection, @@ -142,24 +143,24 @@ class test_DiagnosisModel void test_OnPcscInfoChanged() { - const QString version("Version"); - const DiagnosisContext::ComponentInfo component1(QString("/path/to/component1"), QString("description1"), QString("version1"), QString("vendor1")); - const DiagnosisContext::ComponentInfo component2(QString("/path/to/component2"), QString("description2"), QString("version2"), QString("vendor2")); - const DiagnosisContext::ComponentInfo driver1(QString("/path/to/driver1"), QString("description1"), QString("version1"), QString("vendor1")); - const DiagnosisContext::ComponentInfo driver2(QString("/path/to/driver2"), QString("description2"), QString("version2"), QString("vendor2")); - QVector components = {component1, component2}; - QVector drivers = {driver1, driver2}; + const QString version("Version"_L1); + const DiagnosisContext::ComponentInfo component1("/path/to/component1"_L1, "description1"_L1, "version1"_L1, "vendor1"_L1); + const DiagnosisContext::ComponentInfo component2("/path/to/component2"_L1, "description2"_L1, "version2"_L1, "vendor2"_L1); + const DiagnosisContext::ComponentInfo driver1("/path/to/driver1"_L1, "description1"_L1, "version1"_L1, "vendor1"_L1); + const DiagnosisContext::ComponentInfo driver2("/path/to/driver2"_L1, "description2"_L1, "version2"_L1, "vendor2"_L1); + QList components = {component1, component2}; + QList drivers = {driver1, driver2}; mModel->mContext->setPcscInfo(version, components, drivers); mModel->onPcscInfoChanged(); QCOMPARE(mModel->mPcscSection.size(), 4); - QCOMPARE(mModel->mPcscSection.at(0).mTitle, QString("PC/SC information")); - QCOMPARE(mModel->mPcscSection.at(1).mContent, QString("Version")); - QCOMPARE(mModel->mPcscSection.at(2).mTitle, QString("Components")); - QCOMPARE(mModel->mPcscSection.at(2).mContent, QString("description1\nVendor: vendor1\nVersion: version1\nFile path: /path/to/component1\ndescription2\nVendor: vendor2\nVersion: version2\nFile path: /path/to/component2")); - QCOMPARE(mModel->mPcscSection.at(3).mTitle, QString("Driver")); - QCOMPARE(mModel->mPcscSection.at(3).mContent, QString("description1\nVendor: vendor1\nVersion: version1\nFile path: /path/to/driver1\ndescription2\nVendor: vendor2\nVersion: version2\nFile path: /path/to/driver2")); + QCOMPARE(mModel->mPcscSection.at(0).mTitle, "PC/SC information"_L1); + QCOMPARE(mModel->mPcscSection.at(1).mContent, "Version"_L1); + QCOMPARE(mModel->mPcscSection.at(2).mTitle, "Components"_L1); + QCOMPARE(mModel->mPcscSection.at(2).mContent, "description1\nVendor: vendor1\nVersion: version1\nFile path: /path/to/component1\ndescription2\nVendor: vendor2\nVersion: version2\nFile path: /path/to/component2"_L1); + QCOMPARE(mModel->mPcscSection.at(3).mTitle, "Driver"_L1); + QCOMPARE(mModel->mPcscSection.at(3).mContent, "description1\nVendor: vendor1\nVersion: version1\nFile path: /path/to/driver1\ndescription2\nVendor: vendor2\nVersion: version2\nFile path: /path/to/driver2"_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::READER], { mModel->mRemoteDeviceSection, mModel->mCardReaderSection, @@ -176,13 +177,13 @@ class test_DiagnosisModel mModel->mContext->setTimestamp(invalid); mModel->onTimestampChanged(); - QCOMPARE(mModel->mTimestampSection.last().mTitle, QString("Time of diagnosis")); - QCOMPARE(mModel->mTimestampSection.last().mContent, QString("Failed to retrieve date & time")); + QCOMPARE(mModel->mTimestampSection.last().mTitle, "Time of diagnosis"_L1); + QCOMPARE(mModel->mTimestampSection.last().mContent, "Failed to retrieve date & time"_L1); mModel->mContext->setTimestamp(valid); mModel->onTimestampChanged(); - QCOMPARE(mModel->mTimestampSection.last().mTitle, QString("Time of diagnosis")); - QCOMPARE(mModel->mTimestampSection.last().mContent, QString("12. October 2018, 12:00:00 PM")); + QCOMPARE(mModel->mTimestampSection.last().mTitle, "Time of diagnosis"_L1); + QCOMPARE(mModel->mTimestampSection.last().mContent, "12. October 2018, 12:00:00 PM"_L1); } @@ -198,8 +199,8 @@ class test_DiagnosisModel QCOMPARE(mModel->mNetworkInterfaceSection.size(), 3); for (const auto& item : std::as_const(mModel->mNetworkInterfaceSection)) { - QCOMPARE(item.mTitle, QString("")); - QCOMPARE(item.mContent, QString("Hardware address: \nNo IP addresses assigned")); + QCOMPARE(item.mTitle, QString()); + QCOMPARE(item.mContent, "Hardware address: \nNo IP addresses assigned"_L1); } QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::NETWORK], {mModel->mNetworkConnectionSection, mModel->mNetworkInterfaceSection})); @@ -210,8 +211,8 @@ class test_DiagnosisModel { mModel->onAntivirusDetectionFailed(); QCOMPARE(mModel->mAntivirusSection.size(), 1); - QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, QString("Antivirus information")); - QCOMPARE(mModel->mAntivirusSection.at(0).mContent, QString("Antivirus detection failed.")); + QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, "Antivirus information"_L1); + QCOMPARE(mModel->mAntivirusSection.at(0).mContent, "Antivirus detection failed."_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::SECURITY], {mModel->mAntivirusSection, mModel->mFirewallSection})); } @@ -220,8 +221,8 @@ class test_DiagnosisModel { mModel->onAntivirusInformationChanged(); QCOMPARE(mModel->mAntivirusSection.size(), 1); - QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, QString("Antivirus information")); - QCOMPARE(mModel->mAntivirusSection.at(0).mContent, QString("No Antivirus software detected.")); + QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, "Antivirus information"_L1); + QCOMPARE(mModel->mAntivirusSection.at(0).mContent, "No Antivirus software detected."_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::SECURITY], {mModel->mAntivirusSection, mModel->mFirewallSection})); const QString& fileContent = getTestData(QStringLiteral("antivir_two_antivirus.txt")); @@ -229,11 +230,11 @@ class test_DiagnosisModel mModel->onAntivirusInformationChanged(); QCOMPARE(mModel->mAntivirusSection.size(), 3); - QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, QString("Antivirus information")); - QCOMPARE(mModel->mAntivirusSection.at(1).mTitle, QString("BullGuard Antivirus")); - QCOMPARE(mModel->mAntivirusSection.at(1).mContent, QString("Last updated: Fri, 30 Nov 2018 15:04:13 GMT\nExecutable path: C:\\Program Files\\BullGuard Ltd\\BullGuard\\BullGuard.exe")); - QCOMPARE(mModel->mAntivirusSection.at(2).mTitle, QString("Windows Defender")); - QCOMPARE(mModel->mAntivirusSection.at(2).mContent, QString("Last updated: Mon, 26 Nov 2018 10:34:23 GMT\nExecutable path: windowsdefender://")); + QCOMPARE(mModel->mAntivirusSection.at(0).mTitle, "Antivirus information"_L1); + QCOMPARE(mModel->mAntivirusSection.at(1).mTitle, "BullGuard Antivirus"_L1); + QCOMPARE(mModel->mAntivirusSection.at(1).mContent, "Last updated: Fri, 30 Nov 2018 15:04:13 GMT\nExecutable path: C:\\Program Files\\BullGuard Ltd\\BullGuard\\BullGuard.exe"_L1); + QCOMPARE(mModel->mAntivirusSection.at(2).mTitle, "Windows Defender"_L1); + QCOMPARE(mModel->mAntivirusSection.at(2).mContent, "Last updated: Mon, 26 Nov 2018 10:34:23 GMT\nExecutable path: windowsdefender://"_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::SECURITY], {mModel->mAntivirusSection, mModel->mFirewallSection})); } @@ -242,8 +243,8 @@ class test_DiagnosisModel { mModel->onFirewallInformationFailed(); QCOMPARE(mModel->mFirewallSection.size(), 1); - QCOMPARE(mModel->mFirewallSection.at(0).mTitle, QString("Firewall information")); - QCOMPARE(mModel->mFirewallSection.at(0).mContent, QString("An error occurred while trying to gather firewall information. Please check the log for more information.")); + QCOMPARE(mModel->mFirewallSection.at(0).mTitle, "Firewall information"_L1); + QCOMPARE(mModel->mFirewallSection.at(0).mContent, "An error occurred while trying to gather firewall information. Please check the log for more information."_L1); QVERIFY(verifyOrder(mModel->mSections[DiagnosisModel::Section::SECURITY], {mModel->mAntivirusSection, mModel->mFirewallSection})); } @@ -269,30 +270,41 @@ class test_DiagnosisModel QFETCH(bool, connectionTestOnProxy); QFETCH(bool, connectionTestWithoutProxy); + const auto errorString = "Testerror"_L1; + mModel->mConnectionTest.mIsProxySet = proxySet; mModel->mConnectionTest.mPingTestOnProxySuccessful = pingTestOnProxy; mModel->mConnectionTest.mConnectionTestWithProxySuccessful = connectionTestOnProxy; mModel->mConnectionTest.mConnectionTestWithoutProxySuccessful = connectionTestWithoutProxy; + if (proxySet && !connectionTestOnProxy) + { + mModel->mConnectionTest.mErrorOfConnectionTestWithProxy = errorString; + } mModel->onConnectionTestDone(); QCOMPARE(mModel->mNetworkConnectionSection.size(), 2); - QCOMPARE(mModel->mNetworkConnectionSection.at(0).mTitle, QString("Service addresses")); - QCOMPARE(mModel->mNetworkConnectionSection.at(1).mTitle, QString("Proxy information")); + QCOMPARE(mModel->mNetworkConnectionSection.at(0).mTitle, "Service addresses"_L1); + QCOMPARE(mModel->mNetworkConnectionSection.at(1).mTitle, "Proxy information"_L1); QString contentString; if (proxySet) { - contentString = QString("Hostname: \nPort: \nType: \nCapabilities: \nPing test to proxy: "); - contentString += pingTestOnProxy ? QString("Successful") : QString("Failed"); - contentString += QString("\nConnection test with proxy: "); - contentString += connectionTestOnProxy ? QString("Successful") : QString("Failed"); + contentString = "Hostname: \nPort: \nType: \nCapabilities: \nPing test to proxy: "_L1; + contentString += pingTestOnProxy ? "Successful"_L1 : "Failed"_L1; + contentString += "\nConnection test with proxy: "_L1; + contentString += connectionTestOnProxy ? "Successful"_L1 : "Failed"_L1; + if (!connectionTestOnProxy) + { + contentString += "\nEncountered error: "_L1; + contentString += errorString; + } } else { - contentString = QString("No proxy found"); + contentString = "No proxy found"_L1; } - contentString += QString("\nConnection test without proxy: "); - contentString += connectionTestWithoutProxy ? QString("Successful") : QString("Failed"); + contentString += "\nConnection test without proxy: "_L1; + contentString += connectionTestWithoutProxy ? "Successful"_L1 : "Failed"_L1; QCOMPARE(mModel->mNetworkConnectionSection.at(0).mContent, QStringLiteral("Not bound")); QCOMPARE(mModel->mNetworkConnectionSection.at(1).mContent, contentString); @@ -302,7 +314,7 @@ class test_DiagnosisModel void test_SavePlainText() { - static const QRegularExpression re(R"(^Test_diagnosis_DiagnosisModel\r? + static const QRegularExpression re(QLatin1StringView(R"(^Test_diagnosis_DiagnosisModel\r? Application\r? Test_diagnosis_DiagnosisModel\r? Application Version\r? @@ -340,7 +352,7 @@ Antivirus and firewall\r? Antivirus information\r? .+\r? Firewall information\r? -.+)"); +.+)")); QVERIFY(re.match(mModel->getAsPlaintext()).hasMatch()); QTemporaryFile file; diff --git a/test/qt/file_provider/test_Downloader.cpp b/test/qt/file_provider/test_Downloader.cpp index e488760eb..74756354b 100644 --- a/test/qt/file_provider/test_Downloader.cpp +++ b/test/qt/file_provider/test_Downloader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_Downloader @@ -101,7 +102,7 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadSuccess); - const QUrl url("http://server/reader/icons/icon.png"); + const QUrl url("http://server/reader/icons/icon.png"_L1); downloader->download(url); mMockNetworkManager.fireFinished(); @@ -121,7 +122,7 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadFailed); - const QUrl url("http://server/reader/icons/icon.png"); + const QUrl url("http://server/reader/icons/icon.png"_L1); downloader->download(url); mMockNetworkManager.fireFinished(); @@ -138,7 +139,7 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadFailed); - const QUrl url("http://server/reader/icons/icon.png"); + const QUrl url("http://server/reader/icons/icon.png"_L1); downloader->download(url); mMockNetworkManager.fireFinished(); @@ -155,8 +156,8 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadFailed); - const QUrl urlCurrent("http://server/current"); - const QUrl urlurlNext("http://server/next"); + const QUrl urlCurrent("http://server/current"_L1); + const QUrl urlurlNext("http://server/next"_L1); QTest::ignoreMessage(QtDebugMsg, "Try abort of download: QUrl(\"http://server/current\")"); QVERIFY(!downloader->abort(urlCurrent)); @@ -198,7 +199,7 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadSuccess); - const QUrl url("http://server/reader/icons/icon.png"); + const QUrl url("http://server/reader/icons/icon.png"_L1); const QDateTime timestampInCache(QDate(2017, 6, 1), QTime(12, 00, 0, 0), QTimeZone::utc()); downloader->download(url, timestampInCache); @@ -223,7 +224,7 @@ class test_Downloader auto* const downloader = Env::getSingleton(); QSignalSpy spy(downloader, &Downloader::fireDownloadUnnecessary); - const QUrl url("http://server/reader/icons/icon.png"); + const QUrl url("http://server/reader/icons/icon.png"_L1); const QDateTime timestampInCache(QDate(2017, 7, 1), QTime(12, 00, 0, 0), QTimeZone::utc()); downloader->download(url, timestampInCache); diff --git a/test/qt/file_provider/test_FileProvider.cpp b/test/qt/file_provider/test_FileProvider.cpp index 5877a17e1..361c26b4c 100644 --- a/test/qt/file_provider/test_FileProvider.cpp +++ b/test/qt/file_provider/test_FileProvider.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "FileProvider.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_FileProvider @@ -50,10 +51,10 @@ class test_FileProvider public: test_FileProvider() - : mSection("reader") - , mName1("img_ACS_ACR1252U.png") - , mName2("img_ACS_ACR1252V.png") - , mDefaultPath(":/images/reader/default_no_reader.png") + : mSection("reader"_L1) + , mName1("img_ACS_ACR1252U.png"_L1) + , mName2("img_ACS_ACR1252V.png"_L1) + , mDefaultPath(":/images/reader/default_reader.png"_L1) { } diff --git a/test/qt/file_provider/test_UpdatableFile.cpp b/test/qt/file_provider/test_UpdatableFile.cpp index 75d1f9979..80be6750b 100644 --- a/test/qt/file_provider/test_UpdatableFile.cpp +++ b/test/qt/file_provider/test_UpdatableFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "UpdatableFile.h" @@ -11,6 +11,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_UpdatableFile @@ -70,7 +71,7 @@ class test_UpdatableFile void testFileOnlyInCache() { - const QString filename("img_ACS_ACR1252V.png"); + const QString filename("img_ACS_ACR1252V.png"_L1); const QString filenameInCache = filename + QStringLiteral("_20170601102132MST"); const QDate timestampDate(2017, 6, 1); const QTime timestampTime(10, 21, 32); @@ -93,8 +94,8 @@ class test_UpdatableFile void testFileOnlyInBundle() { - const QString filename("img_ACS_ACR1252U.png"); - const QString expectedPath = ":/updatable-files/reader/" + filename; + const QString filename("img_ACS_ACR1252U.png"_L1); + const QString expectedPath = ":/updatable-files/reader/"_L1 + filename; UpdatableFile updatableFile(mSection, filename); verifySectionCacheFolder(updatableFile); @@ -106,8 +107,8 @@ class test_UpdatableFile void testFileInCacheAndInBundle() { - const QString filename("img_ACS_ACR1252U.png"); - const QString expectedPath = ":/updatable-files/reader/" + filename; + const QString filename("img_ACS_ACR1252U.png"_L1); + const QString expectedPath = ":/updatable-files/reader/"_L1 + filename; const QString filenameInCache = filename + QStringLiteral("_20170601102132GMT"); UpdatableFile updatableFile(mSection, filename); const auto guard = touchFileInCache(filenameInCache, updatableFile); @@ -126,7 +127,7 @@ class test_UpdatableFile void testMoreThanOneVersionInCache() { - const QString filename("img_ACS_ACR1252U.png"); + const QString filename("img_ACS_ACR1252U.png"_L1); const QString filenameInCache1 = filename + QStringLiteral("_20170710120015WAST"); const QString filenameInCache2 = filename + QStringLiteral("_20170601102132UTC"); UpdatableFile updatableFile(mSection, filename); @@ -140,7 +141,7 @@ class test_UpdatableFile void testFileNeitherInCacheNorInBundle() { - const QString filename("img_ACS_ACR1252V.png"); + const QString filename("img_ACS_ACR1252V.png"_L1); UpdatableFile updatableFile(mSection, filename, QStringLiteral("DEFAULT_TEST")); verifySectionCacheFolder(updatableFile); @@ -151,7 +152,7 @@ class test_UpdatableFile void testIsDirty() { - const QString filename("img_ACS_ACR1252U.png"); + const QString filename("img_ACS_ACR1252U.png"_L1); const QString dirtyFilename = filename + QStringLiteral(".dirty"); UpdatableFile updatableFile(mSection, filename); @@ -168,7 +169,7 @@ class test_UpdatableFile void testMarkDirty() { - const QString filename("img_ACS_ACR1252U.png"); + const QString filename("img_ACS_ACR1252U.png"_L1); const QString dirtyFilename = filename + QStringLiteral(".dirty"); UpdatableFile updatableFile(mSection, filename); @@ -184,7 +185,7 @@ class test_UpdatableFile void testClearDirty() { - const QString filename("img_ACS_ACR1252U.png"); + const QString filename("img_ACS_ACR1252U.png"_L1); const QString dirtyFilename = filename + QStringLiteral(".dirty"); UpdatableFile updatableFile(mSection, filename); @@ -230,7 +231,7 @@ class test_UpdatableFile MockDownloader downloader; Env::set(Downloader::staticMetaObject, &downloader); - const QString filename("img_ACS_ACR1252U.png"); + const QString filename("img_ACS_ACR1252U.png"_L1); const QString filenameInCache = filename + QLatin1Char('_') + downloader.getTimeStampString(); UpdatableFile updatableFile(mSection, filename); @@ -254,7 +255,7 @@ class test_UpdatableFile MockDownloader downloader; Env::set(Downloader::staticMetaObject, &downloader); - const QString filename("img_updatetest.png"); + const QString filename("img_updatetest.png"_L1); UpdatableFile updatableFile(mSection, filename); QSignalSpy spy(&updatableFile, &UpdatableFile::fireUpdated); @@ -266,7 +267,7 @@ class test_UpdatableFile QCOMPARE(spy.count(), 1); const QString fileName = updatableFile.getName() + QLatin1Char('_') + downloader.getTimeStampString(); - const QString filePath = updatableFile.getSectionCachePath() + "/" + fileName; + const QString filePath = updatableFile.getSectionCachePath() + QLatin1Char('/') + fileName; const auto guard = qScopeGuard([&fileName, &updatableFile]{ removeFileFromCache(fileName, updatableFile); }); @@ -283,7 +284,7 @@ class test_UpdatableFile MockDownloader downloader(GlobalStatus::Code::Downloader_File_Not_Found); Env::set(Downloader::staticMetaObject, &downloader); - const QString filename("img_updatetest.png"); + const QString filename("img_updatetest.png"_L1); UpdatableFile updatableFile(mSection, filename); QSignalSpy spy(&updatableFile, &UpdatableFile::fireUpdated); @@ -291,7 +292,7 @@ class test_UpdatableFile updatableFile.update(); QCOMPARE(spy.count(), 0); - const QString filePath = updatableFile.getSectionCachePath() + "/" + updatableFile.getName() + QLatin1Char('_') + downloader.getTimeStampString(); + const QString filePath = updatableFile.getSectionCachePath() + QLatin1Char('/') + updatableFile.getName() + QLatin1Char('_') + downloader.getTimeStampString(); QFile testfile(filePath); QVERIFY(!testfile.exists()); } diff --git a/test/qt/global/test_BuildHelper.cpp b/test/qt/global/test_BuildHelper.cpp index a91ffc35a..95c525cab 100644 --- a/test/qt/global/test_BuildHelper.cpp +++ b/test/qt/global/test_BuildHelper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/global/test_CardReturnCode.cpp b/test/qt/global/test_CardReturnCode.cpp index ced985beb..bec34bec6 100644 --- a/test/qt/global/test_CardReturnCode.cpp +++ b/test/qt/global/test_CardReturnCode.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -25,7 +26,7 @@ class test_CardReturnCode void check_errorCodeToMessage() { QCOMPARE(CardReturnCodeUtil::toGlobalStatus(CardReturnCode::CANCELLATION_BY_USER).toErrorDescription(), - QString("The process has been cancelled by the card reader.")); + "The process has been cancelled by the card reader."_L1); } @@ -39,7 +40,7 @@ class test_CardReturnCode { const ECardApiResult& result = ECardApiResult(CardReturnCodeUtil::toGlobalStatus(CardReturnCode::CANCELLATION_BY_USER)); QCOMPARE(result.getMinor(), ECardApiResult::Minor::SAL_Cancellation_by_User); - QCOMPARE(result.getMessage(), QString("The process has been cancelled by the card reader.")); + QCOMPARE(result.getMessage(), "The process has been cancelled by the card reader."_L1); } diff --git a/test/qt/global/test_DeviceInfo.cpp b/test/qt/global/test_DeviceInfo.cpp index fa762c1a9..4cda4aabd 100644 --- a/test/qt/global/test_DeviceInfo.cpp +++ b/test/qt/global/test_DeviceInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/global/test_ECardApiResult.cpp b/test/qt/global/test_ECardApiResult.cpp index 235a793c6..1eb89ece8 100644 --- a/test/qt/global/test_ECardApiResult.cpp +++ b/test/qt/global/test_ECardApiResult.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "CardReturnCode.h" @@ -9,6 +9,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_ECardApiResult @@ -60,8 +61,8 @@ class test_ECardApiResult ECardApiResult result = ECardApiResult(GlobalStatus::Code::Workflow_Cannot_Confirm_IdCard_Authenticity, FailureCode::Reason::Change_Pin_User_Cancelled); QCOMPARE(result.getMajor(), ECardApiResult::Major::Error); QCOMPARE(result.getMinor(), ECardApiResult::Minor::AL_Internal_Error); - QCOMPARE(result.getMessage(), QString("The authenticity of your ID card could not be confirmed.")); - QCOMPARE(result.getMessageLang(), QString("en")); + QCOMPARE(result.getMessage(), "The authenticity of your ID card could not be confirmed."_L1); + QCOMPARE(result.getMessageLang(), "en"_L1); QCOMPARE(result.getFailureCode(), FailureCode::Reason::Change_Pin_User_Cancelled); } @@ -72,7 +73,7 @@ class test_ECardApiResult QCOMPARE(result.getMajor(), ECardApiResult::Major::Ok); QCOMPARE(result.getMinor(), ECardApiResult::Minor::null); QCOMPARE(result.getMessage(), QString()); - QCOMPARE(result.getMessageLang(), QString("en")); + QCOMPARE(result.getMessageLang(), "en"_L1); QCOMPARE(result.getFailureCode(), std::optional()); } @@ -84,42 +85,42 @@ class test_ECardApiResult QCOMPARE(logSpy.count(), 1); auto param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok | | \"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok | | \""_L1)); logSpy.clear(); qDebug() << ECardApiResult(GlobalStatus::Code::Workflow_Cannot_Confirm_IdCard_Authenticity); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#internalError | The authenticity of your ID card could not be confirmed.\"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#internalError | The authenticity of your ID card could not be confirmed.\""_L1)); logSpy.clear(); qDebug() << ECardApiResult(CardReturnCodeUtil::toGlobalStatus(CardReturnCode::CANCELLATION_BY_USER)); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/sal#cancellationByUser | The process has been cancelled by the card reader.\"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/sal#cancellationByUser | The process has been cancelled by the card reader.\""_L1)); logSpy.clear(); qDebug() << ECardApiResult(CardReturnCodeUtil::toGlobalStatus(CardReturnCode::UNDEFINED)); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#unknownError | An unexpected error has occurred during processing.\"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#unknownError | An unexpected error has occurred during processing.\""_L1)); logSpy.clear(); qDebug() << ECardApiResult(GlobalStatus::Code::Workflow_Preverification_Error); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/il/signature#invalidCertificatePath | Pre-verification failed.\"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/il/signature#invalidCertificatePath | Pre-verification failed.\""_L1)); logSpy.clear(); qDebug() << ECardApiResult(GlobalStatus::Code::Card_Cancellation_By_User, FailureCode::Reason::Change_Pin_User_Cancelled); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/sal#cancellationByUser | The process has been cancelled by the card reader. | Change_Pin_User_Cancelled\"")); + QVERIFY(param.at(0).toString().contains("Result: \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error | http://www.bsi.bund.de/ecard/api/1.1/resultminor/sal#cancellationByUser | The process has been cancelled by the card reader. | Change_Pin_User_Cancelled\""_L1)); } @@ -162,33 +163,33 @@ class test_ECardApiResult void convertToStatusMinorNull_data() { - QTest::addColumn("message"); + QTest::addColumn("message"); QTest::addColumn("origin"); - QTest::newRow("No msg - client") << QString() << ECardApiResult::Origin::Client; - QTest::newRow("No msg - server") << QString() << ECardApiResult::Origin::Server; - QTest::newRow("With msg - client") << QString("Game Over :(") << ECardApiResult::Origin::Client; - QTest::newRow("With msg - server") << QString("Game Over :(") << ECardApiResult::Origin::Server; + QTest::newRow("No msg - client") << QLatin1String() << ECardApiResult::Origin::Client; + QTest::newRow("No msg - server") << QLatin1String() << ECardApiResult::Origin::Server; + QTest::newRow("With msg - client") << "Game Over :("_L1 << ECardApiResult::Origin::Client; + QTest::newRow("With msg - server") << "Game Over :("_L1 << ECardApiResult::Origin::Server; } void convertToStatusMinorNull() { - QFETCH(QString, message); + QFETCH(QLatin1String, message); QFETCH(ECardApiResult::Origin, origin); const ECardApiResult result1(ECardApiResult::Major::Error, ECardApiResult::Minor::null, message, origin); QVERIFY(result1.toStatus().isError()); - const QString error("http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error"); + const QString error("http://www.bsi.bund.de/ecard/api/1.1/resultmajor#error"_L1); const ECardApiResult result2(error, QString(), message, origin); QVERIFY(result2.toStatus().isError()); - const ECardApiResult result3(error, "invalid", message, origin); + const ECardApiResult result3(error, "invalid"_L1, message, origin); QVERIFY(result3.toStatus().isError()); - const ECardApiResult result4(error, "http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#unknownError", message, origin); + const ECardApiResult result4(error, "http://www.bsi.bund.de/ecard/api/1.1/resultminor/al/common#unknownError"_L1, message, origin); QVERIFY(result4.toStatus().isError()); } @@ -216,7 +217,7 @@ class test_ECardApiResult void convertToStatus() { QFETCH(ECardApiResult::Minor, minor); - const ECardApiResult result(ECardApiResult::Major::Error, minor, "Game Over :(", ECardApiResult::Origin::Client); + const ECardApiResult result(ECardApiResult::Major::Error, minor, "Game Over :("_L1, ECardApiResult::Origin::Client); QVERIFY(result.toStatus().isError()); } @@ -280,10 +281,10 @@ class test_ECardApiResult break; } - const ECardApiResult result_1(ECardApiResult::Major::Error, minor, "Game Over :(", ECardApiResult::Origin::Client); + const ECardApiResult result_1(ECardApiResult::Major::Error, minor, "Game Over :("_L1, ECardApiResult::Origin::Client); QVERIFY(result_1 == ECardApiResult(result_1.toStatus())); - const ECardApiResult result_2(ECardApiResult::Major::Error, minor, "Game Over :(", ECardApiResult::Origin::Server); + const ECardApiResult result_2(ECardApiResult::Major::Error, minor, "Game Over :("_L1, ECardApiResult::Origin::Server); QVERIFY(!(result_2 == ECardApiResult(result_2.toStatus()))); const ECardApiResult result_3(ECardApiResult::Major::Error, minor, ECardApiResult::getMessage(minor), ECardApiResult::Origin::Server); @@ -295,10 +296,10 @@ class test_ECardApiResult void illegalInitialization() { - ECardApiResult internalError = ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Internal_Error, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.", ECardApiResult::Origin::Client); + ECardApiResult internalError = ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Internal_Error, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."_L1, ECardApiResult::Origin::Client); - QCOMPARE(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::null, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.", ECardApiResult::Origin::Client), internalError); - QCOMPARE(ECardApiResult(ECardApiResult::Major::Ok, ECardApiResult::Minor::AL_Parameter_Error, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr.", ECardApiResult::Origin::Client), internalError); + QCOMPARE(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::null, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."_L1, ECardApiResult::Origin::Client), internalError); + QCOMPARE(ECardApiResult(ECardApiResult::Major::Ok, ECardApiResult::Minor::AL_Parameter_Error, "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."_L1, ECardApiResult::Origin::Client), internalError); } diff --git a/test/qt/global/test_EnumHelper.cpp b/test/qt/global/test_EnumHelper.cpp index c4af81767..03d329a12 100644 --- a/test/qt/global/test_EnumHelper.cpp +++ b/test/qt/global/test_EnumHelper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,9 +9,12 @@ #include "EnumHelper.h" #include "LogHandler.h" +#include "TestFileHelper.h" + #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; namespace @@ -30,6 +33,8 @@ defineEnumType(TestEnum1, FIRST, SECOND, THIRD) defineEnumType(TestEnum2, FIRST = 0xFF, SECOND = 0x01, THIRD = 0xAA) defineTypedEnumType(TestEnum3, char, FIRST = static_cast(0xFF), SECOND = static_cast(0x01), THIRD = static_cast(0xAA)) + +defineEnumTypeQmlExposed(TestEnum4, A, B, C) } // namespace governikus class test_EnumHelper @@ -75,11 +80,11 @@ class test_EnumHelper void operatorString() { - QString str = "this is a dummy: "; + QString str = "this is a dummy: "_L1; str += TestEnum1::FIRST; QCOMPARE(str, QStringLiteral("this is a dummy: FIRST")); - QString str2 = "other text" + TestEnum1::FIRST + str + TestEnum1::SECOND + " test"; + QString str2 = "other text"_L1 + TestEnum1::FIRST + str + TestEnum1::SECOND + " test"_L1; QCOMPARE(str, QStringLiteral("this is a dummy: FIRST")); QCOMPARE(str2, QStringLiteral("other textFIRSTthis is a dummy: FIRSTSECOND test")); } @@ -88,11 +93,17 @@ class test_EnumHelper void operatorDebug() { QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + qDebug() << TestEnum1::FIRST; + QCOMPARE(logSpy.count(), 1); + QVERIFY(TestFileHelper::containsLog(logSpy, "FIRST"_L1)); + + logSpy.takeFirst(); + QCOMPARE(logSpy.count(), 0); + qDebug() << QList({TestEnum1::FIRST, TestEnum1::SECOND}); QCOMPARE(logSpy.count(), 1); - auto result = logSpy.takeFirst(); - QVERIFY(result.at(0).toString().endsWith(QStringLiteral("FIRST") + lineBreak)); + QVERIFY(TestFileHelper::containsLog(logSpy, "(FIRST, SECOND)"_L1)); } @@ -116,10 +127,10 @@ class test_EnumHelper void list() { - const QVector& list1 = Enum::getList(); + const QList& list1 = Enum::getList(); QCOMPARE(list1.size(), 3); - const QVector& list2 = Enum::getList(); + const QList& list2 = Enum::getList(); QCOMPARE(list2.size(), 3); QCOMPARE(list1, list2); @@ -177,7 +188,7 @@ class test_EnumHelper QCOMPARE(Enum::fromString("abc", TestEnum1::THIRD), TestEnum1::THIRD); QVERIFY(Enum::fromString("FIRST", TestEnum1::THIRD) != TestEnum1::THIRD); - QString value = "FIRST"; + QString value = "FIRST"_L1; QVERIFY(Enum::fromString(value, TestEnum1::THIRD) != TestEnum1::THIRD); } @@ -225,6 +236,17 @@ class test_EnumHelper } + void enumProperty() + { + QCOMPARE(EnumTestEnum1::staticMetaObject.classInfoCount(), 0); + + QCOMPARE(EnumTestEnum4::staticMetaObject.classInfoCount(), 1); + const auto meta = EnumTestEnum4::staticMetaObject.classInfo(0); + QCOMPARE(meta.name(), "QML.Element"); + QCOMPARE(meta.value(), "TestEnum4"); + } + + }; QTEST_GUILESS_MAIN(test_EnumHelper) diff --git a/test/qt/global/test_Env.cpp b/test/qt/global/test_Env.cpp index d12a2dfb2..2d6f754b4 100644 --- a/test/qt/global/test_Env.cpp +++ b/test/qt/global/test_Env.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -494,7 +494,7 @@ class test_Env void mockArgs() { - QScopedPointer impl(Env::create(QString("flupp"))); + QScopedPointer impl(Env::create(QStringLiteral("flupp"))); QVERIFY(impl); QCOMPARE(impl->dummy(), QLatin1String("flupp")); impl.reset(); @@ -539,7 +539,7 @@ class test_Env Env::setCreator(funcString); Env::setCreator(funcDefault); - QScopedPointer catcher(Env::create(QString("bla"))); + QScopedPointer catcher(Env::create(QStringLiteral("bla"))); QVERIFY(catcher); QCOMPARE(catcher->dummy(), QLatin1String("YEAH: bla")); @@ -586,7 +586,7 @@ class test_Env void mockMove() { - auto obj = Env::create(QString("huhu")); + auto obj = Env::create(QStringLiteral("huhu")); QCOMPARE(obj.data(), QLatin1String("huhu")); std::function func = [](const QString&){ @@ -594,7 +594,7 @@ class test_Env }; Env::setCreator(func); - auto mock = Env::create(QString("huhu")); + auto mock = Env::create(QStringLiteral("huhu")); QCOMPARE(mock.data(), QLatin1String("mocked")); QCOMPARE(obj.data(), QLatin1String("huhu")); @@ -602,7 +602,7 @@ class test_Env return TestMoveCtorAssign(QStringLiteral("mocked2")); }; Env::setCreator(func); - mock = Env::create(QString("huhu2")); + mock = Env::create(QStringLiteral("huhu2")); QCOMPARE(mock.data(), QLatin1String("mocked2")); QCOMPARE(obj.data(), QLatin1String("huhu")); } @@ -679,7 +679,7 @@ class test_Env }; TestMockedInstance mock; - QVector> threads; + QList> threads; for (int i = 0; i < 100; ++i) { diff --git a/test/qt/global/test_FailureCode.cpp b/test/qt/global/test_FailureCode.cpp index ca6b1f0a1..7552b9de6 100644 --- a/test/qt/global/test_FailureCode.cpp +++ b/test/qt/global/test_FailureCode.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -45,11 +46,11 @@ class test_FailureCode QTest::newRow("Empty") << FailureCode::FailureInfoMap(); QTest::newRow("One entry") << FailureCode::FailureInfoMap({ - {FailureCode::Info::State_Name, "MyStateName"} + {FailureCode::Info::State_Name, "MyStateName"_L1} }); QTest::newRow("Two entries") << FailureCode::FailureInfoMap({ - {FailureCode::Info::State_Name, "MyStateName"}, - {FailureCode::Info::Card_Return_Code, "MyReturnCode"} + {FailureCode::Info::State_Name, "MyStateName"_L1}, + {FailureCode::Info::Card_Return_Code, "MyReturnCode"_L1} }); } diff --git a/test/qt/global/test_FileDestination.cpp b/test/qt/global/test_FileDestination.cpp index 6094b9460..336e9694e 100644 --- a/test/qt/global/test_FileDestination.cpp +++ b/test/qt/global/test_FileDestination.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/global/test_FuncUtils.cpp b/test/qt/global/test_FuncUtils.cpp index 2a9686a30..b470788f9 100644 --- a/test/qt/global/test_FuncUtils.cpp +++ b/test/qt/global/test_FuncUtils.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -60,20 +60,20 @@ class test_FuncUtils Q_OBJECT private: - QVector mReaders; + QList mReaders; private Q_SLOTS: void initTestCase() { - mReaders = QVector({Reader(QStringLiteral("NFC Reader"), true), - Reader(QStringLiteral("Remote Reader"), false), - Reader(QStringLiteral("PCSC Reader"), true)}); + mReaders = QList({Reader(QStringLiteral("NFC Reader"), true), + Reader(QStringLiteral("Remote Reader"), false), + Reader(QStringLiteral("PCSC Reader"), true)}); } void testMapWithNonVoid() { - const QVector readerNamesVector = map([](const Reader& r){ + const QList readerNamesVector = map([](const Reader& r){ return r.getName(); }, mReaders); @@ -84,7 +84,7 @@ class test_FuncUtils const QList readerNamesList = map([](const Reader& r){ return r.getName(); - }, mReaders.toList()); + }, mReaders); QCOMPARE(readerNamesList.size(), 3); QCOMPARE(readerNamesList.at(0), QStringLiteral("NFC Reader")); @@ -95,7 +95,7 @@ class test_FuncUtils void testFilter() { - const QVector connectedReaders = filter([](const Reader& r){ + const QList connectedReaders = filter([](const Reader& r){ return r.isConnected(); }, mReaders); diff --git a/test/qt/global/test_GlobalStatus.cpp b/test/qt/global/test_GlobalStatus.cpp index b7a63b302..21c0d6466 100644 --- a/test/qt/global/test_GlobalStatus.cpp +++ b/test/qt/global/test_GlobalStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -66,7 +66,7 @@ class test_GlobalStatus QTest::newRow("noSupportedApiLevel") << GlobalStatus::Code::IfdConnector_NoSupportedApiLevel << tr("Your smartphone as card reader (SaC) version is incompatible with the local version. Please install the latest %1 version on both your smartphone and your computer.").arg(QCoreApplication::applicationName()); QTest::newRow("connectionTimeout") << GlobalStatus::Code::IfdConnector_ConnectionTimeout << tr("A timeout occurred while trying to establish a connection to the smartphone as card reader (SaC)."); QTest::newRow("connectionError") << GlobalStatus::Code::IfdConnector_ConnectionError << tr("An error occurred while trying to establish a connection to the smartphone as card reader (SaC)."); - QTest::newRow("hostRefused") << GlobalStatus::Code::IfdConnector_RemoteHostRefusedConnection << tr("The smartphone to be paired has rejected the connection. Please check the pairing code. If no pairing code is shown activate the pairing mode."); + QTest::newRow("hostRefused") << GlobalStatus::Code::IfdConnector_RemoteHostRefusedConnection << tr("The smartphone to be paired has rejected the connection. Please check the pairing code."); QTest::newRow("fileNotFound") << GlobalStatus::Code::Downloader_File_Not_Found << tr("File not found."); QTest::newRow("cannotSaveFile") << GlobalStatus::Code::Downloader_Cannot_Save_File << tr("Cannot save file."); QTest::newRow("dataCorrupted") << GlobalStatus::Code::Downloader_Data_Corrupted << tr("Received data were corrupted."); diff --git a/test/qt/global/test_LanguageLoader.cpp b/test/qt/global/test_LanguageLoader.cpp index 8acb87886..9d1af9e54 100644 --- a/test/qt/global/test_LanguageLoader.cpp +++ b/test/qt/global/test_LanguageLoader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_LanguageLoader @@ -161,8 +162,8 @@ class test_LanguageLoader void defaultPath() { - LanguageLoader::getInstance().setPath("dummy"); - QCOMPARE(LanguageLoader::getInstance().getPath(), QString("dummy")); + LanguageLoader::getInstance().setPath("dummy"_L1); + QCOMPARE(LanguageLoader::getInstance().getPath(), "dummy"_L1); } diff --git a/test/qt/global/test_LogHandler.cpp b/test/qt/global/test_LogHandler.cpp index 4a5d7dc25..d4f58a97e 100644 --- a/test/qt/global/test_LogHandler.cpp +++ b/test/qt/global/test_LogHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -507,8 +507,8 @@ class test_LogHandler << QByteArray("initApp"); // the const is fake for better unit testing - QTest::newRow("UILoader::load") << QByteArray("std::enable_if_t::value, bool> governikus::UILoader::load() const [with T = governikus::UIPlugInJson; std::enable_if_t::value, bool> = bool]") - << QByteArray("UILoader::load"); + QTest::newRow("UiLoader::load") << QByteArray("std::enable_if_t::value, bool> governikus::UiLoader::load() const [with T = governikus::UiPluginJson; std::enable_if_t::value, bool> = bool]") + << QByteArray("UiLoader::load"); QTest::newRow("anonymous") << QByteArray("virtual QList (anonymous namespace)::SystemProxyFactory::queryProxy(const QNetworkProxyQuery &)") << QByteArray("SystemProxyFactory::queryProxy"); diff --git a/test/qt/global/test_Randomizer.cpp b/test/qt/global/test_Randomizer.cpp index 850d7bf51..196392c67 100644 --- a/test/qt/global/test_Randomizer.cpp +++ b/test/qt/global/test_Randomizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/global/test_ResourceLoader.cpp b/test/qt/global/test_ResourceLoader.cpp index 2d116edfb..a38bca217 100644 --- a/test/qt/global/test_ResourceLoader.cpp +++ b/test/qt/global/test_ResourceLoader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_ResourceLoader @@ -46,8 +47,8 @@ class test_ResourceLoader QVERIFY(logSpy.count() > 0); auto param = logSpy.takeLast(); - QVERIFY(param.at(0).toString().contains("Register resource: ")); - QVERIFY(param.at(0).toString().contains(" | true")); + QVERIFY(param.at(0).toString().contains("Register resource: "_L1)); + QVERIFY(param.at(0).toString().contains(" | true"_L1)); } @@ -63,8 +64,8 @@ class test_ResourceLoader QVERIFY(logSpy.count() > 1); auto param = logSpy.takeLast(); - QVERIFY(param.at(0).toString().contains("Unregister resource: ")); - QVERIFY(param.at(0).toString().contains(" | true")); + QVERIFY(param.at(0).toString().contains("Unregister resource: "_L1)); + QVERIFY(param.at(0).toString().contains(" | true"_L1)); } @@ -73,8 +74,8 @@ class test_ResourceLoader QVERIFY(!ResourceLoader::getInstance().isLoaded()); ResourceLoader::getInstance().init(); - QVERIFY(!QFile(":/non_existing_dummy_test").exists()); - QVERIFY(QFile(":/images/ausweis.svg").exists()); + QVERIFY(!QFile(":/non_existing_dummy_test"_L1).exists()); + QVERIFY(QFile(":/images/ausweis.svg"_L1).exists()); } diff --git a/test/qt/global/test_VersionInfo.cpp b/test/qt/global/test_VersionInfo.cpp index 67e6f03bc..1ddc9e068 100644 --- a/test/qt/global/test_VersionInfo.cpp +++ b/test/qt/global/test_VersionInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ #include @@ -9,6 +9,7 @@ #include "VersionInfo.h" +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -47,23 +48,23 @@ class test_VersionInfo QCOMPARE(jsonError.error, QJsonParseError::NoError); const auto obj = json.object(); - QCOMPARE(obj["Name"].toString(), QLatin1String("AusweisApp2")); - QCOMPARE(obj["Specification-Title"].toString(), QLatin1String("TR-03124-1")); - QCOMPARE(obj["Specification-Version"].toString(), QLatin1String("1.4")); - QCOMPARE(obj["Specification-Vendor"].toString(), QLatin1String("Federal Office for Information Security")); - QCOMPARE(obj["Implementation-Title"].toString(), QLatin1String("AusweisApp2")); - QCOMPARE(obj["Implementation-Version"].toString(), QLatin1String("x.y.z")); - QCOMPARE(obj["Implementation-Vendor"].toString(), QLatin1String("Governikus GmbH & Co. KG")); + QCOMPARE(obj["Name"_L1].toString(), QLatin1String("AusweisApp2")); + QCOMPARE(obj["Specification-Title"_L1].toString(), QLatin1String("TR-03124-1")); + QCOMPARE(obj["Specification-Version"_L1].toString(), QLatin1String("1.4")); + QCOMPARE(obj["Specification-Vendor"_L1].toString(), QLatin1String("Federal Office for Information Security")); + QCOMPARE(obj["Implementation-Title"_L1].toString(), QLatin1String("AusweisApp2")); + QCOMPARE(obj["Implementation-Version"_L1].toString(), QLatin1String("x.y.z")); + QCOMPARE(obj["Implementation-Vendor"_L1].toString(), QLatin1String("Governikus GmbH & Co. KG")); } void fromTextInvalidData() { - auto versionInfo = VersionInfo::fromText("skdkfsn sdnk fskdfn sdfk sflk nd\n" - "\n" - ":\n" - " :\r\t\n" - ""); + auto versionInfo = VersionInfo::fromText(QLatin1StringView("skdkfsn sdnk fskdfn sdfk sflk nd\n" + "\n" + ":\n" + " :\r\t\n" + "")); QVERIFY(versionInfo.getName().isNull()); QVERIFY(versionInfo.getSpecificationTitle().isNull()); @@ -77,13 +78,13 @@ class test_VersionInfo void fromText() { - auto versionInfo = VersionInfo::fromText("Name: MyName\n" - "Specification-Title: MySpecTitle\n" - "Specification-Version: MySpecVersion\n" - "Specification-Vendor: MySpecVendor\n" - "Implementation-Title: MyImplTitle\n" - "Implementation-Version: MyImplVersion\n" - "Implementation-Vendor: MyImplVendor"); + auto versionInfo = VersionInfo::fromText(QLatin1StringView("Name: MyName\n" + "Specification-Title: MySpecTitle\n" + "Specification-Version: MySpecVersion\n" + "Specification-Vendor: MySpecVendor\n" + "Implementation-Title: MyImplTitle\n" + "Implementation-Version: MyImplVersion\n" + "Implementation-Vendor: MyImplVendor")); QCOMPARE(versionInfo.getName(), QLatin1String("MyName")); QCOMPARE(versionInfo.getSpecificationTitle(), QLatin1String("MySpecTitle")); diff --git a/test/qt/global/test_VersionNumber.cpp b/test/qt/global/test_VersionNumber.cpp index 3e5cccc61..88215f910 100644 --- a/test/qt/global/test_VersionNumber.cpp +++ b/test/qt/global/test_VersionNumber.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_VersionNumber @@ -20,40 +21,40 @@ class test_VersionNumber private Q_SLOTS: void compare() { - VersionNumber number1("1.2.3.4.5"); - VersionNumber number2("1.2.3.4.5"); + VersionNumber number1("1.2.3.4.5"_L1); + VersionNumber number2("1.2.3.4.5"_L1); QCOMPARE(number1, number2); - VersionNumber number3("4.5"); + VersionNumber number3("4.5"_L1); QVERIFY(number1 != number3); QVERIFY(number1 < number3); QVERIFY(number3 > number1); - VersionNumber number4("1.12.0+123"); - VersionNumber number5("1.12.0+124"); + VersionNumber number4("1.12.0+123"_L1); + VersionNumber number5("1.12.0+124"_L1); QVERIFY(number4 < number5); QVERIFY(number5 > number4); - VersionNumber number6(""); + VersionNumber number6(""_L1); QVERIFY(number1 != number6); - VersionNumber number7("1.12.0+123-default-abc123"); - VersionNumber number8("1.12.0+123-default-abc123"); + VersionNumber number7("1.12.0+123-default-abc123"_L1); + VersionNumber number8("1.12.0+123-default-abc123"_L1); QVERIFY(number7 == number8); QVERIFY(!(number7 < number8)); QVERIFY(!(number7 > number8)); QVERIFY(!(number8 < number7)); QVERIFY(!(number8 > number7)); - VersionNumber number9("1.12.0+123-stable-xyz123"); + VersionNumber number9("1.12.0+123-stable-xyz123"_L1); QVERIFY(number7 != number9); QVERIFY(!(number7 < number9)); QVERIFY(!(number7 > number9)); QVERIFY(!(number9 < number7)); QVERIFY(!(number9 > number7)); - VersionNumber number10("1.01.0+123-default-abc123"); - VersionNumber number11("1.1.0+123-default-abc123"); + VersionNumber number10("1.01.0+123-default-abc123"_L1); + VersionNumber number11("1.1.0+123-default-abc123"_L1); QVERIFY(number10 == number11); QVERIFY(!(number10 < number11)); QVERIFY(!(number11 > number10)); @@ -62,12 +63,12 @@ class test_VersionNumber void parser() { - VersionNumber number("1.10.3.8"); + VersionNumber number("1.10.3.8"_L1); QCOMPARE(number.getVersionNumber().majorVersion(), 1); QCOMPARE(number.getVersionNumber().minorVersion(), 10); QCOMPARE(number.getVersionNumber().microVersion(), 3); - VersionNumber numberSpace(" 1.20.0 "); + VersionNumber numberSpace(" 1.20.0 "_L1); QCOMPARE(numberSpace.getVersionNumber().majorVersion(), 1); QCOMPARE(numberSpace.getVersionNumber().minorVersion(), 20); QCOMPARE(numberSpace.getVersionNumber().microVersion(), 0); @@ -103,19 +104,19 @@ class test_VersionNumber void branch_data() { - QTest::addColumn("branch"); + QTest::addColumn("branch"); - QTest::newRow("1.99+432") << QString(); - QTest::newRow("1.99+98-default-et43t") << QString("default"); - QTest::newRow("1.99+1-stable") << QString("stable"); - QTest::newRow("1.99+98-default-et43t+") << QString("default"); - QTest::newRow("1.99+98-default-draft-et43t+") << QString("default"); + QTest::newRow("1.99+432") << QLatin1StringView(); + QTest::newRow("1.99+98-default-et43t") << "default"_L1; + QTest::newRow("1.99+1-stable") << "stable"_L1; + QTest::newRow("1.99+98-default-et43t+") << "default"_L1; + QTest::newRow("1.99+98-default-draft-et43t+") << "default"_L1; } void branch() { - QFETCH(QString, branch); + QFETCH(QLatin1StringView, branch); const auto& version = QString::fromLatin1(QTest::currentDataTag()); QCOMPARE(VersionNumber(version).getBranch(), branch); @@ -124,18 +125,18 @@ class test_VersionNumber void revision_data() { - QTest::addColumn("revision"); + QTest::addColumn("revision"); - QTest::newRow("1.99+432") << QString(); - QTest::newRow("1.99+98-default-et43t") << QString("et43t"); - QTest::newRow("1.99+1-stable") << QString(); - QTest::newRow("1.99+98-default-draft-et43t+") << QString("et43t+"); + QTest::newRow("1.99+432") << QLatin1StringView(); + QTest::newRow("1.99+98-default-et43t") << "et43t"_L1; + QTest::newRow("1.99+1-stable") << QLatin1StringView(); + QTest::newRow("1.99+98-default-draft-et43t+") << "et43t+"_L1; } void revision() { - QFETCH(QString, revision); + QFETCH(QLatin1StringView, revision); const auto& version = QString::fromLatin1(QTest::currentDataTag()); QCOMPARE(VersionNumber(version).getRevision(), revision); @@ -207,15 +208,15 @@ class test_VersionNumber void toString() { - VersionNumber number1("1.6.0+422312-stable-2143eg435"); - QCOMPARE(number1.getVersionNumber().toString(), QString("1.6.0")); + VersionNumber number1("1.6.0+422312-stable-2143eg435"_L1); + QCOMPARE(number1.getVersionNumber().toString(), "1.6.0"_L1); } void debugStream() { QTest::ignoreMessage(QtDebugMsg, "1.6.0+422312-stable-2143eg435"); - VersionNumber number1("1.6.0+422312-stable-2143eg435"); + VersionNumber number1("1.6.0+422312-stable-2143eg435"_L1); qDebug() << number1; } diff --git a/test/qt/ifd/local/test_LocalTlsServer.cpp b/test/qt/ifd/local/test_LocalTlsServer.cpp index 075115790..0e2e68274 100644 --- a/test/qt/ifd/local/test_LocalTlsServer.cpp +++ b/test/qt/ifd/local/test_LocalTlsServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -40,7 +40,7 @@ class test_LocalTlsServer void listenAddress() { - const QVector allowedHosts = {QHostAddress::LocalHostIPv6, QHostAddress::LocalHost}; + const QList allowedHosts = {QHostAddress::LocalHostIPv6, QHostAddress::LocalHost}; QVERIFY(allowedHosts.contains(mServer.serverAddress())); } @@ -59,7 +59,7 @@ class test_LocalTlsServer }); QTcpSocket* remoteSocket = nullptr; - connect(&mServer, &LocalTlsServer::fireNewConnection, this, [&remoteSocket](QTcpSocket* pSocket) + connect(&mServer, &LocalTlsServer::fireNewConnection, this, [&remoteSocket](QTcpSocket* pSocket) // clazy:exclude=lambda-in-connect { remoteSocket = pSocket; }); diff --git a/test/qt/ifd/local/test_LocalWebSocketServer.cpp b/test/qt/ifd/local/test_LocalWebSocketServer.cpp index e74a3ec41..cc0392b22 100644 --- a/test/qt/ifd/local/test_LocalWebSocketServer.cpp +++ b/test/qt/ifd/local/test_LocalWebSocketServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ifd/messages/test_Discovery.cpp b/test/qt/ifd/messages/test_Discovery.cpp index b615285ad..e0453d7d7 100644 --- a/test/qt/ifd/messages/test_Discovery.cpp +++ b/test/qt/ifd/messages/test_Discovery.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/Discovery.h" @@ -43,7 +43,7 @@ class test_Discovery QCOMPARE(msg.getIfdName(), QString()); QCOMPARE(msg.getIfdId(), QString()); QVERIFY(msg.getPort() == 0); - QCOMPARE(msg.getSupportedApis(), QVector()); + QCOMPARE(msg.getSupportedApis(), QList()); QCOMPARE(msg.getPairing(), false); QCOMPARE(logSpy.count(), 6); @@ -71,7 +71,7 @@ class test_Discovery QCOMPARE(discovery.getIfdName(), QStringLiteral("Sony Xperia Z5 compact")); QCOMPARE(discovery.getIfdId(), QStringLiteral("0123456789ABCDEF")); QVERIFY(discovery.getPort() == static_cast(24728)); - QCOMPARE(discovery.getSupportedApis(), QVector({IfdVersion::Version::v0, IfdVersion::Version::v2})); + QCOMPARE(discovery.getSupportedApis(), QList({IfdVersion::Version::v0, IfdVersion::Version::v2})); QVERIFY(!discovery.getPairing()); discovery.setPairing(true); @@ -168,9 +168,9 @@ class test_Discovery QCOMPARE(discovery.getType(), IfdMessageType::UNDEFINED); QCOMPARE(discovery.getContextHandle(), QString()); QCOMPARE(discovery.getIfdName(), QStringLiteral("Sony Xperia Z5 compact")); - QCOMPARE(discovery.getIfdId(), QStringLiteral("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")); + QCOMPARE(discovery.getIfdId(), QStringLiteral("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF").toLower()); QVERIFY(discovery.getPort() == static_cast(24728)); - QCOMPARE(discovery.getSupportedApis(), QVector({IfdVersion::Version::v0})); + QCOMPARE(discovery.getSupportedApis(), QList({IfdVersion::Version::v0})); QCOMPARE(discovery.getPairing(), pairing); } @@ -333,7 +333,7 @@ class test_Discovery QCOMPARE(discovery.getIfdName(), QString()); QCOMPARE(discovery.getIfdId(), QString()); QVERIFY(discovery.getPort() == 0); - QCOMPARE(discovery.getSupportedApis(), QVector()); + QCOMPARE(discovery.getSupportedApis(), QList()); QCOMPARE(discovery.getPairing(), false); QCOMPARE(logSpy.count(), 5); @@ -365,7 +365,7 @@ class test_Discovery const QJsonObject& obj = QJsonDocument::fromJson(message).object(); const Discovery discovery(obj); QVERIFY(discovery.isIncomplete()); - QCOMPARE(discovery.getSupportedApis(), QVector({IfdVersion::Version::v0})); + QCOMPARE(discovery.getSupportedApis(), QList({IfdVersion::Version::v0})); QCOMPARE(logSpy.count(), 1); QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of \"SupportedAPI\" should be of type \"string array\""))); @@ -439,7 +439,7 @@ class test_Discovery const Discovery discovery(obj); QCOMPARE(discovery.isIncomplete(), incomplete); - QCOMPARE(discovery.getIfdId(), QString::fromLatin1(ifdid)); + QCOMPARE(discovery.getIfdId(), QString::fromLatin1(ifdid).toLower()); QCOMPARE(logSpy.count(), incomplete ? 1 : 0); if (incomplete) @@ -449,18 +449,30 @@ class test_Discovery } + void sameIfdId_data() + { + QTest::addColumn("json_ifdid"); + + QTest::newRow("lower case") << QByteArray("0575e99867361c26442ece18bed6f955ab7dd269ae8f42d3a21af0e734c3d8d9"); + QTest::newRow("upper case") << QByteArray("0575E99867361C26442ECE18BED6F955AB7DD269AE8F42D3A21AF0E734C3D8D9"); + } + + void sameIfdId() { + QFETCH(QByteArray, json_ifdid); + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - const QByteArray messageHash(R"({ - "IFDID": "0575e99867361c26442ece18bed6f955ab7dd269ae8f42d3a21af0e734c3d8d9", + QByteArray messageHash(R"({ + "IFDID": "[IFDID]", "IFDName": "Sony Xperia Z5 compact", "SupportedAPI": ["IFDInterface_WebSocket_v0"], "msg": "REMOTE_IFD", "pairing": true, "port": 24728 })"); + messageHash.replace("[IFDID]", json_ifdid); const QJsonObject& objHash = QJsonDocument::fromJson(messageHash).object(); const Discovery discoveryHash(objHash); QCOMPARE(logSpy.count(), 0); diff --git a/test/qt/ifd/messages/test_IfdConnect.cpp b/test/qt/ifd/messages/test_IfdConnect.cpp index c45c00ec2..a27ebc70c 100644 --- a/test/qt/ifd/messages/test_IfdConnect.cpp +++ b/test/qt/ifd/messages/test_IfdConnect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdConnect.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,12 +36,12 @@ class test_IfdConnect QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotName\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"exclusive\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDConnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotName\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"exclusive\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDConnect"_L1)); } @@ -149,14 +149,14 @@ class test_IfdConnect if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDConnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDConnect"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDConnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDConnect"_L1)); } @@ -180,8 +180,8 @@ class test_IfdConnect QVERIFY(!ifdConnect.isExclusive()); QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotName\" should be of type \"string\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"exclusive\" should be of type \"boolean\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotName\" should be of type \"string\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"exclusive\" should be of type \"boolean\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdConnectResponse.cpp b/test/qt/ifd/messages/test_IfdConnectResponse.cpp index 012ae06e5..f2c43aef0 100644 --- a/test/qt/ifd/messages/test_IfdConnectResponse.cpp +++ b/test/qt/ifd/messages/test_IfdConnectResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdConnectResponse.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,13 +36,13 @@ class test_IfdConnectResponse QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 7); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDConnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDConnectResponse"_L1)); } @@ -156,14 +156,14 @@ class test_IfdConnectResponse if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDConnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDConnectResponse"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDConnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDConnectResponse"_L1)); } @@ -189,7 +189,7 @@ class test_IfdConnectResponse QCOMPARE(ifdConnectResponse.getResultMinor(), ECardApiResult::Minor::null); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdDestroyPaceChannel.cpp b/test/qt/ifd/messages/test_IfdDestroyPaceChannel.cpp new file mode 100644 index 000000000..bd24369be --- /dev/null +++ b/test/qt/ifd/messages/test_IfdDestroyPaceChannel.cpp @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "messages/IfdDestroyPaceChannel.h" + +#include "LogHandler.h" +#include "TestFileHelper.h" + +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +Q_DECLARE_METATYPE(IfdVersion::Version) + + +class test_IfdDestroyPaceChannel + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + Env::getSingleton()->init(); + } + + + void invalidJson() + { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message("FooBar"); + const auto& obj = QJsonDocument::fromJson(message).object(); + QVERIFY(obj.isEmpty()); + + IfdDestroyPaceChannel msg(obj); + QVERIFY(msg.isIncomplete()); + + QCOMPARE(logSpy.count(), 5); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"msg\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Invalid messageType received: \"\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"ContextHandle\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"SlotHandle\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannel"))); + } + + + void values() + { + const IfdDestroyPaceChannel ifdDestroyPaceChannel(QStringLiteral("SlotHandle")); + + QVERIFY(!ifdDestroyPaceChannel.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannel.getType(), IfdMessageType::IFDDestroyPACEChannel); + QCOMPARE(ifdDestroyPaceChannel.getContextHandle(), QString()); + QCOMPARE(ifdDestroyPaceChannel.getSlotHandle(), QStringLiteral("SlotHandle")); + } + + + void toJson_data() + { + QTest::addColumn("version"); + QTest::newRow("Unknown") << IfdVersion::Version::Unknown; + QTest::newRow("v0") << IfdVersion::Version::v0; + QTest::newRow("v2") << IfdVersion::Version::v2; + } + + + void toJson() + { + QFETCH(IfdVersion::Version, version); + + const IfdDestroyPaceChannel ifdDestroyPaceChannel(QStringLiteral("SlotHandle")); + + const QByteArray& byteArray = ifdDestroyPaceChannel.toByteArray(version, QStringLiteral("TestContext")); + QCOMPARE(byteArray, + QByteArray("{\n" + " \"ContextHandle\": \"TestContext\",\n" + " \"SlotHandle\": \"SlotHandle\",\n" + " \"msg\": \"IFDDestroyPACEChannel\"\n" + "}\n")); + + const QJsonObject obj = QJsonDocument::fromJson(byteArray).object(); + QCOMPARE(obj.size(), 3); + QCOMPARE(obj.value(QLatin1String("msg")).toString(), QStringLiteral("IFDDestroyPACEChannel")); + QCOMPARE(obj.value(QLatin1String("ContextHandle")).toString(), QStringLiteral("TestContext")); + QCOMPARE(obj.value(QLatin1String("SlotHandle")).toString(), QStringLiteral("SlotHandle")); + } + + + void fromJson() + { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message(R"({ + "ContextHandle": "TestContext", + "SlotHandle": "SlotHandle", + "msg": "IFDDestroyPACEChannel" + })"); + + const QJsonObject& obj = QJsonDocument::fromJson(message).object(); + const IfdDestroyPaceChannel ifdDestroyPaceChannel(obj); + QVERIFY(!ifdDestroyPaceChannel.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannel.getType(), IfdMessageType::IFDDestroyPACEChannel); + QCOMPARE(ifdDestroyPaceChannel.getContextHandle(), QStringLiteral("TestContext")); + QCOMPARE(ifdDestroyPaceChannel.getSlotHandle(), QStringLiteral("SlotHandle")); + } + + + void msgField_data() + { + QTest::addColumn("type"); + + const auto& msgTypes = Enum::getList(); + for (const auto& type : msgTypes) + { + QTest::newRow(getEnumName(type).data()) << type; + } + } + + + void msgField() + { + QFETCH(IfdMessageType, type); + + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message(R"({ + "ContextHandle": "TestContext", + "SlotHandle": "SlotHandle", + "msg": "%1" + })"); + const QJsonObject& obj = QJsonDocument::fromJson(message.replace("%1", QTest::currentDataTag())).object(); + const IfdDestroyPaceChannel ifdDestroyPaceChannel(obj); + + if (type == IfdMessageType::IFDDestroyPACEChannel) + { + QVERIFY(!ifdDestroyPaceChannel.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannel.getType(), IfdMessageType::IFDDestroyPACEChannel); + + QCOMPARE(logSpy.count(), 0); + + return; + } + + QVERIFY(ifdDestroyPaceChannel.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannel.getType(), type); + + if (type == IfdMessageType::UNDEFINED) + { + QCOMPARE(logSpy.count(), 2); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Invalid messageType received: \"UNDEFINED\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannel"))); + + return; + } + + QCOMPARE(logSpy.count(), 1); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannel"))); + } + + +}; + +QTEST_GUILESS_MAIN(test_IfdDestroyPaceChannel) +#include "test_IfdDestroyPaceChannel.moc" diff --git a/test/qt/ifd/messages/test_IfdDestroyPaceChannelResponse.cpp b/test/qt/ifd/messages/test_IfdDestroyPaceChannelResponse.cpp new file mode 100644 index 000000000..2587b8651 --- /dev/null +++ b/test/qt/ifd/messages/test_IfdDestroyPaceChannelResponse.cpp @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "messages/IfdDestroyPaceChannelResponse.h" + +#include "LogHandler.h" +#include "TestFileHelper.h" + +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +Q_DECLARE_METATYPE(IfdVersion::Version) + + +namespace +{ +// https://bugreports.qt.io/browse/QTBUG-89363 +inline QByteArray RESULT_OK() +{ + return QByteArray("http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok"); +} + + +} // namespace + + +class test_IfdDestroyPaceChannelResponse + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + Env::getSingleton()->init(); + } + + + void invalidJson() + { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message("FooBar"); + const auto& obj = QJsonDocument::fromJson(message).object(); + QVERIFY(obj.isEmpty()); + + IfdDestroyPaceChannelResponse msg(obj); + QVERIFY(msg.isIncomplete()); + + QCOMPARE(logSpy.count(), 7); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"msg\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Invalid messageType received: \"\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"ContextHandle\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"ResultMajor\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"ResultMinor\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Missing value \"SlotHandle\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannelResponse"))); + } + + + void values() + { + const IfdDestroyPaceChannelResponse ifdDestroyPaceChannelResponse(QStringLiteral("SlotHandle")); + + QVERIFY(!ifdDestroyPaceChannelResponse.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannelResponse.getType(), IfdMessageType::IFDDestroyPACEChannelResponse); + QCOMPARE(ifdDestroyPaceChannelResponse.getContextHandle(), QString()); + QCOMPARE(ifdDestroyPaceChannelResponse.getSlotHandle(), QStringLiteral("SlotHandle")); + QVERIFY(!ifdDestroyPaceChannelResponse.resultHasError()); + QCOMPARE(ifdDestroyPaceChannelResponse.getResultMinor(), ECardApiResult::Minor::null); + } + + + void toJson_data() + { + QTest::addColumn("version"); + QTest::newRow("Unknown") << IfdVersion::Version::Unknown; + QTest::newRow("v0") << IfdVersion::Version::v0; + QTest::newRow("v2") << IfdVersion::Version::v2; + } + + + void toJson() + { + QFETCH(IfdVersion::Version, version); + + const IfdDestroyPaceChannelResponse ifdDestroyPaceChannelResponse(QStringLiteral("SlotHandle")); + + const QByteArray& byteArray = ifdDestroyPaceChannelResponse.toByteArray(version, QStringLiteral("TestContext")); + QCOMPARE(byteArray, + QByteArray("{\n" + " \"ContextHandle\": \"TestContext\",\n" + " \"ResultMajor\": \"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok\",\n" + " \"ResultMinor\": null,\n" + " \"SlotHandle\": \"SlotHandle\",\n" + " \"msg\": \"IFDDestroyPACEChannelResponse\"\n" + "}\n")); + + const QJsonObject obj = QJsonDocument::fromJson(byteArray).object(); + QCOMPARE(obj.size(), 5); + QCOMPARE(obj.value(QLatin1String("msg")).toString(), QStringLiteral("IFDDestroyPACEChannelResponse")); + QCOMPARE(obj.value(QLatin1String("ContextHandle")).toString(), QStringLiteral("TestContext")); + QCOMPARE(obj.value(QLatin1String("SlotHandle")).toString(), QStringLiteral("SlotHandle")); + QCOMPARE(obj.value(QLatin1String("ResultMajor")).toString(), QStringLiteral("http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok")); + QCOMPARE(obj.value(QLatin1String("ResultMinor")).toString(), QString()); + } + + + void fromJson() + { + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message(R"({ + "ContextHandle": "TestContext", + "ResultMajor": "[OK]", + "ResultMinor": null, + "SlotHandle": "SlotHandle", + "msg": "IFDDestroyPACEChannelResponse" + })"); + message.replace("[OK]", RESULT_OK()); + + const QJsonObject& obj = QJsonDocument::fromJson(message).object(); + const IfdDestroyPaceChannelResponse ifdDestroyPaceChannelResponse(obj); + QVERIFY(!ifdDestroyPaceChannelResponse.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannelResponse.getType(), IfdMessageType::IFDDestroyPACEChannelResponse); + QCOMPARE(ifdDestroyPaceChannelResponse.getContextHandle(), "TestContext"_L1); + QCOMPARE(ifdDestroyPaceChannelResponse.getSlotHandle(), QStringLiteral("SlotHandle")); + QVERIFY(!ifdDestroyPaceChannelResponse.resultHasError()); + QCOMPARE(ifdDestroyPaceChannelResponse.getResultMinor(), ECardApiResult::Minor::null); + } + + + void msgField_data() + { + QTest::addColumn("type"); + + const auto& msgTypes = Enum::getList(); + for (const auto& type : msgTypes) + { + QTest::newRow(getEnumName(type).data()) << type; + } + } + + + void msgField() + { + QFETCH(IfdMessageType, type); + + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); + + QByteArray message(R"({ + "ContextHandle": "TestContext", + "ResultMajor": "[OK]", + "ResultMinor": null, + "SlotHandle": "SlotHandle", + "msg": "%1" + })"); + message.replace("[OK]", RESULT_OK()); + + const QJsonObject& obj = QJsonDocument::fromJson(message.replace("%1", QTest::currentDataTag())).object(); + const IfdDestroyPaceChannelResponse ifdDestroyPaceChannelResponse(obj); + + if (type == IfdMessageType::IFDDestroyPACEChannelResponse) + { + QVERIFY(!ifdDestroyPaceChannelResponse.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannelResponse.getType(), IfdMessageType::IFDDestroyPACEChannelResponse); + + QCOMPARE(logSpy.count(), 0); + + return; + } + + QVERIFY(ifdDestroyPaceChannelResponse.isIncomplete()); + QCOMPARE(ifdDestroyPaceChannelResponse.getType(), type); + + if (type == IfdMessageType::UNDEFINED) + { + QCOMPARE(logSpy.count(), 2); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Invalid messageType received: \"UNDEFINED\""))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannelResponse"))); + + return; + } + + QCOMPARE(logSpy.count(), 1); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("The value of msg should be IFDDestroyPACEChannelResponse"))); + } + + +}; + +QTEST_GUILESS_MAIN(test_IfdDestroyPaceChannelResponse) +#include "test_IfdDestroyPaceChannelResponse.moc" diff --git a/test/qt/ifd/messages/test_IfdDisconnect.cpp b/test/qt/ifd/messages/test_IfdDisconnect.cpp index 1b6894d65..c9075b9ce 100644 --- a/test/qt/ifd/messages/test_IfdDisconnect.cpp +++ b/test/qt/ifd/messages/test_IfdDisconnect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdDisconnect.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,11 +36,11 @@ class test_IfdDisconnect QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 5); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("The value of msg should be IFDDisconnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("The value of msg should be IFDDisconnect"_L1)); } @@ -142,14 +142,14 @@ class test_IfdDisconnect if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDDisconnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDDisconnect"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDDisconnect")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDDisconnect"_L1)); } @@ -171,7 +171,7 @@ class test_IfdDisconnect QCOMPARE(ifdDisconnect.getSlotHandle(), QString()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdDisconnectResponse.cpp b/test/qt/ifd/messages/test_IfdDisconnectResponse.cpp index ae5d4c65e..1a1d9cd05 100644 --- a/test/qt/ifd/messages/test_IfdDisconnectResponse.cpp +++ b/test/qt/ifd/messages/test_IfdDisconnectResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdDisconnectResponse.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,13 +37,13 @@ class test_IfdDisconnectResponse QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 7); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDDisconnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDDisconnectResponse"_L1)); } @@ -156,14 +157,14 @@ class test_IfdDisconnectResponse if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDDisconnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDDisconnectResponse"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDDisconnectResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDDisconnectResponse"_L1)); } @@ -189,7 +190,7 @@ class test_IfdDisconnectResponse QCOMPARE(ifdDisconnectResponse.getResultMinor(), ECardApiResult::Minor::null); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdError.cpp b/test/qt/ifd/messages/test_IfdError.cpp index a3634cd29..a8af4ad3c 100644 --- a/test/qt/ifd/messages/test_IfdError.cpp +++ b/test/qt/ifd/messages/test_IfdError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdError.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,13 +37,13 @@ class test_IfdError QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 7); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDError")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDError"_L1)); } @@ -156,14 +157,14 @@ class test_IfdError if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDError")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDError"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDError")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDError"_L1)); } @@ -189,7 +190,7 @@ class test_IfdError QCOMPARE(ifdError.getResultMinor(), ECardApiResult::Minor::null); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdEstablishContext.cpp b/test/qt/ifd/messages/test_IfdEstablishContext.cpp index 68a088d6a..9d195fe12 100644 --- a/test/qt/ifd/messages/test_IfdEstablishContext.cpp +++ b/test/qt/ifd/messages/test_IfdEstablishContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdEstablishContext.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,12 +36,12 @@ class test_IfdEstablishContext QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"Protocol\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"UDName\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDEstablishContext")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"Protocol\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"UDName\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDEstablishContext"_L1)); } @@ -143,16 +143,16 @@ class test_IfdEstablishContext if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 3); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("The value of msg should be IFDEstablishContext")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("The value of msg should be IFDEstablishContext"_L1)); return; } QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDEstablishContext")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDEstablishContext"_L1)); } @@ -194,8 +194,8 @@ class test_IfdEstablishContext QCOMPARE(ifdEstablishContext.getUdName(), QString()); QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"Protocol\" should be of type \"string\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"UDName\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"Protocol\" should be of type \"string\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"UDName\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdEstablishContextResponse.cpp b/test/qt/ifd/messages/test_IfdEstablishContextResponse.cpp index 962135146..6c7699e4a 100644 --- a/test/qt/ifd/messages/test_IfdEstablishContextResponse.cpp +++ b/test/qt/ifd/messages/test_IfdEstablishContextResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdEstablishContextResponse.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,13 +37,13 @@ class test_IfdEstablishContextResponse QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 7); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"IFDName\"")); - QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"IFDName\""_L1)); + QVERIFY(logSpy.at(6).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse"_L1)); } @@ -156,14 +157,14 @@ class test_IfdEstablishContextResponse if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDEstablishContextResponse"_L1)); } @@ -189,7 +190,7 @@ class test_IfdEstablishContextResponse QCOMPARE(ifdEstablishContextResponse.getResultMinor(), ECardApiResult::Minor::null); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"IFDName\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"IFDName\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdEstablishPaceChannel.cpp b/test/qt/ifd/messages/test_IfdEstablishPaceChannel.cpp index a014d5cf7..0f4dca994 100644 --- a/test/qt/ifd/messages/test_IfdEstablishPaceChannel.cpp +++ b/test/qt/ifd/messages/test_IfdEstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdEstablishPaceChannel.h" @@ -9,7 +9,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -60,7 +60,7 @@ class test_IfdEstablishPaceChannel void values() { EstablishPaceChannel establishPaceChannel; - const IfdEstablishPaceChannel ifdEstablishPaceChannel("SlotHandle", establishPaceChannel, 6); + const IfdEstablishPaceChannel ifdEstablishPaceChannel("SlotHandle"_L1, establishPaceChannel, 6); QVERIFY(!ifdEstablishPaceChannel.isIncomplete()); QCOMPARE(ifdEstablishPaceChannel.getType(), IfdMessageType::IFDEstablishPACEChannel); @@ -87,7 +87,7 @@ class test_IfdEstablishPaceChannel QFETCH(IfdVersion::Version, version); QFETCH(QByteArray, inputApdu); - const IfdEstablishPaceChannel ifdEstablishPaceChannel(QStringLiteral("SlotHandle"), EstablishPaceChannel(PacePasswordId::PACE_PIN), 6); + const IfdEstablishPaceChannel ifdEstablishPaceChannel("SlotHandle"_L1, EstablishPaceChannel(PacePasswordId::PACE_PIN), 6); const QByteArray& byteArray = ifdEstablishPaceChannel.toByteArray(version, QStringLiteral("TestContext")); QCOMPARE(byteArray, diff --git a/test/qt/ifd/messages/test_IfdEstablishPaceChannelResponse.cpp b/test/qt/ifd/messages/test_IfdEstablishPaceChannelResponse.cpp index 476810bcc..86ec7e0f4 100644 --- a/test/qt/ifd/messages/test_IfdEstablishPaceChannelResponse.cpp +++ b/test/qt/ifd/messages/test_IfdEstablishPaceChannelResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdEstablishPaceChannelResponse.h" @@ -9,7 +9,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -181,8 +181,8 @@ class test_IfdEstablishPaceChannelResponse const IfdEstablishPaceChannelResponse ifdEstablishPaceChannelResponse(obj); QCOMPARE(ifdEstablishPaceChannelResponse.isIncomplete(), incomplete); QCOMPARE(ifdEstablishPaceChannelResponse.getType(), IfdMessageType::IFDEstablishPACEChannelResponse); - QCOMPARE(ifdEstablishPaceChannelResponse.getContextHandle(), QString("TestContext")); - QCOMPARE(ifdEstablishPaceChannelResponse.getSlotHandle(), QStringLiteral("SlotHandle")); + QCOMPARE(ifdEstablishPaceChannelResponse.getContextHandle(), "TestContext"_L1); + QCOMPARE(ifdEstablishPaceChannelResponse.getSlotHandle(), "SlotHandle"_L1); QCOMPARE(ifdEstablishPaceChannelResponse.getOutputData().getPaceReturnCode(), incomplete && !withResultCode ? CardReturnCode::COMMAND_FAILED : CardReturnCode::OK); QVERIFY(!ifdEstablishPaceChannelResponse.resultHasError()); QCOMPARE(ifdEstablishPaceChannelResponse.getResultMinor(), ECardApiResult::Minor::null); diff --git a/test/qt/ifd/messages/test_IfdGetStatus.cpp b/test/qt/ifd/messages/test_IfdGetStatus.cpp index a2c278fa0..4e0df3e8d 100644 --- a/test/qt/ifd/messages/test_IfdGetStatus.cpp +++ b/test/qt/ifd/messages/test_IfdGetStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdGetStatus.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,11 +37,11 @@ class test_IfdGetStatus QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 5); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotName\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("The value of msg should be IFDGetStatus")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotName\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("The value of msg should be IFDGetStatus"_L1)); } @@ -142,14 +143,14 @@ class test_IfdGetStatus if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDGetStatus")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDGetStatus"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDGetStatus")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDGetStatus"_L1)); } @@ -171,7 +172,7 @@ class test_IfdGetStatus QCOMPARE(ifdGetStatus.getSlotName(), QString()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotName\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotName\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdMessage.cpp b/test/qt/ifd/messages/test_IfdMessage.cpp index 1ef5b7f9a..dd23f8638 100644 --- a/test/qt/ifd/messages/test_IfdMessage.cpp +++ b/test/qt/ifd/messages/test_IfdMessage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdMessage.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -44,13 +45,13 @@ class test_IfdMessage if (type != IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Missing value \"ContextHandle\""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); return; } QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Invalid messageType received: \""))); - QVERIFY(logSpy.at(1).at(0).toString().contains(QString("Missing value \"ContextHandle\""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); } @@ -78,7 +79,7 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Invalid messageType received: \""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \""_L1)); } @@ -104,7 +105,7 @@ class test_IfdMessage return; } - QCOMPARE(msg.getContextHandle(), QString("TestContext")); + QCOMPARE(msg.getContextHandle(), "TestContext"_L1); if (type != IfdMessageType::UNDEFINED) { @@ -115,7 +116,7 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Invalid messageType received: \""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \""_L1)); } private Q_SLOTS: @@ -137,11 +138,11 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 5); - QVERIFY(logSpy.at(0).at(0).toString().contains("Json parsing failed. 1 : \"illegal value\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Expected object at top level")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ContextHandle\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Json parsing failed. 1 : \"illegal value\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Expected object at top level"_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); } @@ -157,10 +158,10 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 4); - QVERIFY(logSpy.at(0).at(0).toString().contains("Expected object at top level")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ContextHandle\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Expected object at top level"_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); } @@ -176,10 +177,10 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 4); - QVERIFY(logSpy.at(0).at(0).toString().contains("Expected object at top level")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ContextHandle\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Expected object at top level"_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); } @@ -197,8 +198,8 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Missing value \"msg\""))); - QVERIFY(logSpy.at(1).at(0).toString().contains(QString("Invalid messageType received: \"\""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); } @@ -241,7 +242,7 @@ class test_IfdMessage QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains(QString("Invalid messageType received: \""))); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdMessageResponse.cpp b/test/qt/ifd/messages/test_IfdMessageResponse.cpp index 374d3b4d4..60dfff9c5 100644 --- a/test/qt/ifd/messages/test_IfdMessageResponse.cpp +++ b/test/qt/ifd/messages/test_IfdMessageResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdMessageResponse.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,11 +37,11 @@ class test_IfdMessageResponse QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 5); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); } @@ -132,7 +133,7 @@ class test_IfdMessageResponse QCOMPARE(logSpy.count(), spyCount); if (spyCount > 0) { - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"ResultMinor\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"ResultMinor\" should be of type \"string\""_L1)); } } diff --git a/test/qt/ifd/messages/test_IfdModifyPin.cpp b/test/qt/ifd/messages/test_IfdModifyPin.cpp index 41f1efcba..5d0700e7b 100644 --- a/test/qt/ifd/messages/test_IfdModifyPin.cpp +++ b/test/qt/ifd/messages/test_IfdModifyPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdModifyPin.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,12 +36,12 @@ class test_IfdModifyPin QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"InputData\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDModifyPIN")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"InputData\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("The value of msg should be IFDModifyPIN"_L1)); } @@ -151,14 +151,14 @@ class test_IfdModifyPin if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDModifyPIN")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDModifyPIN"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDModifyPIN")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDModifyPIN"_L1)); } @@ -182,8 +182,8 @@ class test_IfdModifyPin QCOMPARE(ifdModifyPin.getInputData(), QByteArray()); QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"InputData\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"InputData\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdModifyPinResponse.cpp b/test/qt/ifd/messages/test_IfdModifyPinResponse.cpp index 30a6428fd..7d9e99e8d 100644 --- a/test/qt/ifd/messages/test_IfdModifyPinResponse.cpp +++ b/test/qt/ifd/messages/test_IfdModifyPinResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdModifyPinResponse.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,14 +36,14 @@ class test_IfdModifyPinResponse QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 8); - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); - QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\"")); - QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\"")); - QVERIFY(logSpy.at(6).at(0).toString().contains("Missing value \"OutputData\"")); - QVERIFY(logSpy.at(7).at(0).toString().contains("The value of msg should be IFDModifyPINResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\""_L1)); + QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\""_L1)); + QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"ResultMajor\""_L1)); + QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"ResultMinor\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"SlotHandle\""_L1)); + QVERIFY(logSpy.at(6).at(0).toString().contains("Missing value \"OutputData\""_L1)); + QVERIFY(logSpy.at(7).at(0).toString().contains("The value of msg should be IFDModifyPINResponse"_L1)); } @@ -108,7 +108,7 @@ class test_IfdModifyPinResponse const IfdModifyPinResponse ifdModifyPinResponse(obj); QVERIFY(!ifdModifyPinResponse.isIncomplete()); QCOMPARE(ifdModifyPinResponse.getType(), IfdMessageType::IFDModifyPINResponse); - QCOMPARE(ifdModifyPinResponse.getContextHandle(), QString("TestContext")); + QCOMPARE(ifdModifyPinResponse.getContextHandle(), "TestContext"_L1); QCOMPARE(ifdModifyPinResponse.getSlotHandle(), QStringLiteral("SlotHandle")); QCOMPARE(ifdModifyPinResponse.getOutputData(), QByteArray::fromHex("ABCD1234")); QVERIFY(!ifdModifyPinResponse.resultHasError()); @@ -163,14 +163,14 @@ class test_IfdModifyPinResponse if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDModifyPINResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDModifyPINResponse"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDModifyPINResponse")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDModifyPINResponse"_L1)); } @@ -198,8 +198,8 @@ class test_IfdModifyPinResponse QCOMPARE(ifdModifyPinResponse.getResultMinor(), ECardApiResult::Minor::null); QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"OutputData\" should be of type \"string\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotHandle\" should be of type \"string\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"OutputData\" should be of type \"string\""_L1)); } diff --git a/test/qt/ifd/messages/test_IfdStatus.cpp b/test/qt/ifd/messages/test_IfdStatus.cpp index 71e63e211..cc774575b 100644 --- a/test/qt/ifd/messages/test_IfdStatus.cpp +++ b/test/qt/ifd/messages/test_IfdStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdStatus.h" @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -62,7 +63,7 @@ class test_IfdStatus void values() { - ReaderInfo info(QStringLiteral("SlotName"), ReaderManagerPlugInType::PCSC, CardInfo(CardType::NONE)); + ReaderInfo info(QStringLiteral("SlotName"), ReaderManagerPluginType::PCSC, CardInfo(CardType::NONE)); info.setBasicReader(false); const IfdStatus ifdStatus(info); @@ -117,7 +118,7 @@ class test_IfdStatus QFETCH(bool, pinpad); QFETCH(QByteArray, json); - ReaderInfo info(QStringLiteral("SlotName"), ReaderManagerPlugInType::PCSC, CardInfo(CardType::NONE)); + ReaderInfo info(QStringLiteral("SlotName"), ReaderManagerPluginType::PCSC, CardInfo(CardType::NONE)); info.setBasicReader(!pinpad); const IfdStatus ifdStatus(info); @@ -212,7 +213,7 @@ class test_IfdStatus QCOMPARE(logSpy.count(), incomplete ? 1 : 0); if (incomplete) { - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"PINPad\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"PINPad\""_L1)); } } @@ -271,14 +272,14 @@ class test_IfdStatus if (type == IfdMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); - QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); - QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDStatus")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\""_L1)); + QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDStatus"_L1)); return; } QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDStatus")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDStatus"_L1)); } @@ -371,50 +372,50 @@ class test_IfdStatus void constructionWithReaderInfo_data() { - QTest::addColumn("type"); + QTest::addColumn("type"); QTest::addColumn("isBasicReader"); QTest::addColumn("maxApduLength"); QTest::addColumn("cardAvailable"); QTest::addColumn("pinPadMode"); - QTest::newRow("NFC - Basic reader without card") << ReaderManagerPlugInType::NFC << true << 500 << false << false; - QTest::newRow("NFC - Basic reader with card") << ReaderManagerPlugInType::NFC << true << 500 << true << false; - QTest::newRow("NFC - Basic reader with card without extended length") << ReaderManagerPlugInType::NFC << true << 200 << true << false; - QTest::newRow("NFC - Basic reader with card and pin pad mode") << ReaderManagerPlugInType::NFC << true << 500 << true << true; - QTest::newRow("NFC - Comfort reader with card and enabled pin pad mode") << ReaderManagerPlugInType::NFC << false << 500 << true << true; - QTest::newRow("NFC - Comfort reader with card and disabled pin pad mode") << ReaderManagerPlugInType::NFC << false << 500 << true << false; - - QTest::newRow("PCSC - Basic reader with pin pad mode") << ReaderManagerPlugInType::PCSC << true << 500 << false << true; - QTest::newRow("PCSC - Basic reader without pin pad mode") << ReaderManagerPlugInType::PCSC << true << 500 << false << false; - QTest::newRow("PCSC - Comfort reader with pin pad mode") << ReaderManagerPlugInType::PCSC << false << 500 << false << true; - QTest::newRow("PCSC - Comfort reader without pin pad mode") << ReaderManagerPlugInType::PCSC << false << 500 << false << false; - - QTest::newRow("REMOTE_IFD - Basic reader with pin pad mode") << ReaderManagerPlugInType::REMOTE_IFD << true << 500 << false << true; - QTest::newRow("REMOTE_IFD - Basic reader without pin pad mode") << ReaderManagerPlugInType::REMOTE_IFD << true << 500 << false << false; - QTest::newRow("REMOTE_IFD - Comfort reader with pin pad mode") << ReaderManagerPlugInType::REMOTE_IFD << false << 500 << false << true; - QTest::newRow("REMOTE_IFD - Comfort reader without pin pad mode") << ReaderManagerPlugInType::REMOTE_IFD << false << 500 << false << false; - - QTest::newRow("LOCAL_IFD - Basic reader with pin pad mode") << ReaderManagerPlugInType::LOCAL_IFD << true << 500 << false << true; - QTest::newRow("LOCAL_IFD - Basic reader without pin pad mode") << ReaderManagerPlugInType::LOCAL_IFD << true << 500 << false << false; - QTest::newRow("LOCAL_IFD - Comfort reader with pin pad mode") << ReaderManagerPlugInType::LOCAL_IFD << false << 500 << false << true; - QTest::newRow("LOCAL_IFD - Comfort reader without pin pad mode") << ReaderManagerPlugInType::LOCAL_IFD << false << 500 << false << false; - - QTest::newRow("SMART - Basic reader with pin pad mode") << ReaderManagerPlugInType::SMART << true << 500 << false << true; - QTest::newRow("SMART - Basic reader without pin pad mode") << ReaderManagerPlugInType::SMART << true << 500 << false << false; - QTest::newRow("SMART - Comfort reader with pin pad mode") << ReaderManagerPlugInType::SMART << false << 500 << false << true; - QTest::newRow("SMART - Comfort reader without pin pad mode") << ReaderManagerPlugInType::SMART << false << 500 << false << false; - - QTest::newRow("SIMULATOR - Basic reader with pin pad mode") << ReaderManagerPlugInType::SIMULATOR << true << 500 << false << true; - QTest::newRow("SIMULATOR - Basic reader without pin pad mode") << ReaderManagerPlugInType::SIMULATOR << true << 500 << false << false; - QTest::newRow("SIMULATOR - Comfort reader with pin pad mode") << ReaderManagerPlugInType::SIMULATOR << false << 500 << false << true; - QTest::newRow("SIMULATOR - Comfort reader without pin pad mode") << ReaderManagerPlugInType::SIMULATOR << false << 500 << false << false; + QTest::newRow("NFC - Basic reader without card") << ReaderManagerPluginType::NFC << true << 500 << false << false; + QTest::newRow("NFC - Basic reader with card") << ReaderManagerPluginType::NFC << true << 500 << true << false; + QTest::newRow("NFC - Basic reader with card without extended length") << ReaderManagerPluginType::NFC << true << 200 << true << false; + QTest::newRow("NFC - Basic reader with card and pin pad mode") << ReaderManagerPluginType::NFC << true << 500 << true << true; + QTest::newRow("NFC - Comfort reader with card and enabled pin pad mode") << ReaderManagerPluginType::NFC << false << 500 << true << true; + QTest::newRow("NFC - Comfort reader with card and disabled pin pad mode") << ReaderManagerPluginType::NFC << false << 500 << true << false; + + QTest::newRow("PCSC - Basic reader with pin pad mode") << ReaderManagerPluginType::PCSC << true << 500 << false << true; + QTest::newRow("PCSC - Basic reader without pin pad mode") << ReaderManagerPluginType::PCSC << true << 500 << false << false; + QTest::newRow("PCSC - Comfort reader with pin pad mode") << ReaderManagerPluginType::PCSC << false << 500 << false << true; + QTest::newRow("PCSC - Comfort reader without pin pad mode") << ReaderManagerPluginType::PCSC << false << 500 << false << false; + + QTest::newRow("REMOTE_IFD - Basic reader with pin pad mode") << ReaderManagerPluginType::REMOTE_IFD << true << 500 << false << true; + QTest::newRow("REMOTE_IFD - Basic reader without pin pad mode") << ReaderManagerPluginType::REMOTE_IFD << true << 500 << false << false; + QTest::newRow("REMOTE_IFD - Comfort reader with pin pad mode") << ReaderManagerPluginType::REMOTE_IFD << false << 500 << false << true; + QTest::newRow("REMOTE_IFD - Comfort reader without pin pad mode") << ReaderManagerPluginType::REMOTE_IFD << false << 500 << false << false; + + QTest::newRow("LOCAL_IFD - Basic reader with pin pad mode") << ReaderManagerPluginType::LOCAL_IFD << true << 500 << false << true; + QTest::newRow("LOCAL_IFD - Basic reader without pin pad mode") << ReaderManagerPluginType::LOCAL_IFD << true << 500 << false << false; + QTest::newRow("LOCAL_IFD - Comfort reader with pin pad mode") << ReaderManagerPluginType::LOCAL_IFD << false << 500 << false << true; + QTest::newRow("LOCAL_IFD - Comfort reader without pin pad mode") << ReaderManagerPluginType::LOCAL_IFD << false << 500 << false << false; + + QTest::newRow("SMART - Basic reader with pin pad mode") << ReaderManagerPluginType::SMART << true << 500 << false << true; + QTest::newRow("SMART - Basic reader without pin pad mode") << ReaderManagerPluginType::SMART << true << 500 << false << false; + QTest::newRow("SMART - Comfort reader with pin pad mode") << ReaderManagerPluginType::SMART << false << 500 << false << true; + QTest::newRow("SMART - Comfort reader without pin pad mode") << ReaderManagerPluginType::SMART << false << 500 << false << false; + + QTest::newRow("SIMULATOR - Basic reader with pin pad mode") << ReaderManagerPluginType::SIMULATOR << true << 500 << false << true; + QTest::newRow("SIMULATOR - Basic reader without pin pad mode") << ReaderManagerPluginType::SIMULATOR << true << 500 << false << false; + QTest::newRow("SIMULATOR - Comfort reader with pin pad mode") << ReaderManagerPluginType::SIMULATOR << false << 500 << false << true; + QTest::newRow("SIMULATOR - Comfort reader without pin pad mode") << ReaderManagerPluginType::SIMULATOR << false << 500 << false << false; } void constructionWithReaderInfo() { - const QString slotName("SlotName"); - QFETCH(ReaderManagerPlugInType, type); + const QString slotName("SlotName"_L1); + QFETCH(ReaderManagerPluginType, type); QFETCH(bool, isBasicReader); QFETCH(int, maxApduLength); QFETCH(bool, cardAvailable); @@ -433,7 +434,7 @@ class test_IfdStatus QCOMPARE(ifdStatus.getType(), IfdMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QString()); QCOMPARE(ifdStatus.getSlotName(), slotName); - const bool isNfcOrSmart = type == ReaderManagerPlugInType::NFC || type == ReaderManagerPlugInType::SMART; + const bool isNfcOrSmart = type == ReaderManagerPluginType::NFC || type == ReaderManagerPluginType::SMART; QCOMPARE(ifdStatus.hasPinPad(), !isBasicReader || (isNfcOrSmart && pinPadMode)); QCOMPARE(ifdStatus.getMaxApduLength(), maxApduLength); QCOMPARE(ifdStatus.getConnectedReader(), true); diff --git a/test/qt/ifd/messages/test_IfdTransmit.cpp b/test/qt/ifd/messages/test_IfdTransmit.cpp index 02d67d8e2..2d3e22d46 100644 --- a/test/qt/ifd/messages/test_IfdTransmit.cpp +++ b/test/qt/ifd/messages/test_IfdTransmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdTransmit.h" @@ -9,7 +9,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -173,7 +173,7 @@ class test_IfdTransmit QCOMPARE(logSpy.count(), incomplete ? 1 : 0); if (incomplete) { - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"InputAPDU\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"InputAPDU\""_L1)); } } @@ -241,25 +241,25 @@ class test_IfdTransmit void displayText_data() { QTest::addColumn("version"); - QTest::addColumn("displayText"); + QTest::addColumn("displayText"); QTest::addColumn("included"); - QTest::newRow("vu - Null") << IfdVersion::Version::Unknown << QString() << false; - QTest::newRow("vu - Empty") << IfdVersion::Version::Unknown << QString("") << false; - QTest::newRow("vu - Text") << IfdVersion::Version::Unknown << QString("Text") << false; - QTest::newRow("v0 - Null") << IfdVersion::Version::v0 << QString() << false; - QTest::newRow("v0 - Empty") << IfdVersion::Version::v0 << QString("") << false; - QTest::newRow("v0 - Text") << IfdVersion::Version::v0 << QString("Text") << false; - QTest::newRow("v2 - Null") << IfdVersion::Version::v2 << QString() << false; - QTest::newRow("v2 - Empty") << IfdVersion::Version::v2 << QString("") << true; - QTest::newRow("v2 - Text") << IfdVersion::Version::v2 << QString("Text") << true; + QTest::newRow("vu - Null") << IfdVersion::Version::Unknown << QLatin1String() << false; + QTest::newRow("vu - Empty") << IfdVersion::Version::Unknown << ""_L1 << false; + QTest::newRow("vu - Text") << IfdVersion::Version::Unknown << "Text"_L1 << false; + QTest::newRow("v0 - Null") << IfdVersion::Version::v0 << QLatin1String() << false; + QTest::newRow("v0 - Empty") << IfdVersion::Version::v0 << ""_L1 << false; + QTest::newRow("v0 - Text") << IfdVersion::Version::v0 << "Text"_L1 << false; + QTest::newRow("v2 - Null") << IfdVersion::Version::v2 << QLatin1String() << false; + QTest::newRow("v2 - Empty") << IfdVersion::Version::v2 << ""_L1 << true; + QTest::newRow("v2 - Text") << IfdVersion::Version::v2 << "Text"_L1 << true; } void displayText() { QFETCH(IfdVersion::Version, version); - QFETCH(QString, displayText); + QFETCH(QLatin1String, displayText); QFETCH(bool, included); const IfdTransmit transmit(QStringLiteral("SlotHandle"), QByteArray("00A402022F00"), displayText); @@ -330,7 +330,7 @@ class test_IfdTransmit QVERIFY(ifdTransmit.isIncomplete()); QCOMPARE(ifdTransmit.getType(), IfdMessageType::IFDTransmit); QCOMPARE(ifdTransmit.getContextHandle(), QStringLiteral("TestContext")); - QCOMPARE(ifdTransmit.getSlotHandle(), QString("SlotHandle")); + QCOMPARE(ifdTransmit.getSlotHandle(), "SlotHandle"_L1); QCOMPARE(ifdTransmit.getInputApdu(), QByteArray()); QCOMPARE(logSpy.count(), 1); @@ -364,7 +364,7 @@ class test_IfdTransmit QVERIFY(ifdTransmit.isIncomplete()); QCOMPARE(ifdTransmit.getType(), IfdMessageType::IFDTransmit); QCOMPARE(ifdTransmit.getContextHandle(), QStringLiteral("TestContext")); - QCOMPARE(ifdTransmit.getSlotHandle(), QString("SlotHandle")); + QCOMPARE(ifdTransmit.getSlotHandle(), "SlotHandle"_L1); QCOMPARE(ifdTransmit.getInputApdu(), QByteArray()); QCOMPARE(logSpy.count(), 1); diff --git a/test/qt/ifd/messages/test_IfdTransmitResponse.cpp b/test/qt/ifd/messages/test_IfdTransmitResponse.cpp index f9f2b3a84..c12deca16 100644 --- a/test/qt/ifd/messages/test_IfdTransmitResponse.cpp +++ b/test/qt/ifd/messages/test_IfdTransmitResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdTransmitResponse.h" @@ -9,7 +9,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -173,7 +173,7 @@ class test_IfdTransmitResponse const IfdTransmitResponse ifdTransmitResponse(obj); QCOMPARE(ifdTransmitResponse.isIncomplete(), incomplete); QCOMPARE(ifdTransmitResponse.getType(), IfdMessageType::IFDTransmitResponse); - QCOMPARE(ifdTransmitResponse.getContextHandle(), QString("TestContext")); + QCOMPARE(ifdTransmitResponse.getContextHandle(), "TestContext"_L1); QCOMPARE(ifdTransmitResponse.getSlotHandle(), QStringLiteral("SlotHandle")); QCOMPARE(ifdTransmitResponse.getResponseApdu(), incomplete ? QByteArray() : QByteArray::fromHex("9000")); QVERIFY(!ifdTransmitResponse.resultHasError()); @@ -182,7 +182,7 @@ class test_IfdTransmitResponse QCOMPARE(logSpy.count(), incomplete ? 1 : 0); if (incomplete) { - QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"ResponseAPDU\"")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"ResponseAPDU\""_L1)); } } @@ -310,7 +310,7 @@ class test_IfdTransmitResponse QVERIFY(ifdTransmitResponse.isIncomplete()); QCOMPARE(ifdTransmitResponse.getType(), IfdMessageType::IFDTransmitResponse); QCOMPARE(ifdTransmitResponse.getContextHandle(), QStringLiteral("TestContext")); - QCOMPARE(ifdTransmitResponse.getSlotHandle(), QString("SlotHandle")); + QCOMPARE(ifdTransmitResponse.getSlotHandle(), "SlotHandle"_L1); QCOMPARE(ifdTransmitResponse.getResponseApdu(), QByteArray()); QVERIFY(!ifdTransmitResponse.resultHasError()); QCOMPARE(ifdTransmitResponse.getResultMinor(), ECardApiResult::Minor::null); @@ -347,7 +347,7 @@ class test_IfdTransmitResponse QVERIFY(!ifdTransmitResponse.isIncomplete()); QCOMPARE(ifdTransmitResponse.getType(), IfdMessageType::IFDTransmitResponse); QCOMPARE(ifdTransmitResponse.getContextHandle(), QStringLiteral("TestContext")); - QCOMPARE(ifdTransmitResponse.getSlotHandle(), QString("SlotHandle")); + QCOMPARE(ifdTransmitResponse.getSlotHandle(), "SlotHandle"_L1); QCOMPARE(ifdTransmitResponse.getResponseApdu(), QByteArray::fromHex("9000")); QVERIFY(!ifdTransmitResponse.resultHasError()); QCOMPARE(ifdTransmitResponse.getResultMinor(), ECardApiResult::Minor::null); diff --git a/test/qt/ifd/messages/test_IfdVersion.cpp b/test/qt/ifd/messages/test_IfdVersion.cpp index 3c2ff208d..cd0c4bc86 100644 --- a/test/qt/ifd/messages/test_IfdVersion.cpp +++ b/test/qt/ifd/messages/test_IfdVersion.cpp @@ -1,11 +1,13 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdVersion.h" #include + +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -17,10 +19,10 @@ class test_IfdVersion private Q_SLOTS: void stringParsing() { - QCOMPARE(IfdVersion("IFDInterface_WebSocket_Unknown"), IfdVersion::Version::Unknown); - QCOMPARE(IfdVersion("IFDInterface_WebSocket_v0"), IfdVersion::Version::v0); - QCOMPARE(IfdVersion("IFDInterface_WebSocket_v2"), IfdVersion::Version::v2); - QCOMPARE(IfdVersion("IFDInterface_WebSocket_v9001"), IfdVersion::Version::Unknown); + QCOMPARE(IfdVersion("IFDInterface_WebSocket_Unknown"_L1), IfdVersion::Version::Unknown); + QCOMPARE(IfdVersion("IFDInterface_WebSocket_v0"_L1), IfdVersion::Version::v0); + QCOMPARE(IfdVersion("IFDInterface_WebSocket_v2"_L1), IfdVersion::Version::v2); + QCOMPARE(IfdVersion("IFDInterface_WebSocket_v9001"_L1), IfdVersion::Version::Unknown); } @@ -42,7 +44,7 @@ class test_IfdVersion void supportedVersions() { - QVector versions({IfdVersion::Version::v2}); + QList versions({IfdVersion::Version::v2}); if (IfdVersion(IfdVersion::Version::v0).isSupported()) { versions.prepend(IfdVersion::Version::v0); diff --git a/test/qt/ifd/remote/test_RemoteIfdClient.cpp b/test/qt/ifd/remote/test_RemoteIfdClient.cpp index 849ca415a..9f3950c0a 100644 --- a/test/qt/ifd/remote/test_RemoteIfdClient.cpp +++ b/test/qt/ifd/remote/test_RemoteIfdClient.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "RemoteIfdClient.h" @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -86,14 +87,14 @@ class RemoteConnectorMock Q_OBJECT public Q_SLOTS: - void onConnectRequest(const IfdDescriptor& pRemoteDeviceDescriptor, const QString& pPsk) override; + void onConnectRequest(const IfdDescriptor& pRemoteDeviceDescriptor, const QByteArray& pPsk) override; Q_SIGNALS: void fireConnectionRequestReceived(); }; -void RemoteConnectorMock::onConnectRequest(const IfdDescriptor&, const QString&) +void RemoteConnectorMock::onConnectRequest(const IfdDescriptor&, const QByteArray&) { Q_EMIT fireConnectionRequestReceived(); } @@ -184,9 +185,9 @@ class test_RemoteIfdClient client.startDetection(); QVERIFY(!mDatagramHandlerMock.isNull()); - Q_EMIT mDatagramHandlerMock->fireNewMessage(unparsableJson, QHostAddress("192.168.1.88")); + Q_EMIT mDatagramHandlerMock->fireNewMessage(unparsableJson, QHostAddress("192.168.1.88"_L1)); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(5).at(0).toString().contains("Discarding unparsable message")); + QVERIFY(logSpy.at(5).at(0).toString().contains("Discarding unparsable message"_L1)); } @@ -199,10 +200,10 @@ class test_RemoteIfdClient QVERIFY(!mDatagramHandlerMock.isNull()); const auto& json = IfdEstablishContext(IfdVersion::Version::latest, DeviceInfo::getName()).toByteArray(IfdVersion::Version::latest, QStringLiteral("TestContext")); - Q_EMIT mDatagramHandlerMock->fireNewMessage(json, QHostAddress("192.168.1.88")); + Q_EMIT mDatagramHandlerMock->fireNewMessage(json, QHostAddress("192.168.1.88"_L1)); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be REMOTE_IFD")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Discarding unparsable message")); + QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be REMOTE_IFD"_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Discarding unparsable message"_L1)); } @@ -220,12 +221,12 @@ class test_RemoteIfdClient { QFETCH(QString, hostAddress); - QString ifdId("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"); + QString ifdId("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"_L1); IfdVersion::Version version = IfdVersion::Version::latest; if (IfdVersion::supported().contains(IfdVersion::Version::v2)) { - ifdId = R"({ + ifdId = QLatin1StringView(R"({ -----BEGIN CERTIFICATE----- MIIC4zCCAcsCBEQvMpowDQYJKoZIhvcNAQELBQAwNDEUMBIGA1UEAwwLQXVzd2Vp c0FwcDIxHDAaBgNVBAUTEzY0MTgwMjY3MTE5MTA5MjY2MzQwIhgPMTk3MDAxMDEw @@ -244,10 +245,10 @@ class test_RemoteIfdClient oQu+/VZgDkJaSdDJ4LqVFIvUy3CFGh6ahDVsHGC5kTDm5EQWh3puWR0AkIjUWMPi xU/nr0Jsab99VgX4/nnCW92v/DIRc1c= -----END CERTIFICATE----- - })"; + })"); version = IfdVersion::Version::v2; } - const QByteArray offerJson = Discovery("Sony Xperia Z5 compact", ifdId, 24728, {version}).toByteArray(version); + const QByteArray offerJson = Discovery("Sony Xperia Z5 compact"_L1, ifdId, 24728, {version}).toByteArray(version); RemoteIfdClient client; client.startDetection(); @@ -292,14 +293,14 @@ class test_RemoteIfdClient RemoteIfdClient client; client.startDetection(); QVERIFY(!mDatagramHandlerMock.isNull()); - Q_EMIT mDatagramHandlerMock->fireNewMessage(offerJson, QHostAddress("192.168.1.88")); + Q_EMIT mDatagramHandlerMock->fireNewMessage(offerJson, QHostAddress("192.168.1.88"_L1)); QVERIFY(!mRemoteConnectorMock.isNull()); QSignalSpy spyConnectionRequest(mRemoteConnectorMock.data(), &RemoteConnectorMock::fireConnectionRequestReceived); - const Discovery discovery("", QStringLiteral("0123456789ABCDEF"), 12345, {IfdVersion::Version::latest, IfdVersion::Version::v2}); - const IfdDescriptor descr(discovery, QHostAddress("192.168.1.88")); + const Discovery discovery(QString(), QStringLiteral("0123456789ABCDEF"), 12345, {IfdVersion::Version::latest, IfdVersion::Version::v2}); + const IfdDescriptor descr(discovery, QHostAddress("192.168.1.88"_L1)); QSharedPointer emptyEntry(new IfdListEntry(descr)); - client.establishConnection(emptyEntry, QString("password1")); + client.establishConnection(emptyEntry, "password1"); QTRY_COMPARE(spyConnectionRequest.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/ifd/remote/test_RemoteIfdReaderManagerPlugin.cpp b/test/qt/ifd/remote/test_RemoteIfdReaderManagerPlugin.cpp index 21fde20cc..430ef45ce 100644 --- a/test/qt/ifd/remote/test_RemoteIfdReaderManagerPlugin.cpp +++ b/test/qt/ifd/remote/test_RemoteIfdReaderManagerPlugin.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref RemoteIfdReaderManagerPlugIn + * \brief Unit tests for \ref RemoteIfdReaderManagerPlugin */ -#include "RemoteIfdReaderManagerPlugIn.h" +#include "RemoteIfdReaderManagerPlugin.h" #include "AppSettings.h" #include "Env.h" @@ -31,6 +31,8 @@ #include #include + +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -51,11 +53,11 @@ class MockIfdClient void startDetection() override; void stopDetection() override; bool isDetecting() override; - void establishConnection(const QSharedPointer& pEntry, const QString& pPsk) override; - QVector getConnectedDeviceInfos() override; + void establishConnection(const QSharedPointer& pEntry, const QByteArray& pPsk) override; + QList getConnectedDeviceInfos() override; void requestRemoteDevices() override; - QVector> mRemoteDevices; + QList> mRemoteDevices; }; @@ -75,16 +77,16 @@ bool MockIfdClient::isDetecting() } -void MockIfdClient::establishConnection(const QSharedPointer& pEntry, const QString& pPsk) +void MockIfdClient::establishConnection(const QSharedPointer& pEntry, const QByteArray& pPsk) { Q_UNUSED(pEntry) Q_UNUSED(pPsk) } -QVector MockIfdClient::getConnectedDeviceInfos() +QList MockIfdClient::getConnectedDeviceInfos() { - return QVector(); + return QList(); } @@ -96,8 +98,8 @@ void MockIfdClient::requestRemoteDevices() void MockIfdClient::populateRemoteDevices() { - const Discovery discovery("TestIfdName", "3ff02e8dc335f7ebb39299fbc12b66bf378445e59a68880e81464c50874e09cd", 1337, {IfdVersion::Version::latest}); - const IfdDescriptor ifdDescriptor(discovery, QHostAddress("127.0.0.1"), true); + const Discovery discovery("TestIfdName"_L1, "3ff02e8dc335f7ebb39299fbc12b66bf378445e59a68880e81464c50874e09cd"_L1, 1337, {IfdVersion::Version::latest}); + const IfdDescriptor ifdDescriptor(discovery, QHostAddress("127.0.0.1"_L1), true); mRemoteDevices = {QSharedPointer::create(ifdDescriptor)}; auto& remoteServiceSettings = Env::getSingleton()->getRemoteServiceSettings(); const QByteArray certData = R"(-----BEGIN CERTIFICATE----- @@ -135,7 +137,7 @@ void MockIfdClient::populateRemoteDevices() } -class test_RemoteIfdReaderManagerPlugIn +class test_RemoteIfdReaderManagerPlugin : public QObject { Q_OBJECT @@ -143,10 +145,10 @@ class test_RemoteIfdReaderManagerPlugIn private: QThread mNetworkThread; QSharedPointer mIfdClient; - QSharedPointer mPlugin; + QSharedPointer mPlugin; QSharedPointer mDispatcher1; QSharedPointer mDispatcher2; - QVector> mClientMessages; + QList> mClientMessages; ReaderInfo getReaderInfo(QSignalSpy& pSpy) { @@ -176,7 +178,7 @@ class test_RemoteIfdReaderManagerPlugIn mDispatcher2->setPairingConnection(true); mDispatcher2->moveToThread(&mNetworkThread); - mPlugin.reset(new RemoteIfdReaderManagerPlugIn()); + mPlugin.reset(new RemoteIfdReaderManagerPlugin()); mPlugin->init(); } @@ -219,11 +221,11 @@ class test_RemoteIfdReaderManagerPlugIn spySend.clear(); QSharedPointer message; - QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugIn::fireReaderAdded); - QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugIn::fireReaderPropertiesUpdated); - QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugIn::fireReaderRemoved); + QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugin::fireReaderAdded); + QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugin::fireReaderPropertiesUpdated); + QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugin::fireReaderRemoved); - ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::NFC); + ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPluginType::NFC); info.setBasicReader(true); info.setMaxApduLength(500); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); @@ -259,11 +261,11 @@ class test_RemoteIfdReaderManagerPlugIn spySend.clear(); QSharedPointer message; - QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugIn::fireReaderAdded); - QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugIn::fireReaderPropertiesUpdated); - QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugIn::fireReaderRemoved); + QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugin::fireReaderAdded); + QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugin::fireReaderPropertiesUpdated); + QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugin::fireReaderRemoved); - ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::NFC); + ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPluginType::NFC); info.setBasicReader(true); info.setMaxApduLength(500); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); @@ -327,10 +329,10 @@ class test_RemoteIfdReaderManagerPlugIn spySend.clear(); QSharedPointer message; - QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugIn::fireReaderAdded); - QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugIn::fireReaderRemoved); + QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugin::fireReaderAdded); + QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugin::fireReaderRemoved); - ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::NFC); + ReaderInfo info(QStringLiteral("NFC Reader"), ReaderManagerPluginType::NFC); info.setBasicReader(true); info.setMaxApduLength(500); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(true); @@ -361,18 +363,18 @@ class test_RemoteIfdReaderManagerPlugIn spySend2.clear(); QSharedPointer message; - QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugIn::fireReaderAdded); - QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugIn::fireReaderPropertiesUpdated); - QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugIn::fireReaderRemoved); + QSignalSpy spyAdded(mPlugin.data(), &ReaderManagerPlugin::fireReaderAdded); + QSignalSpy spyUpdated(mPlugin.data(), &ReaderManagerPlugin::fireReaderPropertiesUpdated); + QSignalSpy spyRemoved(mPlugin.data(), &ReaderManagerPlugin::fireReaderRemoved); - ReaderInfo info1(QStringLiteral("NFC Reader 1"), ReaderManagerPlugInType::NFC); + ReaderInfo info1(QStringLiteral("NFC Reader 1"), ReaderManagerPluginType::NFC); info1.setMaxApduLength(500); info1.setBasicReader(true); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); message.reset(new IfdStatus(info1)); mDispatcher1->onReceived(message); - ReaderInfo info2(QStringLiteral("NFC Reader 2"), ReaderManagerPlugInType::NFC); + ReaderInfo info2(QStringLiteral("NFC Reader 2"), ReaderManagerPluginType::NFC); info2.setMaxApduLength(500); info2.setBasicReader(true); message.reset(new IfdStatus(info2)); @@ -460,7 +462,7 @@ class test_RemoteIfdReaderManagerPlugIn QSharedPointer message; - ReaderInfo info1(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::NFC); + ReaderInfo info1(QStringLiteral("NFC Reader"), ReaderManagerPluginType::NFC); info1.setMaxApduLength(500); message.reset(new IfdStatus(info1)); info1.setBasicReader(true); @@ -511,7 +513,7 @@ class test_RemoteIfdReaderManagerPlugIn QCOMPARE(spyChanged.size(), 0); QCOMPARE(spyUpdated.size(), 0); - ReaderInfo info2(QStringLiteral("NFC Reader"), ReaderManagerPlugInType::NFC); + ReaderInfo info2(QStringLiteral("NFC Reader"), ReaderManagerPluginType::NFC); info2.setMaxApduLength(1); info2.setBasicReader(true); message.reset(new IfdStatus(info2)); @@ -549,11 +551,11 @@ class test_RemoteIfdReaderManagerPlugIn mDispatcher1->setState(MockIfdDispatcher::DispatcherState::ReaderWithCard); Q_EMIT mIfdClient->fireNewDispatcher(mDispatcher1); - QTRY_COMPARE(spySend.count(), 8); // clazy:exclude=qstring-allocations + QTRY_COMPARE(spySend.count(), 6); // clazy:exclude=qstring-allocations spySend.takeFirst(); result = qvariant_cast>(spySend.takeFirst().at(0)); QCOMPARE(result->getType(), IfdMessageType::IFDConnect); - for (int i = 0; i < 5; ++i) // CardInfo detection + for (int i = 0; i < 3; ++i) // CardInfo detection { result = qvariant_cast>(spySend.takeFirst().at(0)); QCOMPARE(result->getType(), IfdMessageType::IFDTransmit); @@ -621,13 +623,13 @@ class test_RemoteIfdReaderManagerPlugIn QTRY_COMPARE(spySend.count(), 1); // clazy:exclude=qstring-allocations spySend.clear(); - const QVector> clientMessages({ - QSharedPointer(new IfdEstablishContext(IfdVersion::Version::latest, "MAC-MINI")), - QSharedPointer(new IfdGetStatus("Remote Reader")), - QSharedPointer(new IfdConnect("NFC Reader")), - QSharedPointer(new IfdDisconnect("NFC Reader")), - QSharedPointer(new IfdTransmit("NFC Reader", "00A402022F00")), - QSharedPointer(new IfdEstablishPaceChannel("SlotHandle", EstablishPaceChannel(), 6)) + const QList> clientMessages({ + QSharedPointer(new IfdEstablishContext(IfdVersion::Version::latest, "MAC-MINI"_L1)), + QSharedPointer(new IfdGetStatus("Remote Reader"_L1)), + QSharedPointer(new IfdConnect("NFC Reader"_L1)), + QSharedPointer(new IfdDisconnect("NFC Reader"_L1)), + QSharedPointer(new IfdTransmit("NFC Reader"_L1, "00A402022F00")), + QSharedPointer(new IfdEstablishPaceChannel("SlotHandle"_L1, EstablishPaceChannel(), 6)) } ); for (const auto& clientMessage : clientMessages) @@ -675,7 +677,7 @@ class test_RemoteIfdReaderManagerPlugIn QTRY_COMPARE(mPlugin->mConnectionAttempts.size(), 1); // clazy:exclude=qstring-allocations QTest::ignoreMessage(QtInfoMsg, "Removing \"3ff02e8dc335f7ebb39299fbc12b66bf378445e59a68880e81464c50874e09cd\" from connection attempt list as it has vanished"); - Q_EMIT mIfdClient->fireDeviceVanished(mIfdClient->mRemoteDevices.first()); + Q_EMIT mIfdClient->fireDeviceVanished(std::as_const(mIfdClient->mRemoteDevices).first()); QTRY_COMPARE(mPlugin->mConnectionAttempts.size(), 0); // clazy:exclude=qstring-allocations } @@ -688,7 +690,7 @@ class test_RemoteIfdReaderManagerPlugIn QTRY_COMPARE(mPlugin->mConnectionAttempts.size(), 1); // clazy:exclude=qstring-allocations QTest::ignoreMessage(QtInfoMsg, "Removing \"3ff02e8dc335f7ebb39299fbc12b66bf378445e59a68880e81464c50874e09cd\" from connection attempt list as the request finished with No_Error | \"No error occurred.\""); - Q_EMIT mIfdClient->fireEstablishConnectionDone(mIfdClient->mRemoteDevices.first(), GlobalStatus::Code::No_Error); + Q_EMIT mIfdClient->fireEstablishConnectionDone(std::as_const(mIfdClient->mRemoteDevices).first(), GlobalStatus::Code::No_Error); QTRY_COMPARE(mPlugin->mConnectionAttempts.size(), 0); // clazy:exclude=qstring-allocations } @@ -723,5 +725,5 @@ class test_RemoteIfdReaderManagerPlugIn }; -QTEST_GUILESS_MAIN(test_RemoteIfdReaderManagerPlugIn) +QTEST_GUILESS_MAIN(test_RemoteIfdReaderManagerPlugin) #include "test_RemoteIfdReaderManagerPlugin.moc" diff --git a/test/qt/ifd/remote/test_RemoteIfdServer.cpp b/test/qt/ifd/remote/test_RemoteIfdServer.cpp index ea6488b87..2e81815d9 100644 --- a/test/qt/ifd/remote/test_RemoteIfdServer.cpp +++ b/test/qt/ifd/remote/test_RemoteIfdServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ifd/remote/test_RemoteReaderAdvertiser.cpp b/test/qt/ifd/remote/test_RemoteReaderAdvertiser.cpp index 09ad044b5..116ad1174 100644 --- a/test/qt/ifd/remote/test_RemoteReaderAdvertiser.cpp +++ b/test/qt/ifd/remote/test_RemoteReaderAdvertiser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -28,6 +28,7 @@ template<> RemoteReaderAdvertiser* createNewObject #include #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(SecureStorage::TlsSuite) +Q_DECLARE_METATYPE(KeyPair) class test_RemoteTlsServer : public QObject @@ -30,6 +33,79 @@ class test_RemoteTlsServer QByteArray psk; const KeyPair pair = KeyPair::generate(); + + void pairDevices(const KeyPair& pClientPair, const QList& pCertChain, QtMsgType pLogMsgType, const QString& pLogError) + { + RemoteTlsServer server; + QCOMPARE(server.getCurrentCertificate(), QSslCertificate()); + connect(&server, &RemoteTlsServer::firePskChanged, this, [this](const QByteArray& pPsk){ + psk = pPsk; + }); + server.setPairing(); + server.startListening(0); + QVERIFY(server.hasPsk()); + + auto config = Env::getSingleton()->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getConfiguration(); + config.setPrivateKey(pClientPair.getKey()); + config.setLocalCertificateChain(pCertChain); + + bool pskSignalFired = false; + QSslSocket client; + client.setSslConfiguration(config); + connect(&client, QOverload&>::of(&QSslSocket::sslErrors), this, [&client](const QList& pErrors){ + QList ignoreList; + for (const auto& error : pErrors) + { + if (error.error() == QSslError::SelfSignedCertificate || + error.error() == QSslError::SelfSignedCertificateInChain || + error.error() == QSslError::HostNameMismatch) + { + ignoreList << error; + } + } + client.ignoreSslErrors(ignoreList); + }); + + connect(&client, &QSslSocket::preSharedKeyAuthenticationRequired, this, [&pskSignalFired, this](QSslPreSharedKeyAuthenticator* pAuthenticator){ + pAuthenticator->setPreSharedKey(psk); + pskSignalFired = true; + }); + + QTcpSocket* remoteSocket = nullptr; + connect(&server, &RemoteTlsServer::fireNewConnection, this, [&remoteSocket](QTcpSocket* pSocket){ + remoteSocket = pSocket; + }); + + QSignalSpy newConnection(&server, &RemoteTlsServer::fireNewConnection); + QSignalSpy clientEncrypted(&client, &QSslSocket::encrypted); + QSignalSpy clientErrorOccured(&client, &QAbstractSocket::errorOccurred); + + client.connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + if (pLogError.isEmpty()) + { + QTRY_COMPARE(newConnection.count(), 1); // clazy:exclude=qstring-allocations + QVERIFY(pskSignalFired); + QTRY_COMPARE(clientEncrypted.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(clientErrorOccured.count(), 0); + + QVERIFY(remoteSocket); + const QByteArray sendData("hello world"); + QSignalSpy spyRead(remoteSocket, &QIODevice::readyRead); + client.write(sendData); + QTRY_COMPARE(spyRead.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(remoteSocket->readAll(), sendData); + QCOMPARE(server.getCurrentCertificate(), pClientPair.getCertificate()); + } + else + { + QTest::ignoreMessage(pLogMsgType, QRegularExpression(pLogError)); + QTRY_COMPARE(clientErrorOccured.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(client.error(), QAbstractSocket::RemoteHostClosedError); + } + + } + private Q_SLOTS: void initTestCase() { @@ -79,66 +155,6 @@ class test_RemoteTlsServer } - void requiredPskForPairing() - { - RemoteTlsServer server; - QCOMPARE(server.getCurrentCertificate(), QSslCertificate()); - connect(&server, &RemoteTlsServer::firePskChanged, this, [this](const QByteArray& pPsk){ - psk = pPsk; - }); - server.setPairing(); - server.startListening(0); - QVERIFY(server.hasPsk()); - - auto config = Env::getSingleton()->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getConfiguration(); - config.setPrivateKey(pair.getKey()); - config.setLocalCertificate(pair.getCertificate()); - - bool pskSignalFired = false; - QSslSocket client; - client.setSslConfiguration(config); - connect(&client, QOverload&>::of(&QSslSocket::sslErrors), this, [&client](const QList& pErrors){ - QList ignoreList; - for (const auto& error : pErrors) - { - if (error.error() == QSslError::SelfSignedCertificate || - error.error() == QSslError::HostNameMismatch) - { - ignoreList << error; - } - } - client.ignoreSslErrors(ignoreList); - }); - - connect(&client, &QSslSocket::preSharedKeyAuthenticationRequired, this, [&pskSignalFired, this](QSslPreSharedKeyAuthenticator* pAuthenticator){ - pAuthenticator->setPreSharedKey(psk); - pskSignalFired = true; - }); - - QTcpSocket* remoteSocket = nullptr; - connect(&server, &RemoteTlsServer::fireNewConnection, this, [&remoteSocket](QTcpSocket* pSocket){ - remoteSocket = pSocket; - }); - - QSignalSpy newConnection(&server, &RemoteTlsServer::fireNewConnection); - QSignalSpy clientEncrypted(&client, &QSslSocket::encrypted); - - client.connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); - - QTRY_COMPARE(newConnection.count(), 1); // clazy:exclude=qstring-allocations - QVERIFY(pskSignalFired); - QTRY_COMPARE(clientEncrypted.count(), 1); // clazy:exclude=qstring-allocations - - QVERIFY(remoteSocket); - const QByteArray sendData("hello world"); - QSignalSpy spyRead(remoteSocket, &QIODevice::readyRead); - client.write(sendData); - QTRY_COMPARE(spyRead.count(), 1); // clazy:exclude=qstring-allocations - QCOMPARE(remoteSocket->readAll(), sendData); - QCOMPARE(server.getCurrentCertificate(), pair.getCertificate()); - } - - void tryReconnectWithoutPairedDeviceAndReconnectedPaired() { auto& settings = Env::getSingleton()->getRemoteServiceSettings(); @@ -164,7 +180,7 @@ class test_RemoteTlsServer } QSslSocket clientPaired; - config.setCaCertificates({settings.getCertificate()}); + config.setCaCertificates(settings.getCertificates()); clientPaired.setSslConfiguration(config); connect(&clientPaired, QOverload&>::of(&QSslSocket::sslErrors), this, [&clientPaired](const QList& pErrors){ QList ignoreList; @@ -186,20 +202,99 @@ class test_RemoteTlsServer } + void pairDeviceAndReconnect_data() + { + QTest::addColumn("pairedPair"); + QTest::addColumn>("pairedChain"); + QTest::addColumn("pairedLogMsgType"); + QTest::addColumn("pairedLogError"); + QTest::addColumn("connectPair"); + QTest::addColumn>("connectChain"); + QTest::addColumn("connectLogMsgType"); + QTest::addColumn("connectLogError"); + + QTest::newRow("no peer cert pairing") << pair + << QList({}) + << QtDebugMsg + << QStringLiteral("The peer did not present any certificate") + << pair + << QList({}) + << QtDebugMsg + << QStringLiteral("The peer did not present any certificate"); + + QTest::newRow("no peer cert reconnect") << pair + << QList({pair.getCertificate()}) + << QtDebugMsg + << QString() + << pair + << QList({}) + << QtDebugMsg + << QStringLiteral("The peer did not present any certificate"); + + QTest::newRow("self signed") << pair + << QList({pair.getCertificate()}) + << QtDebugMsg + << QString() + << pair + << QList({pair.getCertificate()}) + << QtDebugMsg + << QString(); + + const auto& derived = KeyPair::generate(3072, pair.getKey().toPem(), pair.getCertificate().toPem()); + QTest::newRow("self signed & derived") << pair + << QList({pair.getCertificate()}) + << QtDebugMsg + << QString() + << derived + << QList({derived.getCertificate(), pair.getCertificate()}) + << QtDebugMsg + << QString(); + + const auto& derived2 = KeyPair::generate(3072, pair.getKey().toPem(), pair.getCertificate().toPem()); + QTest::newRow("derived") << derived2 + << QList({derived2.getCertificate(), pair.getCertificate()}) + << QtDebugMsg + << QString() + << derived2 + << QList({derived2.getCertificate(), pair.getCertificate()}) + << QtDebugMsg + << QString(); + + QTest::newRow("derived and no root reconnect") << derived2 + << QList({derived2.getCertificate(), pair.getCertificate()}) + << QtDebugMsg + << QString() + << derived2 + << QList({derived2.getCertificate()}) + << QtCriticalMsg + << QStringLiteral("Client denied... no root certificate found!"); + } + + void pairDeviceAndReconnect() { + QFETCH(KeyPair, pairedPair); + QFETCH(QList, pairedChain); + QFETCH(QtMsgType, pairedLogMsgType); + QFETCH(QString, pairedLogError); + QFETCH(KeyPair, connectPair); + QFETCH(QList, connectChain); + QFETCH(QtMsgType, connectLogMsgType); + QFETCH(QString, connectLogError); + auto& settings = Env::getSingleton()->getRemoteServiceSettings(); settings.setTrustedCertificates({}); - requiredPskForPairing(); - QVERIFY(settings.checkAndGenerateKey()); + pairDevices(pairedPair, pairedChain, pairedLogMsgType, pairedLogError); + QVERIFY(!QTest::currentTestFailed()); RemoteTlsServer server; server.startListening(0); + QVERIFY(!settings.getCertificates().isEmpty()); auto config = Env::getSingleton()->getTlsConfigRemoteIfd().getConfiguration(); - config.setPrivateKey(pair.getKey()); - config.setLocalCertificate(pair.getCertificate()); - config.setCaCertificates({settings.getCertificate()}); + config.setPrivateKey(connectPair.getKey()); + config.setLocalCertificateChain(connectChain); + config.setCaCertificates(settings.getCertificates()); QSslSocket client; client.setSslConfiguration(config); @@ -216,11 +311,22 @@ class test_RemoteTlsServer }); QSignalSpy clientEncrypted(&client, &QSslSocket::encrypted); + QSignalSpy clientErrorOccured(&client, &QAbstractSocket::errorOccurred); QSignalSpy newConnection(&server, &RemoteTlsServer::fireNewConnection); client.connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); - QTRY_COMPARE(newConnection.count(), 1); // clazy:exclude=qstring-allocations - QTRY_COMPARE(clientEncrypted.count(), 1); // clazy:exclude=qstring-allocations + if (connectLogError.isEmpty()) + { + QTRY_COMPARE(newConnection.count(), 1); // clazy:exclude=qstring-allocations + QTRY_COMPARE(clientEncrypted.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(clientErrorOccured.count(), 0); + } + else + { + QTest::ignoreMessage(connectLogMsgType, QRegularExpression(connectLogError)); + QTRY_COMPARE(clientErrorOccured.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(client.error(), QAbstractSocket::RemoteHostClosedError); + } } diff --git a/test/qt/ifd/remote/test_RemoteWebSocketServer.cpp b/test/qt/ifd/remote/test_RemoteWebSocketServer.cpp index 0b9f3fcc0..9d93d720a 100644 --- a/test/qt/ifd/remote/test_RemoteWebSocketServer.cpp +++ b/test/qt/ifd/remote/test_RemoteWebSocketServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,6 +18,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -65,6 +66,7 @@ class PskHandler if (pairingCiphers.contains(config.sessionCipher())) { allowedErrors << QSslError::SelfSignedCertificate; + allowedErrors << QSslError::SelfSignedCertificateInChain; } bool ignoreErrors = true; @@ -178,7 +180,7 @@ class test_RemoteWebSocketServer QVERIFY(mServer->listen(QStringLiteral("TestServer"))); QVERIFY(mServer->isPairingAnnounced()); - client.open(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + client.open(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(client.state(), QAbstractSocket::SocketState::ConnectedState); @@ -197,12 +199,12 @@ class test_RemoteWebSocketServer auto config = Env::getSingleton()->getTlsConfigRemoteIfd().getConfiguration(); config.setPrivateKey(pair.getKey()); config.setLocalCertificate(pair.getCertificate()); - config.setCaCertificates({settings.getCertificate()}); + config.setCaCertificates(settings.getCertificates()); client.setSslConfiguration(config); QSignalSpy spy(&client, &QWebSocket::connected); PskHandler pskHandler(&client); - client.open(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + client.open(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(client.state(), QAbstractSocket::SocketState::ConnectedState); @@ -214,7 +216,7 @@ class test_RemoteWebSocketServer { QVERIFY(mServer->listen(QStringLiteral("TestServer"))); - QUrl serverUrl(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + QUrl serverUrl(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); mServer->close(); QWebSocket client; @@ -247,10 +249,10 @@ class test_RemoteWebSocketServer QSignalSpy spy1(&client1, &QWebSocket::connected); QSignalSpy spy2(&client2, &QWebSocket::disconnected); - client1.open(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + client1.open(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); QTRY_COMPARE(spy1.count(), 1); // clazy:exclude=qstring-allocations - client2.open(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + client2.open(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); QTRY_COMPARE(spy2.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(client1.state(), QAbstractSocket::SocketState::ConnectedState); @@ -279,7 +281,7 @@ class test_RemoteWebSocketServer PskHandler pskHandler(&client, mServer.data()); mServer->setPairing(); - client.open(QString("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); + client.open(QStringLiteral("wss://127.0.0.1:").append(QString::number(mServer->getServerPort()))); QVERIFY(mServer->isPairingAnnounced()); QTRY_COMPARE(newConnectionSpy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/ifd/test_IfdConnector.cpp b/test/qt/ifd/test_IfdConnector.cpp index dc2b7e7ab..d3f773c13 100644 --- a/test/qt/ifd/test_IfdConnector.cpp +++ b/test/qt/ifd/test_IfdConnector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include "RemoteWebSocketServer.h" #include "ResourceLoader.h" #include "SecureStorage.h" +#include "TlsChecker.h" #include "messages/Discovery.h" #include @@ -22,6 +23,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(IfdDescriptor) @@ -40,7 +42,7 @@ class test_IfdConnector Discovery getDiscovery(const QString& pIfdName, quint16 pPort) { - QString ifdId("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"); + QString ifdId("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"_L1); IfdVersion::Version version = IfdVersion::Version::latest; if (IfdVersion::supported().contains(IfdVersion::Version::v2)) @@ -64,7 +66,7 @@ class test_IfdConnector oQu+/VZgDkJaSdDJ4LqVFIvUy3CFGh6ahDVsHGC5kTDm5EQWh3puWR0AkIjUWMPi xU/nr0Jsab99VgX4/nnCW92v/DIRc1c= -----END CERTIFICATE----- - )"; + )"_L1; version = IfdVersion::Version::v2; } return Discovery(pIfdName, ifdId, pPort, {version}); @@ -74,7 +76,7 @@ class test_IfdConnector void sendRequest(const QSharedPointer& pConnector, const QHostAddress& pHostAddress, const Discovery& pDiscovery, - const QString& pPassword) + const QByteArray& pPassword) { const IfdDescriptor descr(pDiscovery, pHostAddress); QMetaObject::invokeMethod(pConnector.data(), [ = ] { @@ -87,7 +89,7 @@ class test_IfdConnector const quint16 pPort) { const static QHostAddress HOST_ADDRESS(QHostAddress::LocalHost); - const static QString IFD_NAME("Smartphone1"); + const static QString IFD_NAME("Smartphone1"_L1); bool signalFound = false; for (const QList& arguments : pSignalSpy) @@ -184,7 +186,7 @@ class test_IfdConnector // No device name. const QHostAddress hostAddress(QHostAddress::LocalHost); const Discovery discoveryMsg(QString(), QStringLiteral("0123456789ABCDEF"), 2020, {IfdVersion::Version::latest}); - sendRequest(connector, hostAddress, discoveryMsg, QString()); + sendRequest(connector, hostAddress, discoveryMsg, QByteArray()); QTRY_COMPARE(spyError.count(), 1); // clazy:exclude=qstring-allocations clientThread.exit(); @@ -208,7 +210,7 @@ class test_IfdConnector // Device information is null. const QHostAddress hostAddress(QHostAddress::LocalHost); - sendRequest(connector, hostAddress, Discovery(QJsonObject()), QStringLiteral("secret")); + sendRequest(connector, hostAddress, Discovery(QJsonObject()), "secret"); QTRY_COMPARE(spyError.count(), 1); // clazy:exclude=qstring-allocations clientThread.exit(); @@ -222,7 +224,7 @@ class test_IfdConnector void requestWithEncryptedServerAndReconnectFails() { QScopedPointer server(Env::create()); - server->listen("dummy"); + server->listen("dummy"_L1); QThread clientThread; const QSharedPointer connector(new IfdConnectorImpl()); @@ -235,7 +237,7 @@ class test_IfdConnector // Password is empty. const QHostAddress hostAddress(QHostAddress::LocalHost); const Discovery discoveryMsg = getDiscovery(QStringLiteral("Smartphone1"), server->getServerPort()); - sendRequest(connector, hostAddress, discoveryMsg, QString()); + sendRequest(connector, hostAddress, discoveryMsg, QByteArray()); QTRY_COMPARE(spyError.count(), 1); // clazy:exclude=qstring-allocations clientThread.exit(); @@ -260,7 +262,7 @@ class test_IfdConnector // Currently, only API level 1 is supported. const QHostAddress hostAddress(QHostAddress::LocalHost); const Discovery discoveryMsg(QStringLiteral("Smartphone1"), QStringLiteral("0123456789ABCDEF"), 2020, {IfdVersion::Version::Unknown}); - sendRequest(connector, hostAddress, discoveryMsg, QStringLiteral("secret")); + sendRequest(connector, hostAddress, discoveryMsg, "secret"); QTRY_COMPARE(spyError.count(), 1); // clazy:exclude=qstring-allocations clientThread.exit(); @@ -285,7 +287,7 @@ class test_IfdConnector // Correct request but no server is running. const QHostAddress hostAddress(QHostAddress::LocalHost); const Discovery discoveryMsg = getDiscovery(QStringLiteral("Smartphone1"), 2020); - sendRequest(connector, hostAddress, discoveryMsg, QString("dummy")); + sendRequest(connector, hostAddress, discoveryMsg, "dummy"); QTRY_COMPARE(spyError.count(), 1); // clazy:exclude=qstring-allocations clientThread.exit(); @@ -303,37 +305,37 @@ class test_IfdConnector void encryptedConnectionSucceeds_data() { - QTest::addColumn("psk"); + QTest::addColumn("psk"); QTest::addColumn("sslConfigServer"); QTest::addColumn>("trustedCertificates"); auto& settings = Env::getSingleton()->getRemoteServiceSettings(); - QVERIFY(settings.checkAndGenerateKey()); + QVERIFY(settings.checkAndGenerateKey(3072)); QVERIFY(pair1.isValid()); QSslConfiguration config = Env::getSingleton()->getTlsConfigRemoteIfd().getConfiguration(); config.setPrivateKey(pair1.getKey()); config.setLocalCertificate(pair1.getCertificate()); - config.setCaCertificates({pair2.getCertificate(), settings.getCertificate(), pair3.getCertificate()}); - QTest::newRow("paired") << QString() << config << QList({pair2.getCertificate(), pair1.getCertificate(), pair3.getCertificate()}); + config.setCaCertificates({pair2.getCertificate(), TlsChecker::getRootCertificate(settings.getCertificates()), pair3.getCertificate()}); + QTest::newRow("paired") << QByteArray() << config << QList({pair2.getCertificate(), pair1.getCertificate(), pair3.getCertificate()}); config = Env::getSingleton()->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getConfiguration(); config.setPrivateKey(pair1.getKey()); config.setLocalCertificate(pair1.getCertificate()); - QTest::newRow("unpaired") << QString("123456") << config << QList(); + QTest::newRow("unpaired") << "123456"_ba << config << QList(); } void encryptedConnectionSucceeds() { - QFETCH(QString, psk); + QFETCH(QByteArray, psk); QFETCH(QSslConfiguration, sslConfigServer); QFETCH(QList, trustedCertificates); QWebSocketServer webSocketServer(QStringLiteral("Smartphone1"), QWebSocketServer::SecureMode); connect(&webSocketServer, &QWebSocketServer::preSharedKeyAuthenticationRequired, this, [&psk](QSslPreSharedKeyAuthenticator* pAuthenticator){ - pAuthenticator->setPreSharedKey(psk.toLatin1()); + pAuthenticator->setPreSharedKey(psk); }); QSignalSpy spySocketError(&webSocketServer, &QWebSocketServer::serverError); QSignalSpy spySocketSuccess(&webSocketServer, &QWebSocketServer::newConnection); @@ -393,7 +395,7 @@ class test_IfdConnector void encryptedConnectionWithWrongPasswordFails() { QWebSocketServer webSocketServer(QStringLiteral("Smartphone1"), QWebSocketServer::SecureMode); - QObject::connect(&webSocketServer, &QWebSocketServer::preSharedKeyAuthenticationRequired, [](QSslPreSharedKeyAuthenticator* pAuthenticator){ + QObject::connect(&webSocketServer, &QWebSocketServer::preSharedKeyAuthenticationRequired, this, [](QSslPreSharedKeyAuthenticator* pAuthenticator){ pAuthenticator->setPreSharedKey(QByteArray("secret")); }); QSignalSpy spySocketError(&webSocketServer, &QWebSocketServer::serverError); @@ -422,7 +424,7 @@ class test_IfdConnector // Send encrypted connect request with wrong psk. const QHostAddress hostAddress(QHostAddress::LocalHost); const Discovery discoveryMsg = getDiscovery(QStringLiteral("Smartphone1"), serverPort); - sendRequest(connector, hostAddress, discoveryMsg, QStringLiteral("sekret")); + sendRequest(connector, hostAddress, discoveryMsg, "sekret"); QTRY_COMPARE(spyConnectorError.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(spyConnectorSuccess.count(), 0); diff --git a/test/qt/ifd/test_IfdDescriptor.cpp b/test/qt/ifd/test_IfdDescriptor.cpp index da70d39f2..4ce2dada7 100644 --- a/test/qt/ifd/test_IfdDescriptor.cpp +++ b/test/qt/ifd/test_IfdDescriptor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdDescriptor.h" @@ -8,7 +8,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -52,7 +52,7 @@ class test_IfdDescriptor void testValidDescriptorIsDifferentFromInvalid() { const Discovery validMsg(QStringLiteral("Device"), QStringLiteral("0123456789ABCDEF"), mPort, {IfdVersion::Version::latest}); - const Discovery invalidMsg("", "", 0, {}); + const Discovery invalidMsg(""_L1, ""_L1, 0, {}); const QHostAddress address(QHostAddress::LocalHost); const IfdDescriptor valid(validMsg, address); diff --git a/test/qt/ifd/test_IfdDispatcher.cpp b/test/qt/ifd/test_IfdDispatcher.cpp index 1cb2bd052..acfb1930f 100644 --- a/test/qt/ifd/test_IfdDispatcher.cpp +++ b/test/qt/ifd/test_IfdDispatcher.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -32,9 +32,9 @@ class IfdDispatcherSpy const QSharedPointer mDispatcher; bool mClosed; GlobalStatus::Code mCloseCode; - QVector mReceivedMessageTypes; - QVector mReceivedMessages; - QVector mReceivedSignalSenders; + QList mReceivedMessageTypes; + QList mReceivedMessages; + QList mReceivedSignalSenders; public: IfdDispatcherSpy(const QSharedPointer pDispatcher); @@ -42,9 +42,9 @@ class IfdDispatcherSpy [[nodiscard]] bool isClosed() const; [[nodiscard]] GlobalStatus::Code getCloseCode() const; - [[nodiscard]] const QVector& getReceivedMessageTypes() const; - [[nodiscard]] const QVector& getReceivedMessages() const; - [[nodiscard]] const QVector& getReceivedSignalSenders() const; + [[nodiscard]] const QList& getReceivedMessageTypes() const; + [[nodiscard]] const QList& getReceivedMessages() const; + [[nodiscard]] const QList& getReceivedSignalSenders() const; private Q_SLOTS: void onClosed(GlobalStatus::Code pCloseCode, const QString& pId); @@ -107,19 +107,19 @@ GlobalStatus::Code IfdDispatcherSpy::getCloseCode() const } -const QVector& IfdDispatcherSpy::getReceivedMessageTypes() const +const QList& IfdDispatcherSpy::getReceivedMessageTypes() const { return mReceivedMessageTypes; } -const QVector& IfdDispatcherSpy::getReceivedMessages() const +const QList& IfdDispatcherSpy::getReceivedMessages() const { return mReceivedMessages; } -const QVector& IfdDispatcherSpy::getReceivedSignalSenders() const +const QList& IfdDispatcherSpy::getReceivedSignalSenders() const { return mReceivedSignalSenders; } @@ -158,7 +158,7 @@ class test_IfdDispatcher QVERIFY(spy.isClosed()); QCOMPARE(spy.getCloseCode(), GlobalStatus::Code::No_Error); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 1); QCOMPARE(senders.first(), dispatcher->getId()); } @@ -174,7 +174,7 @@ class test_IfdDispatcher QVERIFY(spy.isClosed()); QCOMPARE(spy.getCloseCode(), GlobalStatus::Code::No_Error); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 1); QCOMPARE(senders.first(), dispatcher->getId()); } @@ -190,7 +190,7 @@ class test_IfdDispatcher QVERIFY(spy.isClosed()); QCOMPARE(spy.getCloseCode(), GlobalStatus::Code::RemoteReader_CloseCode_AbnormalClose); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 1); QCOMPARE(senders.first(), dispatcher->getId()); } @@ -206,7 +206,7 @@ class test_IfdDispatcher QVERIFY(spy.isClosed()); QCOMPARE(spy.getCloseCode(), GlobalStatus::Code::RemoteReader_CloseCode_AbnormalClose); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 1); QCOMPARE(senders.first(), dispatcher->getId()); } @@ -230,8 +230,8 @@ class test_IfdDispatcher clientDispatcher->send(QSharedPointer(new IfdTransmit(QStringLiteral("NFC Reader"), QByteArray::fromHex("00A402022F00")))); clientDispatcher->send(QSharedPointer(new IfdDisconnect(QStringLiteral("NFC Reader")))); - const QVector receivedMessageTypes = spy.getReceivedMessageTypes(); - const QVector receivedMessages = spy.getReceivedMessages(); + const QList receivedMessageTypes = spy.getReceivedMessageTypes(); + const QList receivedMessages = spy.getReceivedMessages(); QCOMPARE(receivedMessageTypes.size(), 3); QCOMPARE(receivedMessages.size(), 3); @@ -251,7 +251,7 @@ class test_IfdDispatcher QCOMPARE(ifdDisconnect.getType(), IfdMessageType::IFDDisconnect); QCOMPARE(ifdDisconnect.getSlotHandle(), QStringLiteral("NFC Reader")); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 3); QCOMPARE(senders.at(0), serverDispatcher->getId()); QCOMPARE(senders.at(1), serverDispatcher->getId()); @@ -277,7 +277,7 @@ class test_IfdDispatcher QVERIFY(spy.isClosed()); QCOMPARE(spy.getCloseCode(), GlobalStatus::Code::No_Error); - const QVector& senders = spy.getReceivedSignalSenders(); + const QList& senders = spy.getReceivedSignalSenders(); QCOMPARE(senders.size(), 1); QCOMPARE(senders.at(0), serverDispatcher->getId()); } @@ -297,7 +297,7 @@ class test_IfdDispatcher clientDispatcher->send(QSharedPointer(new IfdEstablishContext(IfdVersion::Version::v2, DeviceInfo::getName()))); clientDispatcher->send(QSharedPointer(new IfdEstablishContext(IfdVersion::Version::v2, DeviceInfo::getName()))); - const QVector& clientReceivedDataBlocks = clientChannel->getReceivedDataBlocks(); + const QList& clientReceivedDataBlocks = clientChannel->getReceivedDataBlocks(); QCOMPARE(clientReceivedDataBlocks.size(), 2); const IfdEstablishContextResponse message1(IfdMessage::parseByteArray(clientReceivedDataBlocks.at(0))); @@ -327,7 +327,7 @@ class test_IfdDispatcher clientDispatcher->send(QSharedPointer(new IfdEstablishContext(IfdVersion::Version::Unknown, DeviceInfo::getName()))); - const QVector& clientReceivedDataBlocks = clientChannel->getReceivedDataBlocks(); + const QList& clientReceivedDataBlocks = clientChannel->getReceivedDataBlocks(); QCOMPARE(clientReceivedDataBlocks.size(), 1); const IfdEstablishContextResponse message(IfdMessage::parseByteArray(clientReceivedDataBlocks.at(0))); diff --git a/test/qt/ifd/test_IfdListImpl.cpp b/test/qt/ifd/test_IfdListImpl.cpp index 772893ed4..362659fbe 100644 --- a/test/qt/ifd/test_IfdListImpl.cpp +++ b/test/qt/ifd/test_IfdListImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "IfdListImpl.h" @@ -8,6 +8,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -22,10 +23,10 @@ class test_IfdListImpl IfdListImpl deviceList(10, 1); QSignalSpy spyVanished(&deviceList, &IfdListImpl::fireDeviceVanished); - const Discovery offerMsg1 = Discovery("Dev1", QStringLiteral("0123456789ABCDEF"), 1234, {IfdVersion::Version::latest}); - const Discovery offerMsg2 = Discovery("Dev1", QStringLiteral("0123456789ABCDFF"), 1234, {IfdVersion::Version::latest}); - const QHostAddress addr1 = QHostAddress(QString("5.6.7.8")); - const QHostAddress addr2 = QHostAddress(QString("5.6.7.9")); + const Discovery offerMsg1 = Discovery("Dev1"_L1, QStringLiteral("0123456789ABCDEF"), 1234, {IfdVersion::Version::latest}); + const Discovery offerMsg2 = Discovery("Dev1"_L1, QStringLiteral("0123456789ABCDFF"), 1234, {IfdVersion::Version::latest}); + const QHostAddress addr1 = QHostAddress("5.6.7.8"_L1); + const QHostAddress addr2 = QHostAddress("5.6.7.9"_L1); { const IfdDescriptor descr(offerMsg1, addr1); diff --git a/test/qt/ifd/test_ServerMessageHandler.cpp b/test/qt/ifd/test_ServerMessageHandler.cpp index c1d236f2b..de2572d5c 100644 --- a/test/qt/ifd/test_ServerMessageHandler.cpp +++ b/test/qt/ifd/test_ServerMessageHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,8 @@ #include "ServerMessageHandlerImpl.h" #include "messages/IfdConnect.h" #include "messages/IfdConnectResponse.h" +#include "messages/IfdDestroyPaceChannel.h" +#include "messages/IfdDestroyPaceChannelResponse.h" #include "messages/IfdDisconnect.h" #include "messages/IfdDisconnectResponse.h" #include "messages/IfdError.h" @@ -26,16 +28,16 @@ #include "messages/IfdTransmit.h" #include "messages/IfdTransmitResponse.h" -#include "MockCardConnectionWorker.h" #include "MockDataChannel.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "TestFileHelper.h" #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(ECardApiResult::Minor) @@ -81,7 +83,7 @@ class test_ServerMessageHandler void removeReaderAndConsumeMessages(const QString& pReaderName) { QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReaderManagerPlugIn::getInstance().removeReader(pReaderName); + MockReaderManagerPlugin::getInstance().removeReader(pReaderName); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations } @@ -115,7 +117,7 @@ class test_ServerMessageHandler void initTestCase() { Env::getSingleton()->init(); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -206,10 +208,10 @@ class test_ServerMessageHandler const QByteArrayList serverMessages({ status.toByteArray(IfdVersion::Version::v2, contextHandle), - IfdConnectResponse("NFC Reader").toByteArray(IfdVersion::Version::v2, contextHandle), - IfdDisconnectResponse("NFC Reader").toByteArray(IfdVersion::Version::v2, contextHandle), - IfdTransmitResponse("NFC Reader", "9000").toByteArray(IfdVersion::Version::v2, contextHandle), - IfdEstablishPaceChannelResponse("My little Reader", EstablishPaceChannelOutput()).toByteArray(IfdVersion::Version::v2, contextHandle) + IfdConnectResponse("NFC Reader"_L1).toByteArray(IfdVersion::Version::v2, contextHandle), + IfdDisconnectResponse("NFC Reader"_L1).toByteArray(IfdVersion::Version::v2, contextHandle), + IfdTransmitResponse("NFC Reader"_L1, "9000").toByteArray(IfdVersion::Version::v2, contextHandle), + IfdEstablishPaceChannelResponse("My little Reader"_L1, EstablishPaceChannelOutput()).toByteArray(IfdVersion::Version::v2, contextHandle) }); for (const auto& serverMessage : serverMessages) { @@ -266,7 +268,7 @@ class test_ServerMessageHandler ensureContext(contextHandle); QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations sendSpy.clear(); @@ -300,12 +302,12 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -362,11 +364,11 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -423,11 +425,11 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -486,11 +488,11 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -549,11 +551,11 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -624,13 +626,13 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig({ {CardReturnCode::OK, QByteArray("9000")} })); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -692,11 +694,11 @@ class test_ServerMessageHandler QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("test-reader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations reader->setCard(MockCardConfig()); QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); @@ -740,44 +742,154 @@ class test_ServerMessageHandler QVERIFY(ifdEstablishPACEChannelResponse.resultHasError()); QCOMPARE(ifdEstablishPACEChannelResponse.getResultMinor(), ECardApiResult::Minor::AL_Unknown_Error); - QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("EstablishPaceChannel is only available in pin pad mode."))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("\"EstablishPaceChannel\" is only available in pin pad mode."))); removeReaderAndConsumeMessages(QStringLiteral("test-reader")); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(pinpadModeToSave); } - void test_handleIfdModifyPin() + void test_handleDestroyPaceChannel() { + const bool pinpadModeToSave = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); + Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); - const QByteArray message("{\n" - " \"ContextHandle\": \"TestContext\",\n" - " \"InputData\": \"abcd1234\",\n" - " \"SlotHandle\": \"SlotHandle\",\n" - " \"msg\": \"IFDModifyPIN\"\n" - "}\n"); + ServerMessageHandlerImpl serverMsgHandler(mDataChannel); + QString contextHandle; + ensureContext(contextHandle); + + QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); + + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + reader->setCard(MockCardConfig({ + {CardReturnCode::OK, QByteArray("6700")} + })); + QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); + ReaderInfo info = reader->getReaderInfo(); + info.setCardInfo(cardInfo); + reader->setReaderInfo(info); + QTRY_COMPARE(sendSpy.count(), 3); // clazy:exclude=qstring-allocations + sendSpy.clear(); + + mDataChannel->onReceived(IfdDestroyPaceChannel(QStringLiteral("invalidSlotHandle")).toByteArray(IfdVersion::Version::latest, contextHandle)); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + sendSpy.clear(); + + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Card is not connected"))); + const auto& msg0 = mDispatcher->getMessage().staticCast(); + QCOMPARE(msg0->getResultMinor(), ECardApiResult::Minor::IFDL_InvalidSlotHandle); + + const QByteArray ifdConnectMsg = IfdConnect(QStringLiteral("test-reader"), true).toByteArray(IfdVersion::Version::latest, contextHandle); + mDataChannel->onReceived(ifdConnectMsg); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + + const QList& connectResponseArguments = sendSpy.takeLast(); + const QVariant connectResponseVariant = connectResponseArguments.at(0); + QVERIFY(connectResponseVariant.canConvert()); + + const IfdConnectResponse connectResponse(IfdMessage::parseByteArray(connectResponseVariant.toByteArray())); + QVERIFY(!connectResponse.isIncomplete()); + QCOMPARE(connectResponse.getType(), IfdMessageType::IFDConnectResponse); + QCOMPARE(connectResponse.getContextHandle(), contextHandle); + QVERIFY(!connectResponse.getSlotHandle().isEmpty()); + QVERIFY(!connectResponse.resultHasError()); + QCOMPARE(connectResponse.getResultMinor(), ECardApiResult::Minor::null); + + const QByteArray ifdDestroyPace = IfdDestroyPaceChannel(connectResponse.getSlotHandle()).toByteArray(IfdVersion::Version::latest, contextHandle); + mDataChannel->onReceived(ifdDestroyPace); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + sendSpy.clear(); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("\"DestroyPaceChannel\" is only available in pin pad mode."))); + QCOMPARE(mDispatcher->getMessage()->getType(), IfdMessageType::IFDDestroyPACEChannelResponse); + const auto& msg1 = mDispatcher->getMessage().staticCast(); + QCOMPARE(msg1->getResultMinor(), ECardApiResult::Minor::AL_Unknown_Error); + QCOMPARE(msg1->getSlotHandle(), connectResponse.getSlotHandle()); + + Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(true); + mDataChannel->onReceived(ifdDestroyPace); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + sendSpy.clear(); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Destroying PACE channel"))); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Destroying PACE channel with invalid command causing 6700 as return code"))); + QCOMPARE(mDispatcher->getMessage()->getType(), IfdMessageType::IFDDestroyPACEChannelResponse); + const auto& msg2 = mDispatcher->getMessage().staticCast(); + QCOMPARE(msg2->getResultMinor(), ECardApiResult::Minor::null); + QCOMPARE(msg2->getSlotHandle(), connectResponse.getSlotHandle()); - const QJsonObject& obj = QJsonDocument::fromJson(message).object(); + removeReaderAndConsumeMessages(QStringLiteral("test-reader")); + Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(pinpadModeToSave); + } + + + void test_handleIfdModifyPin() + { + const bool pinpadModeToSave = Env::getSingleton()->getRemoteServiceSettings().getPinPadMode(); + Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); + + QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); ServerMessageHandlerImpl serverMsgHandler(mDataChannel); QSignalSpy spyModifyPin(&serverMsgHandler, &ServerMessageHandler::fireModifyPin); QString contextHandle; ensureContext(contextHandle); - QVERIFY(!TestFileHelper::containsLog(logSpy, QLatin1String("ModifyPin is only available in pin pad mode."))); - Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(false); - Q_EMIT mDispatcher->fireReceived(IfdMessageType::IFDModifyPIN, obj, QString()); + QSignalSpy sendSpy(mDataChannel.data(), &MockDataChannel::fireSend); + + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("test-reader"_L1); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + reader->setCard(MockCardConfig()); + QTRY_COMPARE(sendSpy.count(), 2); // clazy:exclude=qstring-allocations + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); + ReaderInfo info = reader->getReaderInfo(); + info.setCardInfo(cardInfo); + reader->setReaderInfo(info); + QTRY_COMPARE(sendSpy.count(), 3); // clazy:exclude=qstring-allocations + sendSpy.clear(); + + mDataChannel->onReceived(IfdModifyPin(QStringLiteral("invalidSlotHandle"), QByteArray::fromHex("abcd1234")).toByteArray(IfdVersion::Version::latest, contextHandle)); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + sendSpy.clear(); + + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Card is not connected"))); + const auto& msg0 = mDispatcher->getMessage().staticCast(); + QCOMPARE(msg0->getResultMinor(), ECardApiResult::Minor::IFDL_InvalidSlotHandle); + QCOMPARE(spyModifyPin.count(), 0); + + const QByteArray ifdConnectMsg = IfdConnect(QStringLiteral("test-reader"), true).toByteArray(IfdVersion::Version::latest, contextHandle); + mDataChannel->onReceived(ifdConnectMsg); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + + const QList& connectResponseArguments = sendSpy.takeLast(); + const QVariant connectResponseVariant = connectResponseArguments.at(0); + QVERIFY(connectResponseVariant.canConvert()); + + const IfdConnectResponse connectResponse(IfdMessage::parseByteArray(connectResponseVariant.toByteArray())); + QVERIFY(!connectResponse.isIncomplete()); + QCOMPARE(connectResponse.getType(), IfdMessageType::IFDConnectResponse); + QCOMPARE(connectResponse.getContextHandle(), contextHandle); + QVERIFY(!connectResponse.getSlotHandle().isEmpty()); + QVERIFY(!connectResponse.resultHasError()); + QCOMPARE(connectResponse.getResultMinor(), ECardApiResult::Minor::null); + + const QByteArray ifdModifyPin = IfdModifyPin(connectResponse.getSlotHandle(), QByteArray::fromHex("abcd1234")).toByteArray(IfdVersion::Version::latest, contextHandle); + mDataChannel->onReceived(ifdModifyPin); + QTRY_COMPARE(sendSpy.count(), 1); // clazy:exclude=qstring-allocations + sendSpy.clear(); + QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("\"ModifyPin\" is only available in pin pad mode."))); QCOMPARE(mDispatcher->getMessage()->getType(), IfdMessageType::IFDModifyPINResponse); const auto& msg1 = mDispatcher->getMessage().staticCast(); QCOMPARE(msg1->getResultMinor(), ECardApiResult::Minor::AL_Unknown_Error); - QCOMPARE(msg1->getSlotHandle(), "SlotHandle"); - QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("ModifyPin is only available in pin pad mode."))); + QCOMPARE(msg1->getSlotHandle(), connectResponse.getSlotHandle()); + QCOMPARE(spyModifyPin.count(), 0); - QVERIFY(!TestFileHelper::containsLog(logSpy, QLatin1String("Card is not connected"))); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(true); - Q_EMIT mDispatcher->fireReceived(IfdMessageType::IFDModifyPIN, obj, QString()); - const auto& msg2 = mDispatcher->getMessage().staticCast(); - QCOMPARE(msg2->getResultMinor(), ECardApiResult::Minor::IFDL_InvalidSlotHandle); - QVERIFY(TestFileHelper::containsLog(logSpy, QLatin1String("Card is not connected"))); + mDataChannel->onReceived(ifdModifyPin); + QCOMPARE(spyModifyPin.count(), 1); + + removeReaderAndConsumeMessages(QStringLiteral("test-reader")); + Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(pinpadModeToSave); } @@ -802,7 +914,7 @@ class test_ServerMessageHandler QFETCH(ECardApiResult::Minor, minor); ServerMessageHandlerImpl serverMsgHandler(mDataChannel); - const QString slotHandle("Slot Handle"); + const QString slotHandle("Slot Handle"_L1); const ResponseApdu apdu(statusCode); QString contextHandle; @@ -831,7 +943,7 @@ class test_ServerMessageHandler QFETCH(CardReturnCode, returnCode); QFETCH(ECardApiResult::Minor, minor); - const QString slotHandle("Slot Handle"); + const QString slotHandle("Slot Handle"_L1); EstablishPaceChannelOutput output; output.setPaceReturnCode(returnCode); diff --git a/test/qt/ifd/test_WebSocketChannel.cpp b/test/qt/ifd/test_WebSocketChannel.cpp new file mode 100644 index 000000000..be455c27d --- /dev/null +++ b/test/qt/ifd/test_WebSocketChannel.cpp @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "WebSocketChannel.h" + +#include "Env.h" +#include "KeyPair.h" +#include "RemoteServiceSettings.h" +#include "ResourceLoader.h" +#include "SecureStorage.h" +#include "TlsChecker.h" + +#include +#include +#include + +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +class test_WebSocketChannel + : public QObject +{ + Q_OBJECT + + private: + const KeyPair mKeyServer = KeyPair::generate(); + const KeyPair mKeyClient = KeyPair::generate(); + QSharedPointer mServer; + QSharedPointer mClient; + QSharedPointer mChannel; + + void setupServerConfig(const QList& pKnownCerts) + { + if (mServer) + { + QSslConfiguration sslConfig; + sslConfig.setCiphers(Env::getSingleton()->getTlsConfig().getCiphers()); + sslConfig.setLocalCertificate(mKeyServer.getCertificate()); + sslConfig.setPrivateKey(mKeyServer.getKey()); + sslConfig.setCaCertificates(pKnownCerts); + mServer->setSslConfiguration(sslConfig); + } + } + + + void setupClientConfig(const QList& pKnownCerts, const QSslKey& pPrivateKey) + { + if (mClient) + { + QSslConfiguration sslConfig; + sslConfig.setCiphers(Env::getSingleton()->getTlsConfig().getCiphers()); + sslConfig.setLocalCertificateChain(pKnownCerts); + sslConfig.setPrivateKey(pPrivateKey); + sslConfig.setCaCertificates({mKeyServer.getCertificate()}); + mClient->setSslConfiguration(sslConfig); + } + } + + + void establishConnection() + { + QVERIFY(mServer->listen(QHostAddress::LocalHost)); + + mClient->open(mServer->serverUrl()); + QTRY_VERIFY(mClient->isValid()); // clazy:exclude=qstring-allocations + QTRY_VERIFY(!mChannel.isNull()); // clazy:exclude=qstring-allocations + } + + private Q_SLOTS: + void initTestCase() + { + ResourceLoader::getInstance().init(); + } + + + void init() + { + mServer.reset(new QWebSocketServer(QStringLiteral("test_WebSocketChannel"), QWebSocketServer::SecureMode)); + connect(mServer.data(), &QWebSocketServer::newConnection, this, [this]{ + QWebSocket* socket = mServer->nextPendingConnection(); + if (socket) + { + mChannel.reset(new WebSocketChannel(QSharedPointer(socket))); + } + }); + + mClient.reset(new QWebSocket()); + connect(mClient.data(), &QWebSocket::sslErrors, this, [this](const QList& pErrors) { + Q_UNUSED(pErrors) + mClient->ignoreSslErrors(); + }); + } + + + void test_send() + { + setupServerConfig({mKeyClient.getCertificate()}); + setupClientConfig({mKeyClient.getCertificate()}, mKeyClient.getKey()); + establishConnection(); + + QSignalSpy textReceivedSpy(mClient.data(), &QWebSocket::textMessageReceived); + + const auto& text = "Hello, World!"_ba; + mChannel->send(text); + QTRY_COMPARE(textReceivedSpy.count(), 1); // clazy:exclude=qstring-allocations + QCOMPARE(textReceivedSpy.constFirst().constFirst().value(), text); + } + + + void test_getId_data() + { + QTest::addColumn>("certs"); + QTest::addColumn("privateKey"); + + QList certs {mKeyClient.getCertificate()}; + + QTest::addRow("Single certificate") << certs << mKeyClient.getKey(); + + const auto& keySize = 3000; + const auto& derivedCert = KeyPair::generate(keySize, mKeyClient.getKey().toPem(), mKeyClient.getCertificate().toPem()); + certs.prepend(derivedCert.getCertificate()); + QTest::addRow("Two certificates (one derived)") << certs << derivedCert.getKey(); + + const auto& secondDerivedCert = KeyPair::generate(keySize, derivedCert.getKey().toPem(), derivedCert.getCertificate().toPem()); + certs.prepend(secondDerivedCert.getCertificate()); + QTest::addRow("Three certificates (two derived)") << certs << secondDerivedCert.getKey(); + + std::reverse(certs.begin(), certs.end()); + QTest::addRow("Three certificates (two derived) - reversed order") << certs << mKeyClient.getKey(); + } + + + void test_getId() + { + QFETCH(QList, certs); + QFETCH(QSslKey, privateKey); + + setupServerConfig(certs); + setupClientConfig(certs, privateKey); + establishConnection(); + + const auto& selfSignedCert = TlsChecker::getRootCertificate(certs); + QCOMPARE(mChannel->getId(), RemoteServiceSettings::generateFingerprint(selfSignedCert)); + } + + +}; + + +QTEST_GUILESS_MAIN(test_WebSocketChannel) +#include "test_WebSocketChannel.moc" diff --git a/test/qt/network/test_DatagramHandlerImpl.cpp b/test/qt/network/test_DatagramHandlerImpl.cpp index 7b73361dc..03da2de42 100644 --- a/test/qt/network/test_DatagramHandlerImpl.cpp +++ b/test/qt/network/test_DatagramHandlerImpl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -22,6 +22,7 @@ #include #endif +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -57,12 +58,12 @@ class test_DatagramHandlerImpl QVERIFY(socket->isBound()); QCOMPARE(logSpy.count(), 1); auto param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Bound on port:")); + QVERIFY(param.at(0).toString().contains("Bound on port:"_L1)); socket.reset(); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Shutdown socket")); + QVERIFY(param.at(0).toString().contains("Shutdown socket"_L1)); } @@ -92,7 +93,7 @@ class test_DatagramHandlerImpl QVERIFY(!socket->isBound()); QCOMPARE(logSpy.count(), 1); auto param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Cannot bind socket: \"The address is protected\"")); + QVERIFY(param.at(0).toString().contains("Cannot bind socket: \"The address is protected\""_L1)); } @@ -175,7 +176,7 @@ class test_DatagramHandlerImpl QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); QJsonObject obj; - obj["test"] = "dummy"; + obj["test"_L1] = "dummy"_L1; QJsonDocument doc; doc.setObject(obj); if (broadcast) diff --git a/test/qt/network/test_HttpRequest.cpp b/test/qt/network/test_HttpRequest.cpp index 7c4274ae0..cff98b235 100644 --- a/test/qt/network/test_HttpRequest.cpp +++ b/test/qt/network/test_HttpRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -36,7 +37,7 @@ class test_HttpRequest QCOMPARE(request.getHttpMethod(), HTTP_GET); QCOMPARE(request.getHeader().size(), 1); QCOMPARE(request.getHeader("host"), QByteArray("Dummy.de")); - QCOMPARE(request.getUrl(), QUrl("/favicon.ico")); + QCOMPARE(request.getUrl(), QUrl("/favicon.ico"_L1)); QCOMPARE(request.getBody().size(), 0); } @@ -64,7 +65,7 @@ class test_HttpRequest QCOMPARE(request.getHeader("host"), QByteArray("server.example.com")); QCOMPARE(request.getHeader("upgrade"), QByteArray("websocket")); QCOMPARE(request.getHeader("connection"), QByteArray("Upgrade")); - QCOMPARE(request.getUrl(), QUrl("/")); + QCOMPARE(request.getUrl(), QUrl("/"_L1)); QCOMPARE(request.getBody().size(), 0); } @@ -100,7 +101,7 @@ class test_HttpRequest QCOMPARE(request.getHttpMethod(), HTTP_GET); QCOMPARE(request.getHeader().size(), 9); QCOMPARE(request.getHeader("host"), QByteArray("127.0.0.1:24727")); - QCOMPARE(request.getUrl(), QUrl("/eID-Client?tcTokenURL=https%3A%2F%2Ftest.governikus-eid.de%3A443%2FAutent-DemoApplication%2FRequestServlet%3Fprovider%3Ddemo_epa_20%26redirect%3Dtrue")); + QCOMPARE(request.getUrl(), QUrl("/eID-Client?tcTokenURL=https%3A%2F%2Ftest.governikus-eid.de%3A443%2FAutent-DemoApplication%2FRequestServlet%3Fprovider%3Ddemo_epa_20%26redirect%3Dtrue"_L1)); QCOMPARE(request.getBody().size(), 0); request.triggerSocketBuffer(); diff --git a/test/qt/network/test_HttpResponse.cpp b/test/qt/network/test_HttpResponse.cpp index a9a7481c7..be7f658f2 100644 --- a/test/qt/network/test_HttpResponse.cpp +++ b/test/qt/network/test_HttpResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -21,7 +22,7 @@ class test_HttpResponse private Q_SLOTS: void init() { - QCoreApplication::setApplicationVersion("1.2"); + QCoreApplication::setApplicationVersion("1.2"_L1); } diff --git a/test/qt/network/test_HttpServer.cpp b/test/qt/network/test_HttpServer.cpp index 791f2badb..48b3ab7e1 100644 --- a/test/qt/network/test_HttpServer.cpp +++ b/test/qt/network/test_HttpServer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,6 +21,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -62,7 +63,7 @@ class test_HttpServer QVERIFY(server->boundAddresses().size() < 3); auto param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Spawn shared instance: governikus::HttpServer")); + QVERIFY(param.at(0).toString().contains("Spawn shared instance: governikus::HttpServer"_L1)); param = logSpy.takeFirst(); const auto listenPort = param.at(0).toString(); @@ -104,7 +105,7 @@ class test_HttpServer server.reset(); QCOMPARE(logSpy.count(), 1); param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Shutdown server")); + QVERIFY(param.at(0).toString().contains("Shutdown server"_L1)); } @@ -127,7 +128,7 @@ class test_HttpServer QVERIFY(!server.isListening()); QCOMPARE(logSpy.count(), 2); auto param = logSpy.takeFirst(); - QVERIFY(param.at(0).toString().contains("Cannot start server: \"The address is protected\"")); + QVERIFY(param.at(0).toString().contains("Cannot start server: \"The address is protected\""_L1)); } @@ -137,7 +138,7 @@ class test_HttpServer QVERIFY(server.isListening()); QSignalSpy spyServer(&server, &HttpServer::fireNewHttpRequest); - auto url = QUrl("http://127.0.0.1:" + QString::number(server.getServerPort()) + "/eID-Client?tcTokenURL=https%3A%2F%2Fdummy.de"); + auto url = QUrl("http://127.0.0.1:"_L1 + QString::number(server.getServerPort()) + "/eID-Client?tcTokenURL=https%3A%2F%2Fdummy.de"_L1); auto reply = mAccessManager.get(QNetworkRequest(url)); QSignalSpy spyClient(reply, &QNetworkReply::finished); @@ -145,7 +146,7 @@ class test_HttpServer auto param = spyServer.takeFirst(); auto httpRequest = qvariant_cast>(param.at(0)); QCOMPARE(httpRequest->getMethod(), QByteArray("GET")); - QCOMPARE(httpRequest->getUrl(), QUrl("/eID-Client?tcTokenURL=https%3A%2F%2Fdummy.de")); + QCOMPARE(httpRequest->getUrl(), QUrl("/eID-Client?tcTokenURL=https%3A%2F%2Fdummy.de"_L1)); QVERIFY(httpRequest->send(HTTP_STATUS_NOT_FOUND)); @@ -161,7 +162,7 @@ class test_HttpServer QVERIFY(server.isListening()); QSignalSpy spyServer(&server, &HttpServer::fireNewWebSocketRequest); - QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.getServerPort()))); + QNetworkRequest request(QUrl("http://127.0.0.1:"_L1 + QString::number(server.getServerPort()))); request.setRawHeader("upgrade", "websocket"); request.setRawHeader("connection", "upgrade"); mAccessManager.get(request); @@ -178,7 +179,7 @@ class test_HttpServer QVERIFY(requestData.contains("\r\n\r\n")); param = logSpy.takeLast(); - QVERIFY(param.at(0).toString().contains("Upgrade to websocket requested")); + QVERIFY(param.at(0).toString().contains("Upgrade to websocket requested"_L1)); } @@ -187,7 +188,7 @@ class test_HttpServer HttpServer server; QVERIFY(server.isListening()); - QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.getServerPort()))); + QNetworkRequest request(QUrl("http://127.0.0.1:"_L1 + QString::number(server.getServerPort()))); request.setRawHeader("upgrade", "unknown"); request.setRawHeader("connection", "upgrade"); auto reply = mAccessManager.get(request); @@ -199,7 +200,7 @@ class test_HttpServer QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 404); auto param = logSpy.takeLast(); - QVERIFY(param.at(0).toString().contains("Unknown upgrade requested")); + QVERIFY(param.at(0).toString().contains("Unknown upgrade requested"_L1)); } @@ -225,7 +226,7 @@ class test_HttpServer HttpServer server; QVERIFY(server.isListening()); - request.setUrl(QUrl("http://127.0.0.1:" + QString::number(server.getServerPort()))); + request.setUrl(QUrl("http://127.0.0.1:"_L1 + QString::number(server.getServerPort()))); auto reply = mAccessManager.get(request); @@ -243,7 +244,7 @@ class test_HttpServer void addressInUseError() { QTcpServer existingServer; - existingServer.listen(QHostAddress::LocalHost, 0); + QVERIFY(existingServer.listen(QHostAddress::LocalHost, 0)); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); HttpServer server(existingServer.serverPort()); diff --git a/test/qt/network/test_HttpServerRequestor.cpp b/test/qt/network/test_HttpServerRequestor.cpp index 55cdf2284..86248c867 100644 --- a/test/qt/network/test_HttpServerRequestor.cpp +++ b/test/qt/network/test_HttpServerRequestor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "HttpServerRequestor.h" @@ -9,6 +9,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QHostAddress) @@ -22,27 +23,27 @@ class test_HttpServerRequestor private Q_SLOTS: void createUrl_data() { - QTest::addColumn("query"); + QTest::addColumn("query"); QTest::addColumn("port"); QTest::addColumn("host"); - QTest::addColumn("path"); + QTest::addColumn("path"); QTest::addColumn("result"); - QTest::addRow("Localhost IPv4") << "foo=bar" << quint16(1337) << QHostAddress(QHostAddress::LocalHost) << "/some/path" << QUrl("http://127.0.0.1:1337/some/path?foo=bar"); - QTest::addRow("Localhost IPv6") << "foo=bar" << quint16(1337) << QHostAddress(QHostAddress::LocalHostIPv6) << "/some/path" << QUrl("http://[::1]:1337/some/path?foo=bar"); + QTest::addRow("Localhost IPv4") << "foo=bar"_L1 << quint16(1337) << QHostAddress(QHostAddress::LocalHost) << "/some/path"_L1 << QUrl("http://127.0.0.1:1337/some/path?foo=bar"_L1); + QTest::addRow("Localhost IPv6") << "foo=bar"_L1 << quint16(1337) << QHostAddress(QHostAddress::LocalHostIPv6) << "/some/path"_L1 << QUrl("http://[::1]:1337/some/path?foo=bar"_L1); } void createUrl() { - QFETCH(QString, query); + QFETCH(QLatin1String, query); QFETCH(quint16, port); QFETCH(QHostAddress, host); - QFETCH(QString, path); + QFETCH(QLatin1String, path); QFETCH(QUrl, result); const auto& url = HttpServerRequestor::createUrl(query, port, host, path); - QCOMPARE(url.scheme(), "http"); + QCOMPARE(url.scheme(), "http"_L1); QCOMPARE(url.query(), query); QCOMPARE(url.port(), port); QCOMPARE(QHostAddress(url.host()), host); @@ -54,27 +55,27 @@ class test_HttpServerRequestor void getRequest_data() { QTest::addColumn("customManager"); - QTest::addColumn("path"); + QTest::addColumn("path"); QTest::addColumn("response"); - QTest::addRow("HTTP_STATUS_OK") << false << "/foo" << HttpResponse(HTTP_STATUS_OK, "bar"); - QTest::addRow("HTTP_STATUS_NOT_FOUND") << false << "/foo" << HttpResponse(HTTP_STATUS_NOT_FOUND); - QTest::addRow("HTTP_STATUS_OK_customManager") << true << "/foo" << HttpResponse(HTTP_STATUS_OK, "bar"); - QTest::addRow("HTTP_STATUS_NOT_FOUND_customManager") << true << "/foo" << HttpResponse(HTTP_STATUS_NOT_FOUND); + QTest::addRow("HTTP_STATUS_OK") << false << "/foo"_ba << HttpResponse(HTTP_STATUS_OK, "bar"); + QTest::addRow("HTTP_STATUS_NOT_FOUND") << false << "/foo"_ba << HttpResponse(HTTP_STATUS_NOT_FOUND); + QTest::addRow("HTTP_STATUS_OK_customManager") << true << "/foo"_ba << HttpResponse(HTTP_STATUS_OK, "bar"); + QTest::addRow("HTTP_STATUS_NOT_FOUND_customManager") << true << "/foo"_ba << HttpResponse(HTTP_STATUS_NOT_FOUND); } void getRequest() { QFETCH(bool, customManager); - QFETCH(QString, path); + QFETCH(QByteArray, path); QFETCH(HttpResponse, response); MockHttpServer server; - server.addMock(path.toLocal8Bit(), response, HTTP_GET); + server.addMock(path, response, HTTP_GET); HttpServerRequestor requestor(customManager); - const auto& reply = requestor.getRequest(server.getAddress(path)); + const auto& reply = requestor.getRequest(server.getAddress(QString::fromLatin1(path))); QVERIFY(reply->isFinished()); QCOMPARE(reply->readAll(), response.getBody()); const auto& statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -84,24 +85,24 @@ class test_HttpServerRequestor void postRequest_data() { - QTest::addColumn("path"); + QTest::addColumn("path"); QTest::addColumn("response"); - QTest::addRow("HTTP_STATUS_OK") << "/foo" << HttpResponse(HTTP_STATUS_OK, "bar"); - QTest::addRow("HTTP_STATUS_NOT_FOUND") << "/foo" << HttpResponse(HTTP_STATUS_NOT_FOUND); + QTest::addRow("HTTP_STATUS_OK") << "/foo"_ba << HttpResponse(HTTP_STATUS_OK, "bar"); + QTest::addRow("HTTP_STATUS_NOT_FOUND") << "/foo"_ba << HttpResponse(HTTP_STATUS_NOT_FOUND); } void postRequest() { - QFETCH(QString, path); + QFETCH(QByteArray, path); QFETCH(HttpResponse, response); MockHttpServer server; - server.addMock(path.toLocal8Bit(), response, HTTP_POST); + server.addMock(path, response, HTTP_POST); HttpServerRequestor requestor; - const auto& reply = requestor.postRequest(server.getAddress(path), "bar", "application/json"); + const auto& reply = requestor.postRequest(server.getAddress(QString::fromLatin1(path)), "bar", "application/json"_L1); QVERIFY(reply->isFinished()); QCOMPARE(reply->readAll(), response.getBody()); const auto& statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -111,24 +112,24 @@ class test_HttpServerRequestor void deleteRequest_data() { - QTest::addColumn("path"); + QTest::addColumn("path"); QTest::addColumn("response"); - QTest::addRow("HTTP_STATUS_OK") << "/foo" << HttpResponse(HTTP_STATUS_OK, "bar"); - QTest::addRow("HTTP_STATUS_NOT_FOUND") << "/foo" << HttpResponse(HTTP_STATUS_NOT_FOUND); + QTest::addRow("HTTP_STATUS_OK") << "/foo"_ba << HttpResponse(HTTP_STATUS_OK, "bar"); + QTest::addRow("HTTP_STATUS_NOT_FOUND") << "/foo"_ba << HttpResponse(HTTP_STATUS_NOT_FOUND); } void deleteRequest() { - QFETCH(QString, path); + QFETCH(QByteArray, path); QFETCH(HttpResponse, response); MockHttpServer server; - server.addMock(path.toLocal8Bit(), response, HTTP_DELETE); + server.addMock(path, response, HTTP_DELETE); HttpServerRequestor requestor; - const auto& reply = requestor.deleteRequest(server.getAddress(path)); + const auto& reply = requestor.deleteRequest(server.getAddress(QString::fromLatin1(path))); QVERIFY(reply->isFinished()); QCOMPARE(reply->readAll(), response.getBody()); const auto& statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); diff --git a/test/qt/network/test_NetworkManager.cpp b/test/qt/network/test_NetworkManager.cpp index 417f24870..0fdf5ce21 100644 --- a/test/qt/network/test_NetworkManager.cpp +++ b/test/qt/network/test_NetworkManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -23,6 +23,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QSharedPointer) @@ -38,7 +39,7 @@ class test_NetworkManager ResourceLoader::getInstance().init(); Env::getSingleton()->init(); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -59,22 +60,22 @@ class test_NetworkManager void paosRequestAttached() { - QNetworkRequest request(QUrl("https://dummy")); + QNetworkRequest request(QUrl("https://dummy"_L1)); auto reply = Env::getSingleton()->paos(request, "paosNamespace", "content", false, QByteArray()); reply->abort(); QVERIFY(request.hasRawHeader("PAOS")); QCOMPARE(request.rawHeader("PAOS"), QByteArray("ver=\"paosNamespace\"")); QCOMPARE(request.sslConfiguration().ellipticCurves().size(), 5); - QVERIFY(request.sslConfiguration().ellipticCurves().contains(QSslEllipticCurve::fromLongName("prime256v1"))); + QVERIFY(request.sslConfiguration().ellipticCurves().contains(QSslEllipticCurve::fromLongName("prime256v1"_L1))); const auto cipherCount = Env::getSingleton()->getTlsConfig().getCiphers().size(); QCOMPARE(request.sslConfiguration().ciphers().size(), cipherCount); - QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("ECDHE-RSA-AES256-GCM-SHA384"))); + QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("ECDHE-RSA-AES256-GCM-SHA384"_L1))); } void paosRequestPsk() { - QNetworkRequest request(QUrl("https://dummy")); + QNetworkRequest request(QUrl("https://dummy"_L1)); auto reply = Env::getSingleton()->paos(request, "paosNamespace", "content", true, QByteArray()); reply->abort(); QVERIFY(request.hasRawHeader("PAOS")); @@ -82,17 +83,17 @@ class test_NetworkManager QCOMPARE(request.sslConfiguration().ellipticCurves().size(), 0); const auto cipherCount = Env::getSingleton()->getTlsConfig(SecureStorage::TlsSuite::PSK).getCiphers().size(); QCOMPARE(request.sslConfiguration().ciphers().size(), cipherCount); - QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES128-CBC-SHA256"))); - QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES128-GCM-SHA256"))); - QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES256-CBC-SHA384"))); - QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES256-GCM-SHA384"))); + QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES128-CBC-SHA256"_L1))); + QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES128-GCM-SHA256"_L1))); + QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES256-CBC-SHA384"_L1))); + QVERIFY(request.sslConfiguration().ciphers().contains(QSslCipher("RSA-PSK-AES256-GCM-SHA384"_L1))); } void serviceUnavailableEnums() { auto reply = QSharedPointer::create(); - reply->setError(QNetworkReply::ServiceUnavailableError, "dummy error msg"); + reply->setError(QNetworkReply::ServiceUnavailableError, "dummy error msg"_L1); QCOMPARE(NetworkManager::toNetworkError(reply), NetworkManager::NetworkError::ServiceUnavailable); QCOMPARE(NetworkManager::toTrustedChannelStatus(reply), GlobalStatus(GlobalStatus::Code::Workflow_TrustedChannel_ServiceUnavailable, {GlobalStatus::ExternalInformation::LAST_URL, reply->url().toString()})); @@ -136,8 +137,8 @@ class test_NetworkManager networkManager.fireFinished(); }, Qt::QueuedConnection); - auto reply = new MockNetworkReply(); - reply->setError(QNetworkReply::ServiceUnavailableError, "dummy"); + auto* reply = new MockNetworkReply(); + reply->setError(QNetworkReply::ServiceUnavailableError, "dummy"_L1); networkManager.setNextReply(reply); auto context = QSharedPointer::create(); diff --git a/test/qt/network/test_PortFile.cpp b/test/qt/network/test_PortFile.cpp index a35d43a4e..8a39f309e 100644 --- a/test/qt/network/test_PortFile.cpp +++ b/test/qt/network/test_PortFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_PortFile @@ -53,7 +54,7 @@ class test_PortFile if (!usage.isEmpty()) { - QVERIFY(filename.contains(QLatin1Char('.') + usage + QLatin1Char('.'))); + QVERIFY(filename.contains('.'_L1 + usage + '.'_L1)); } } diff --git a/test/qt/network/test_Template.cpp b/test/qt/network/test_Template.cpp index 836302d0c..1e6519104 100644 --- a/test/qt/network/test_Template.cpp +++ b/test/qt/network/test_Template.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -34,7 +35,7 @@ class test_Template void emptyTemplate() { - Template tplt(""); + Template tplt(""_L1); QCOMPARE(tplt.getContextKeys().size(), 0); } @@ -88,15 +89,15 @@ class test_Template void renderErrorPage() { - QString title("test titel"); - QString application_link("application_link"); - QString msg_header("nachrichten header"); - QString msg_header_expl("nachricht"); - QString error_msg("fehler"); - QString error_msg_label("fehler label"); - QString report_header("report_header"); - QString report_link("report_link"); - QString report_button("report_button"); + QString title("test titel"_L1); + QString application_link("application_link"_L1); + QString msg_header("nachrichten header"_L1); + QString msg_header_expl("nachricht"_L1); + QString error_msg("fehler"_L1); + QString error_msg_label("fehler label"_L1); + QString report_header("report_header"_L1); + QString report_link("report_link"_L1); + QString report_button("report_button"_L1); Template tplt = Template::fromFile(QStringLiteral(":/template.html")); @@ -112,7 +113,7 @@ class test_Template const auto& errorPage = tplt.render(); QCOMPARE(tplt.getContextKeys().size(), 9); - QVERIFY(!errorPage.contains(QLatin1Char('$'))); + QVERIFY(!errorPage.contains('$'_L1)); QVERIFY(errorPage.contains(title)); QVERIFY(errorPage.contains(application_link)); QVERIFY(errorPage.contains(msg_header)); @@ -127,13 +128,13 @@ class test_Template void renderAlreadyActivePage() { - QString title("test titel"); - QString application_link("application_link"); - QString msg_header("nachrichten header"); - QString msg_header_expl("nachricht"); - QString content_header("inhalt header"); - QString content_link("inhalt link"); - QString content_button("inhalt button"); + QString title("test titel"_L1); + QString application_link("application_link"_L1); + QString msg_header("nachrichten header"_L1); + QString msg_header_expl("nachricht"_L1); + QString content_header("inhalt header"_L1); + QString content_link("inhalt link"_L1); + QString content_button("inhalt button"_L1); Template tplt = Template::fromFile(QStringLiteral(":/template.html")); @@ -149,7 +150,7 @@ class test_Template QTest::ignoreMessage(QtDebugMsg, "No parameter specified, replace with empty string: \"MESSAGE_SUBHEADER_LABEL\""); const auto& errorPage = tplt.render(); QCOMPARE(tplt.getContextKeys().size(), 9); - QVERIFY(!errorPage.contains(QLatin1Char('$'))); + QVERIFY(!errorPage.contains('$'_L1)); QVERIFY(errorPage.contains(title)); QVERIFY(errorPage.contains(application_link)); QVERIFY(errorPage.contains(msg_header)); diff --git a/test/qt/network/test_TlsChecker.cpp b/test/qt/network/test_TlsChecker.cpp index d06ab8406..0745e3b2e 100644 --- a/test/qt/network/test_TlsChecker.cpp +++ b/test/qt/network/test_TlsChecker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -20,6 +20,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QSsl::KeyAlgorithm) @@ -29,7 +30,7 @@ class test_TlsChecker { Q_OBJECT - QVector certs; + QList certs; static QSslKey createQSslKeyWithHandle(const QByteArray& pPemEncodedEvpPKey) { @@ -95,9 +96,9 @@ class test_TlsChecker void checkCertificateHash() { - QVERIFY(!TlsChecker::checkCertificate(certs.at(0), QCryptographicHash::Algorithm::Sha256, QSet() << "dummy" << "bla bla")); - const QString hash = QStringLiteral("9B:87:54:6D:28:D9:A5:CF:49:C8:B1:AB:3F:C6:0D:EA:63:4B:77:64:44:3A:A8:B1:87:9B:51:44:7E:97:D2:CA").remove(QLatin1Char(':')); - QVERIFY(TlsChecker::checkCertificate(certs.at(0), QCryptographicHash::Algorithm::Sha256, QSet() << "dummy" << hash << "bla bla")); + QVERIFY(!TlsChecker::checkCertificate(certs.at(0), QCryptographicHash::Algorithm::Sha256, QSet() << "dummy"_L1 << "bla bla"_L1)); + const QString hash = QStringLiteral("9B:87:54:6D:28:D9:A5:CF:49:C8:B1:AB:3F:C6:0D:EA:63:4B:77:64:44:3A:A8:B1:87:9B:51:44:7E:97:D2:CA").remove(':'_L1); + QVERIFY(TlsChecker::checkCertificate(certs.at(0), QCryptographicHash::Algorithm::Sha256, QSet() << "dummy"_L1 << hash << "bla bla"_L1)); } @@ -113,6 +114,7 @@ class test_TlsChecker QTest::addColumn("pem"); QTest::addColumn("algorithm"); QTest::addColumn("sufficient"); + QTest::addColumn("infoMap"); /* * openssl ecparam -name secp112r2 -out secp112r2_param.pem @@ -123,8 +125,7 @@ class test_TlsChecker "MDIwEAYHKoZIzj0CAQYFK4EEAAcDHgAEWo89aCax3oUWJho7rFZ1u70WqghvA7Tf\n" "SXXiZw==\n" "-----END PUBLIC KEY-----"); - - QTest::newRow("ec112") << ec112 << QSsl::KeyAlgorithm::Ec << false; + QTest::newRow("ec112") << ec112 << QSsl::KeyAlgorithm::Ec << false << FailureCode::FailureInfoMap {}; /* * openssl ecparam -name secp521r1 -out secp521r1_param.pem @@ -137,7 +138,10 @@ class test_TlsChecker "zBwxpgBC09TO/3D8fS70xVqBX6dzA4lO9MUZCqgBMt2LTFpklUabviy657kcRQ+H\n" "tTAy2sDy+bhcj1UyWlE=\n" "-----END PUBLIC KEY-----"); - QTest::newRow("ec521") << ec521 << QSsl::KeyAlgorithm::Ec << true; + QTest::newRow("ec521") << ec521 << QSsl::KeyAlgorithm::Ec << true << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Ec"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "521"_L1} + }; /* * openssl dsaparam -out dsa768_param.pem 1024 @@ -154,7 +158,10 @@ class test_TlsChecker "b3586zIW9Fdg/Rq4yda8GzMLVAtF540s3k5RmsJvnxPEGXlc3c+wEOKR/iHwPrg4\n" "DNXOVys=\n" "-----END PUBLIC KEY-----"); - QTest::newRow("dsa768") << dsa768 << QSsl::KeyAlgorithm::Dsa << false; + QTest::newRow("dsa768") << dsa768 << QSsl::KeyAlgorithm::Dsa << false << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Dsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "768"_L1} + }; /* * openssl dsaparam -out dsa1024_param.pem 1024 @@ -173,7 +180,10 @@ class test_TlsChecker "1vSGQgpXPK6250pSrx8r8pngr9Qxrt8ElFpLtK+Of6Th/wSTe8COYbXSOP/6Yx7v\n" "6cObyPo7eAmX8Sg=\n" "-----END PUBLIC KEY-----"); - QTest::newRow("dsa1024") << dsa1024 << QSsl::KeyAlgorithm::Dsa << false; + QTest::newRow("dsa1024") << dsa1024 << QSsl::KeyAlgorithm::Dsa << false << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Dsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "1024"_L1} + }; /* * openssl dsaparam -out dsa2048_param.pem 2048 @@ -201,7 +211,49 @@ class test_TlsChecker "foMYlbwM/IzefL1TD2+eBlyV0unSwMIwrvXPTg==\n" "-----END PUBLIC KEY-----\n"); - QTest::newRow("dsa2048") << dsa2048 << QSsl::KeyAlgorithm::Dsa << true; + QTest::newRow("dsa2048") << dsa2048 << QSsl::KeyAlgorithm::Dsa << false << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Dsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "2048"_L1} + }; + + /* + * openssl dsaparam -out dsa3072_param.pem 3072 + * openssl gendsa -out dsa3072_key.pem dsa3072_param.pem + * openssl dsa -in dsa3072_key.pem -pubout -out dsa3072_pubkey.pem + */ + QByteArray dsa3072("-----BEGIN PUBLIC KEY-----\n" + "MIIEwjCCAzUGByqGSM44BAEwggMoAoIBgQCSrktmNWqtkuTQKbZnPkpqVq56/YTD\n" + "Fc5EHJmqWoWWyobwChfWn9bsanUGKYUdSR4Y+PfsmNHkHTytaMPixXC3F9wnA14O\n" + "RaI34Ivf+1CUsGbQH0aVX0GfQHODNsqqLaxS6/sI+Kd4Xye6GPQYdxaetLwo9TEA\n" + "jQYHQd3gClQXdSWgqG5bDCU4ILkUNJ5coP8UOkFJjk/z7EcxcuFOu9OPCExxI9G4\n" + "U3bFBIHjUcFk5cbe0i1YehwAo2HGTUmc/K1XGr50THuMSgcWH/MvuXmY7/mhlnlh\n" + "7udLkT1CsBezbcpA2uG7nkDKBzjGKnOnLkLy0elhJs+OYUjR4PibaR2Mat52tM/K\n" + "lUl5duIhxbb/TWLGvVZYBYNm96O2d8P9XVknlqbH1lrukrouF/yTH9yH/s32npR/\n" + "0R7vjzXmokyj0+4AT33NxzWX1ANzI7H4bALKx4G/hpmyBo+dbWrmaUqANVg3blsf\n" + "fgKUleKK5b7lk8Rj1NHazHk3NbXC1GqKIKsCHQD1k8RPbnqQ0itWdC+kTI0lKIas\n" + "92tw8KVbEq/XAoIBgEMfD1FJgMLzS8p7vrw9G2PvaLB5KHrPDu/9uzsdjWDndyzN\n" + "bJCAdDxWB5hPwVS3S5Hx06weT8xNRNYGomlG3iW+AbWNBxpDyWLKeVl4FvGGBYK+\n" + "j7o3vOEKqfVXNxY8ALQUUWPprEpm6UH/mtqMa6AE26bunx/dDDOCdyoLtP1VcYCG\n" + "Un1QhdZ0jo7Aj5gZDsa09Iluxq4I73WE71/3TFgM0RFInR1mNEFRZkLpn1q+YZ4d\n" + "HJllhVmSZFN1LDJ3SEbTBi6nEy3PvWFFUAsYIJPtoZjFWRLoLkNAwLUTdEijOkXG\n" + "F5okmnjmCUC/tLy3jpwKq8X4PCcU29sV0tDINIF0bf182/P9kmfs5GIVeVubkmlX\n" + "/cGb5A+HfRVALAPPP0NYp0RM28OYKmEdPPs2hrbnh49GVaPEdwSI+Ta75zafTXp0\n" + "wH9s3tzChuVfQT0U+aApz4/Zo4RfjjtxvxM4x0PF7+PvNrX0DXYGnetE1pqaOwpW\n" + "cNXwgNTTCOY5LjXreQOCAYUAAoIBgBoAsSoEmKbDONThiRSFP0edi7Rt+gx2NgRr\n" + "oAVtCi0nqCG3yNOA2IbDRINgWxgw+HHvzazQQQMsJA6UPPkxSLBXHnWCSY8EM3iG\n" + "Uu0qVu8eaq7OFmqeSJdg04LmXGMIqA5L79XMKT06gAuOaMQt8NbB8HXZFTlGgLZZ\n" + "76jdrOTjqoChr9jYUbUNd2v9d+YWNWWP9A7YFbiNkmwbWqc2SbecziD3AUuasrZU\n" + "m6+NJjVo2W44mKmXvYyY/wPBV80qGqAXkosef/Xh1c4kHifGID5sKtWRMT881a0Z\n" + "4UT0LgoNpcLlr6FDUWqfUHlHz6h3EdINueHsdvHoRyfK16HfQzcycJ1wePyDP010\n" + "h2BpFQkvsbB4GlEpg2EpA+8pME1pKOdziNR6OPUY/O7CtSl4NzuKbm0xRSRe8Y0l\n" + "WYgK8nUY1xGKBVmGoUfFhCPgZtz2n7g2EXGZuu80qfiGmmKOyo2QmPWvXeErEPop\n" + "onJVM+lxe8gp7okaGGmRcBgho199Bg==\n" + "-----END PUBLIC KEY-----"); + + QTest::newRow("dsa3072") << dsa3072 << QSsl::KeyAlgorithm::Dsa << true << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Dsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "3072"_L1} + }; /* * openssl genrsa -out rsa1024_key.pem 1024 @@ -213,7 +265,10 @@ class test_TlsChecker "tHKRnCy0sQiCQqmSNmWe4qeLwXslKxm1fqj3/tvrX+0VxDVxXz5jS0HH7hHMdELQ\n" "om/I1IppJFS4IkqEoQIDAQAB\n" "-----END PUBLIC KEY-----"); - QTest::newRow("rsa1024") << rsa1024 << QSsl::KeyAlgorithm::Rsa << false; + QTest::newRow("rsa1024") << rsa1024 << QSsl::KeyAlgorithm::Rsa << false << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Rsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "1024"_L1} + }; /* * openssl genrsa -out rsa2048_key.pem 2048 @@ -228,7 +283,30 @@ class test_TlsChecker "q0hOP6K9hZ7pBZvqLZ0gZdVWqarIf9w/I5yS2QGN9jgJN/oJIKyljlreGuSagST/\n" "5wIDAQAB\n" "-----END PUBLIC KEY-----"); - QTest::newRow("rsa2048") << rsa2048 << QSsl::KeyAlgorithm::Rsa << true; + QTest::newRow("rsa2048") << rsa2048 << QSsl::KeyAlgorithm::Rsa << false << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Rsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "2048"_L1} + }; + + /* + * openssl genrsa -out rsa3072_key.pem 3072 + * openssl rsa -in rsa3072_key.pem -out rsa3072_pubkey.pem -pubout + */ + QByteArray rsa3072("-----BEGIN PUBLIC KEY-----\n" + "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAml5hQRUb0j/3+bnBCoBE\n" + "U75t43Mp+XOS6nwOy/KJgvbpT+oPjKcNOmM0fXAnByCcpbc0avrT9+jNGduzNWU0\n" + "/TAHBJxfWV3+rC/vQ9MFdOEmcmGB6j2pCbiuxJLQX4jAFE0ilSXouisPhDrU1dvJ\n" + "2NlSV2IarjeywfzN77ik3eA69pBKT9B9Vior5TtWwpqIkeC/41vnysFusbWTfn7M\n" + "3BilReDC1k9KBlm5hHQy3GpswnFRABLvsy/hz3yAeeCQyZxUXCKcSahqE+DB/PTy\n" + "nPwOWU9mL7d61WZ6mZjSo+iHHgeVkAsTnuLOr3yo5FG+utMsNxgZeI352ylMeJdj\n" + "bMlbpdqHBtn5sr3OvOt3Hi+vvzDxI1lX0b71vTVriGfgr+o6VUbvfCRy0b8J2/6f\n" + "HSYiIDh/Wf2tz5mKRfpV61k3AIM7aiw5+evFtU7cT/mBH2e5K2rhcywlUiEmiwzP\n" + "8P3+H+HvrctpZoO3J9kIqOoGBz7Q7ocl1HNYMKFh7oy7AgMBAAE=\n" + "-----END PUBLIC KEY-----"); + QTest::newRow("rsa3072") << rsa3072 << QSsl::KeyAlgorithm::Rsa << true << FailureCode::FailureInfoMap { + {FailureCode::Info::Ephemeral_Server_Key_Algorithm, "Rsa"_L1}, + {FailureCode::Info::Ephemeral_Server_Key_Length, "3072"_L1} + }; } @@ -237,11 +315,16 @@ class test_TlsChecker QFETCH(QByteArray, pem); QFETCH(QSsl::KeyAlgorithm, algorithm); QFETCH(bool, sufficient); + QFETCH(FailureCode::FailureInfoMap, infoMap); QSslKey key = createQSslKeyWithHandle(pem); QVERIFY(!key.isNull()); QCOMPARE(key.algorithm(), algorithm); QCOMPARE(TlsChecker::hasValidEphemeralKeyLength(key), sufficient); + if (!infoMap.isEmpty()) + { + QCOMPARE(TlsChecker::getEphemeralKeyInfoMap(key), infoMap); + } } @@ -303,16 +386,20 @@ class test_TlsChecker TlsChecker::logSslConfig(cfg, spawnMessageLogger(network)); QCOMPARE(logSpy.count(), 6); - QVERIFY(logSpy.at(0).at(0).toString().contains("Used session cipher QSslCipher(name=, bits=0, proto=)")); - QVERIFY(logSpy.at(1).at(0).toString().contains("Used session protocol: \"UnknownProtocol\"")); - QVERIFY(logSpy.at(2).at(0).toString().contains("Used ephemeral server key:")); + QVERIFY(logSpy.at(0).at(0).toString().contains("Used session cipher QSslCipher(name=, bits=0, proto=)"_L1)); +#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) + QVERIFY(logSpy.at(1).at(0).toString().contains("Used session protocol: \"UnknownProtocol\""_L1)); +#else + QVERIFY(logSpy.at(1).at(0).toString().contains("Used session protocol: QSsl::UnknownProtocol"_L1)); +#endif + QVERIFY(logSpy.at(2).at(0).toString().contains("Used ephemeral server key:"_L1)); #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 0)) - QVERIFY(logSpy.at(3).at(0).toString().contains("Used peer certificate: QSslCertificate(\"\", \"\", \"1B2M2Y8AsgTpgAmY7PhCfg==\"")); + QVERIFY(logSpy.at(3).at(0).toString().contains("Used peer certificate: QSslCertificate(\"\", \"\", \"1B2M2Y8AsgTpgAmY7PhCfg==\""_L1)); #else - QVERIFY(logSpy.at(3).at(0).toString().contains(R"(Used peer certificate: QSslCertificate(Version="", SerialNumber="", Digest="1B2M2Y8AsgTpgAmY7PhCfg==", Issuer="", Subject="", AlternativeSubjectNames=QMultiMap(), EffectiveDate=QDateTime(Invalid), ExpiryDate=QDateTime(Invalid))")); + QVERIFY(logSpy.at(3).at(0).toString().contains(R"(Used peer certificate: QSslCertificate(Version="", SerialNumber="", Digest="1B2M2Y8AsgTpgAmY7PhCfg==", Issuer="", Subject="", AlternativeSubjectNames=QMultiMap(), EffectiveDate=QDateTime(Invalid), ExpiryDate=QDateTime(Invalid))"_L1)); #endif - QVERIFY(logSpy.at(4).at(0).toString().contains("Used ssl session: \"\"")); - QVERIFY(logSpy.at(5).at(0).toString().contains("Handshake of tls connection done!")); + QVERIFY(logSpy.at(4).at(0).toString().contains("Used ssl session: \"\""_L1)); + QVERIFY(logSpy.at(5).at(0).toString().contains("Handshake of tls connection done!"_L1)); } diff --git a/test/qt/network/test_UrlUtil.cpp b/test/qt/network/test_UrlUtil.cpp index 6a36477c1..6d37d1137 100644 --- a/test/qt/network/test_UrlUtil.cpp +++ b/test/qt/network/test_UrlUtil.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -28,20 +29,20 @@ class test_UrlUtil QTest::addColumn("url2"); QTest::addColumn("valid"); - QTest::newRow("none_80") << QUrl("http://www.web.de/index.html") << QUrl("http://www.web.de:80") << true; - QTest::newRow("8080_8080") << QUrl("http://www.web.de:8080/index.html") << QUrl("http://www.web.de:8080") << true; - QTest::newRow("none_443") << QUrl("https://www.web.de/index.html") << QUrl("https://www.web.de:443") << true; - QTest::newRow("8443_8443") << QUrl("https://www.web.de:8443/index.html") << QUrl("https://www.web.de:8443") << true; + QTest::newRow("none_80") << QUrl("http://www.web.de/index.html"_L1) << QUrl("http://www.web.de:80"_L1) << true; + QTest::newRow("8080_8080") << QUrl("http://www.web.de:8080/index.html"_L1) << QUrl("http://www.web.de:8080"_L1) << true; + QTest::newRow("none_443") << QUrl("https://www.web.de/index.html"_L1) << QUrl("https://www.web.de:443"_L1) << true; + QTest::newRow("8443_8443") << QUrl("https://www.web.de:8443/index.html"_L1) << QUrl("https://www.web.de:8443"_L1) << true; - QTest::newRow("false_8443_8444") << QUrl("https://www.web.de:8443/index.html") << QUrl("https://www.web.de:8444") << false; - QTest::newRow("false_999_999") << QUrl("https://www.web.de:999/index.html") << QUrl("http://www.web.de:999") << false; - QTest::newRow("false_different_domain") << QUrl("http://www.google.de:999/index.html") << QUrl("http://www.web.de:999") << false; + QTest::newRow("false_8443_8444") << QUrl("https://www.web.de:8443/index.html"_L1) << QUrl("https://www.web.de:8444"_L1) << false; + QTest::newRow("false_999_999") << QUrl("https://www.web.de:999/index.html"_L1) << QUrl("http://www.web.de:999"_L1) << false; + QTest::newRow("false_different_domain") << QUrl("http://www.google.de:999/index.html"_L1) << QUrl("http://www.web.de:999"_L1) << false; - QTest::newRow("no_scheme_https_with_port") << QUrl("de.dummy.cz") << QUrl("https://de.dummy.cz:443") << false; - QTest::newRow("no_scheme_https_without_port") << QUrl("de.dummy.cz") << QUrl("https://de.dummy.cz") << false; + QTest::newRow("no_scheme_https_with_port") << QUrl("de.dummy.cz"_L1) << QUrl("https://de.dummy.cz:443"_L1) << false; + QTest::newRow("no_scheme_https_without_port") << QUrl("de.dummy.cz"_L1) << QUrl("https://de.dummy.cz"_L1) << false; - QTest::newRow("no_scheme_http_with_port") << QUrl("de.dummy.cz") << QUrl("http://de.dummy.cz:80") << false; - QTest::newRow("no_scheme_http_without_port") << QUrl("de.dummy.cz") << QUrl("http://de.dummy.cz") << false; + QTest::newRow("no_scheme_http_with_port") << QUrl("de.dummy.cz"_L1) << QUrl("http://de.dummy.cz:80"_L1) << false; + QTest::newRow("no_scheme_http_without_port") << QUrl("de.dummy.cz"_L1) << QUrl("http://de.dummy.cz"_L1) << false; } @@ -55,59 +56,28 @@ class test_UrlUtil } - void majorMinor() - { - const QString URL_PREFIX("https://www.der-pott-kocht.net:8443/index.html"); - const QUrl url(URL_PREFIX); - - // Ok - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Ok, ECardApiResult::Minor::null))).toString(), - URL_PREFIX + "?ResultMajor=ok"); - - // General server error - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Unknown_Error, QString(), ECardApiResult::Origin::Server))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=serverError"); - - // Minors defined in TR-03112-1 and TR-03124-1 2.5.4.2 - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Communication_Error))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=communicationError"); - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::DP_Trusted_Channel_Establishment_Failed))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=trustedChannelEstablishmentFailed"); - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::SAL_Cancellation_by_User))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=cancellationByUser"); - - // No difference between client and server origin - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::SAL_Cancellation_by_User, QString(), ECardApiResult::Origin::Server))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=cancellationByUser"); - - // General client error - QCOMPARE(UrlUtil::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Not_Initialized))).toString(), - URL_PREFIX + "?ResultMajor=error&ResultMinor=clientError"); - } - - void getRequest_data() { QTest::addColumn("url"); QTest::addColumn("type"); - QTest::addColumn("value"); - - QTest::newRow("empty") << QUrl("") << UrlQueryRequest::UNKNOWN << QString(); - QTest::newRow("no query") << QUrl("example.com") << UrlQueryRequest::UNKNOWN << QString(); - QTest::newRow("empty value") << QUrl("?showui=") << UrlQueryRequest::SHOWUI << QString(); - QTest::newRow("showui - l") << QUrl("?showui=test") << UrlQueryRequest::SHOWUI << QString("test"); - QTest::newRow("showui - h") << QUrl("?SHOWUI=test") << UrlQueryRequest::SHOWUI << QString("test"); - QTest::newRow("status - l") << QUrl("?status=test") << UrlQueryRequest::STATUS << QString("test"); - QTest::newRow("status - h") << QUrl("?STATUS=test") << UrlQueryRequest::STATUS << QString("test"); - QTest::newRow("tctokenurl - l") << QUrl("?tctokenurl=test") << UrlQueryRequest::TCTOKENURL << QString("test"); - QTest::newRow("tctokenurl - h") << QUrl("?TCTOKENURL=test") << UrlQueryRequest::TCTOKENURL << QString("test"); - QTest::newRow("multi 1") << QUrl("?showui=test1&status=test2") << UrlQueryRequest::SHOWUI << QString("test1"); - QTest::newRow("multi 2") << QUrl("?status=test1&showui=test2") << UrlQueryRequest::STATUS << QString("test1"); - QTest::newRow("multi 3") << QUrl("?foo=test1&showui=test2") << UrlQueryRequest::SHOWUI << QString("test2"); - QTest::newRow("multi 4") << QUrl("?foo=&showui=test2") << UrlQueryRequest::SHOWUI << QString("test2"); - QTest::newRow("multi 5") << QUrl("?foo=test1&showui=") << UrlQueryRequest::SHOWUI << QString(); - QTest::newRow("multi 6") << QUrl("?showui=&showui=test1") << UrlQueryRequest::SHOWUI << QString(); - QTest::newRow("multi 7") << QUrl("?foo=test1&bar=test2") << UrlQueryRequest::UNKNOWN << QString(); + QTest::addColumn("value"); + + QTest::newRow("empty") << QUrl(""_L1) << UrlQueryRequest::UNKNOWN << QLatin1String(); + QTest::newRow("no query") << QUrl("example.com"_L1) << UrlQueryRequest::UNKNOWN << QLatin1String(); + QTest::newRow("empty value") << QUrl("?showui="_L1) << UrlQueryRequest::SHOWUI << QLatin1String(); + QTest::newRow("showui - l") << QUrl("?showui=test"_L1) << UrlQueryRequest::SHOWUI << "test"_L1; + QTest::newRow("showui - h") << QUrl("?SHOWUI=test"_L1) << UrlQueryRequest::SHOWUI << "test"_L1; + QTest::newRow("status - l") << QUrl("?status=test"_L1) << UrlQueryRequest::STATUS << "test"_L1; + QTest::newRow("status - h") << QUrl("?STATUS=test"_L1) << UrlQueryRequest::STATUS << "test"_L1; + QTest::newRow("tctokenurl - l") << QUrl("?tctokenurl=test"_L1) << UrlQueryRequest::TCTOKENURL << "test"_L1; + QTest::newRow("tctokenurl - h") << QUrl("?TCTOKENURL=test"_L1) << UrlQueryRequest::TCTOKENURL << "test"_L1; + QTest::newRow("multi 1") << QUrl("?showui=test1&status=test2"_L1) << UrlQueryRequest::SHOWUI << "test1"_L1; + QTest::newRow("multi 2") << QUrl("?status=test1&showui=test2"_L1) << UrlQueryRequest::STATUS << "test1"_L1; + QTest::newRow("multi 3") << QUrl("?foo=test1&showui=test2"_L1) << UrlQueryRequest::SHOWUI << "test2"_L1; + QTest::newRow("multi 4") << QUrl("?foo=&showui=test2"_L1) << UrlQueryRequest::SHOWUI << "test2"_L1; + QTest::newRow("multi 5") << QUrl("?foo=test1&showui="_L1) << UrlQueryRequest::SHOWUI << QLatin1String(); + QTest::newRow("multi 6") << QUrl("?showui=&showui=test1"_L1) << UrlQueryRequest::SHOWUI << QLatin1String(); + QTest::newRow("multi 7") << QUrl("?foo=test1&bar=test2"_L1) << UrlQueryRequest::UNKNOWN << QLatin1String(); } @@ -115,12 +85,12 @@ class test_UrlUtil { QFETCH(QUrl, url); QFETCH(UrlQueryRequest, type); - QFETCH(QString, value); + QFETCH(QLatin1String, value); const auto queryUrl = QUrlQuery(url); const auto [parsedType, parsedValue] = UrlUtil::getRequest(queryUrl); - QCOMPARE(type, parsedType); - QCOMPARE(value, parsedValue); + QCOMPARE(parsedType, type); + QCOMPARE(parsedValue, value); } @@ -130,25 +100,27 @@ class test_UrlUtil QTest::addColumn("useTestUri"); QTest::addColumn("enableSimulator"); - QTest::newRow("empty") << QUrl("") << false << false; - QTest::newRow("useTestUri") << QUrl("?useTestUri=true") << true << false; - QTest::newRow("!useTestUri") << QUrl("?useTestUri=false") << false << false; - QTest::newRow("enableSimulator") << QUrl("?enableSimulator=true") << false << true; - QTest::newRow("!enableSimulator") << QUrl("?enableSimulator=false") << false << false; - QTest::newRow("multi 1") << QUrl("?useTestUri=true&enableSimulator=true") << true << true; - QTest::newRow("multi 2") << QUrl("?useTestUri=true&enableSimulator=false") << true << false; + QTest::newRow("empty") << QUrl(""_L1) << false << false; + QTest::newRow("useTestUri") << QUrl("?useTestUri=true"_L1) << true << false; + QTest::newRow("!useTestUri") << QUrl("?useTestUri=false"_L1) << false << false; + QTest::newRow("enableSimulator") << QUrl("?enableSimulator=true"_L1) << false << true; + QTest::newRow("!enableSimulator") << QUrl("?enableSimulator=false"_L1) << false << false; + QTest::newRow("multi 1") << QUrl("?useTestUri=true&enableSimulator=true"_L1) << true << true; + QTest::newRow("multi 2") << QUrl("?useTestUri=true&enableSimulator=false"_L1) << true << false; } void setHiddenSettings() { auto& generalSettings = Env::getSingleton()->getGeneralSettings(); + auto& simulatorSettings = Env::getSingleton()->getSimulatorSettings(); + generalSettings.setDeveloperOptions(true); generalSettings.setUseSelfauthenticationTestUri(false); - generalSettings.setSimulatorEnabled(false); + simulatorSettings.setEnabled(false); QCOMPARE(generalSettings.useSelfAuthTestUri(), false); - QCOMPARE(generalSettings.isSimulatorEnabled(), false); + QCOMPARE(simulatorSettings.isEnabled(), false); QFETCH(QUrl, url); QFETCH(bool, useTestUri); @@ -157,7 +129,7 @@ class test_UrlUtil UrlUtil::setHiddenSettings(QUrlQuery(url)); QCOMPARE(generalSettings.useSelfAuthTestUri(), useTestUri); - QCOMPARE(generalSettings.isSimulatorEnabled(), enableSimulator); + QCOMPARE(simulatorSettings.isEnabled(), enableSimulator); } diff --git a/test/qt/network/test_WifiInfo.cpp b/test/qt/network/test_WifiInfo.cpp index e647e0278..49f7df3e6 100644 --- a/test/qt/network/test_WifiInfo.cpp +++ b/test/qt/network/test_WifiInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ Q_DECLARE_METATYPE(QHostAddress) +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_WifiInfo @@ -26,28 +27,28 @@ class test_WifiInfo QTest::addColumn("isPrivate"); QTest::newRow("empty") << QHostAddress() << false; - QTest::newRow("localhost") << QHostAddress("127.0.0.1") << false; - QTest::newRow("linkLocal") << QHostAddress("169.254.0.1") << false; + QTest::newRow("localhost") << QHostAddress("127.0.0.1"_L1) << false; + QTest::newRow("linkLocal") << QHostAddress("169.254.0.1"_L1) << false; - QTest::newRow("A lower") << QHostAddress("10.0.0.0") << true; - QTest::newRow("A upper") << QHostAddress("10.255.255.255") << true; + QTest::newRow("A lower") << QHostAddress("10.0.0.0"_L1) << true; + QTest::newRow("A upper") << QHostAddress("10.255.255.255"_L1) << true; - QTest::newRow("B lower over") << QHostAddress("172.15.255.255") << false; - QTest::newRow("B lower") << QHostAddress("172.16.0.0") << true; - QTest::newRow("B upper") << QHostAddress("172.31.255.255") << true; - QTest::newRow("B upper over") << QHostAddress("172.32.0.0") << false; + QTest::newRow("B lower over") << QHostAddress("172.15.255.255"_L1) << false; + QTest::newRow("B lower") << QHostAddress("172.16.0.0"_L1) << true; + QTest::newRow("B upper") << QHostAddress("172.31.255.255"_L1) << true; + QTest::newRow("B upper over") << QHostAddress("172.32.0.0"_L1) << false; - QTest::newRow("C lower") << QHostAddress("192.168.0.0") << true; - QTest::newRow("C upper") << QHostAddress("192.168.255.255") << true; + QTest::newRow("C lower") << QHostAddress("192.168.0.0"_L1) << true; + QTest::newRow("C upper") << QHostAddress("192.168.255.255"_L1) << true; - QTest::newRow("fritzbox") << QHostAddress("192.168.178.0") << true; - QTest::newRow("fritzbox range") << QHostAddress("192.168.178.255") << true; + QTest::newRow("fritzbox") << QHostAddress("192.168.178.0"_L1) << true; + QTest::newRow("fritzbox range") << QHostAddress("192.168.178.255"_L1) << true; - QTest::newRow("google dns") << QHostAddress("8.8.8.8") << false; - QTest::newRow("governikus") << QHostAddress("194.31.70.66") << false; - QTest::newRow("telekom") << QHostAddress("91.39.48.2") << false; - QTest::newRow("vodafone mobile") << QHostAddress("100.90.174.1") << false; - QTest::newRow("provider") << QHostAddress("100.64.0.0") << false; + QTest::newRow("google dns") << QHostAddress("8.8.8.8"_L1) << false; + QTest::newRow("governikus") << QHostAddress("194.31.70.66"_L1) << false; + QTest::newRow("telekom") << QHostAddress("91.39.48.2"_L1) << false; + QTest::newRow("vodafone mobile") << QHostAddress("100.90.174.1"_L1) << false; + QTest::newRow("provider") << QHostAddress("100.64.0.0"_L1) << false; } diff --git a/test/qt/secure_storage/test_SecureStorage.cpp b/test/qt/secure_storage/test_SecureStorage.cpp index 43d70fc74..a1747db91 100644 --- a/test/qt/secure_storage/test_SecureStorage.cpp +++ b/test/qt/secure_storage/test_SecureStorage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,6 +17,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(SecureStorage::TlsSuite) @@ -73,14 +74,14 @@ class test_SecureStorage void testGetCVRootCertificatesUnique() { const auto secureStorage = Env::getSingleton(); - static const int EXPECTED_CERTIFICATE_COUNT = 17; + static const int EXPECTED_CERTIFICATE_COUNT = 19; - QVector> cvcs = CVCertificate::fromRaw(secureStorage->getCVRootCertificates(true)) + QList> cvcs = CVCertificate::fromRaw(secureStorage->getCVRootCertificates(true)) + CVCertificate::fromRaw(secureStorage->getCVRootCertificates(false)); const auto count = cvcs.count(); QCOMPARE(count, EXPECTED_CERTIFICATE_COUNT); - const QStringList comments = loadCommentList("_comment_2") + loadCommentList("_comment_4"); + const QStringList comments = loadCommentList("_comment_2"_L1) + loadCommentList("_comment_4"_L1); QCOMPARE(comments.size(), count); // Check that each certificate has a unique car/chr. @@ -113,8 +114,8 @@ class test_SecureStorage QTest::addColumn("isProductive"); QTest::addColumn("commentName"); - QTest::newRow("production") << 5 << true << "_comment_2"; - QTest::newRow("test") << 12 << false << "_comment_4"; + QTest::newRow("production") << 6 << true << "_comment_2"; + QTest::newRow("test") << 13 << false << "_comment_4"; } @@ -126,7 +127,7 @@ class test_SecureStorage const auto secureStorage = Env::getSingleton(); - QVector> cvcs = CVCertificate::fromRaw(secureStorage->getCVRootCertificates(isProductive)); + QList> cvcs = CVCertificate::fromRaw(secureStorage->getCVRootCertificates(isProductive)); QCOMPARE(cvcs.count(), certificateCount); const QStringList& comments = loadCommentList(commentName); @@ -300,8 +301,8 @@ class test_SecureStorage void testLocalIfdConfig() { const auto secureStorage = Env::getSingleton(); - QCOMPARE(secureStorage->getLocalIfdPackageName(), "com.governikus.ausweisapp2.dev"); - QCOMPARE(secureStorage->getLocalIfdMinVersion(), "1.100.0"); + QCOMPARE(secureStorage->getLocalIfdPackageName(), "com.governikus.ausweisapp2.dev"_L1); + QCOMPARE(secureStorage->getLocalIfdMinVersion(), "1.100.0"_L1); QCOMPARE(secureStorage->getLocalIfdMinPskSize(), 256); const auto& certificateHashes = secureStorage->getLocalIfdAllowedCertificateHashes(); @@ -315,28 +316,18 @@ class test_SecureStorage void testAppcast() { const auto secureStorage = Env::getSingleton(); - QCOMPARE(secureStorage->getAppcastUpdateUrl(), QUrl("https://updates.autentapp.de/AppcastInfo.json")); - QCOMPARE(secureStorage->getAppcastBetaUpdateUrl(), QUrl("https://updates.autentapp.de/beta/AppcastInfo.json")); + QCOMPARE(secureStorage->getAppcastUpdateUrl(), QUrl("https://updates.autentapp.de/AppcastInfo.json"_L1)); + QCOMPARE(secureStorage->getAppcastBetaUpdateUrl(), QUrl("https://updates.autentapp.de/beta/AppcastInfo.json"_L1)); } - void testMinStaticKeySizes() + void testMinKeySizes() { const auto secureStorage = Env::getSingleton(); - QCOMPARE(secureStorage->getMinimumStaticKeySize(QSsl::KeyAlgorithm::Rsa), 2000); - QCOMPARE(secureStorage->getMinimumStaticKeySize(QSsl::KeyAlgorithm::Dsa), 2000); - QCOMPARE(secureStorage->getMinimumStaticKeySize(QSsl::KeyAlgorithm::Dh), 2000); - QCOMPARE(secureStorage->getMinimumStaticKeySize(QSsl::KeyAlgorithm::Ec), 250); - } - - - void testMinEphemeralKeySizes() - { - const auto secureStorage = Env::getSingleton(); - QCOMPARE(secureStorage->getMinimumEphemeralKeySize(QSsl::KeyAlgorithm::Rsa), 2000); - QCOMPARE(secureStorage->getMinimumEphemeralKeySize(QSsl::KeyAlgorithm::Dsa), 2000); - QCOMPARE(secureStorage->getMinimumEphemeralKeySize(QSsl::KeyAlgorithm::Dh), 2000); - QCOMPARE(secureStorage->getMinimumEphemeralKeySize(QSsl::KeyAlgorithm::Ec), 250); + QCOMPARE(secureStorage->getMinimumKeySize(QSsl::KeyAlgorithm::Rsa), 3000); + QCOMPARE(secureStorage->getMinimumKeySize(QSsl::KeyAlgorithm::Dsa), 3000); + QCOMPARE(secureStorage->getMinimumKeySize(QSsl::KeyAlgorithm::Dh), 3000); + QCOMPARE(secureStorage->getMinimumKeySize(QSsl::KeyAlgorithm::Ec), 250); } @@ -381,41 +372,41 @@ class test_SecureStorage { const auto secureStorage = Env::getSingleton(); const auto& ciphersForwardSecrecy = secureStorage->getTlsConfig().getCiphers(); - QCOMPARE(ciphersForwardSecrecy.first(), QSslCipher("ECDHE-ECDSA-AES256-GCM-SHA384")); - QCOMPARE(ciphersForwardSecrecy.last(), QSslCipher("DHE-RSA-AES128-SHA256")); + QCOMPARE(ciphersForwardSecrecy.first(), QSslCipher("ECDHE-ECDSA-AES256-GCM-SHA384"_L1)); + QCOMPARE(ciphersForwardSecrecy.last(), QSslCipher("DHE-RSA-AES128-SHA256"_L1)); const auto& ciphersPsk = secureStorage->getTlsConfig(SecureStorage::TlsSuite::PSK).getCiphers(); QVERIFY(ciphersPsk.count() > 0); - QCOMPARE(ciphersPsk.first(), QSslCipher("RSA-PSK-AES256-GCM-SHA384")); - QCOMPARE(ciphersPsk.last(), QSslCipher("RSA-PSK-AES256-CBC-SHA")); + QCOMPARE(ciphersPsk.first(), QSslCipher("RSA-PSK-AES256-GCM-SHA384"_L1)); + QCOMPARE(ciphersPsk.last(), QSslCipher("RSA-PSK-AES256-CBC-SHA"_L1)); const auto& ciphersEc = secureStorage->getTlsConfig().getEllipticCurves(); QCOMPARE(ciphersEc.count(), 5); - QCOMPARE(ciphersEc.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1")); - QCOMPARE(ciphersEc.last(), QSslEllipticCurve::fromLongName("prime256v1")); + QCOMPARE(ciphersEc.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1"_L1)); + QCOMPARE(ciphersEc.last(), QSslEllipticCurve::fromLongName("prime256v1"_L1)); const auto& ciphersEcRemoteReader = secureStorage->getTlsConfigRemoteIfd().getEllipticCurves(); QCOMPARE(ciphersEcRemoteReader.count(), 5); - QCOMPARE(ciphersEcRemoteReader.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1")); - QCOMPARE(ciphersEcRemoteReader.last(), QSslEllipticCurve::fromLongName("prime256v1")); + QCOMPARE(ciphersEcRemoteReader.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1"_L1)); + QCOMPARE(ciphersEcRemoteReader.last(), QSslEllipticCurve::fromLongName("prime256v1"_L1)); const auto& ciphersEcRemoteReaderPairing = secureStorage->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getEllipticCurves(); QCOMPARE(ciphersEcRemoteReaderPairing.count(), 0); const auto& ciphersRemoteReader = secureStorage->getTlsConfigRemoteIfd(SecureStorage::TlsSuite::PSK).getCiphers(); QVERIFY(ciphersRemoteReader.count() > 0); - QCOMPARE(ciphersRemoteReader.first(), QSslCipher("RSA-PSK-AES256-GCM-SHA384")); - QCOMPARE(ciphersRemoteReader.last(), QSslCipher("RSA-PSK-AES256-CBC-SHA")); + QCOMPARE(ciphersRemoteReader.first(), QSslCipher("RSA-PSK-AES256-GCM-SHA384"_L1)); + QCOMPARE(ciphersRemoteReader.last(), QSslCipher("RSA-PSK-AES256-CBC-SHA"_L1)); const auto& localIfdConfig = secureStorage->getTlsConfigLocalIfd(); const auto& ciphersEcLocalIfd = localIfdConfig.getEllipticCurves(); QCOMPARE(ciphersEcLocalIfd.count(), 5); - QCOMPARE(ciphersEcLocalIfd.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1")); - QCOMPARE(ciphersEcLocalIfd.last(), QSslEllipticCurve::fromLongName("prime256v1")); + QCOMPARE(ciphersEcLocalIfd.first(), QSslEllipticCurve::fromLongName("brainpoolP512r1"_L1)); + QCOMPARE(ciphersEcLocalIfd.last(), QSslEllipticCurve::fromLongName("prime256v1"_L1)); const auto& ciphersLocalIfd = localIfdConfig.getCiphers(); QVERIFY(ciphersLocalIfd.count() == 2); - QCOMPARE(ciphersLocalIfd.first(), QSslCipher("ECDHE-PSK-AES128-CBC-SHA256")); - QCOMPARE(ciphersLocalIfd.last(), QSslCipher("ECDHE-PSK-AES256-CBC-SHA384")); + QCOMPARE(ciphersLocalIfd.first(), QSslCipher("ECDHE-PSK-AES128-CBC-SHA256"_L1)); + QCOMPARE(ciphersLocalIfd.last(), QSslCipher("ECDHE-PSK-AES256-CBC-SHA384"_L1)); } @@ -464,6 +455,19 @@ class test_SecureStorage } + void testSizesIfd() + { + const auto secureStorage = Env::getSingleton(); + + QCOMPARE(secureStorage->getIfdCreateSize(), 3072); + QCOMPARE(secureStorage->getMinimumIfdKeySize(QSsl::KeyAlgorithm::Rsa), 2000); + QCOMPARE(secureStorage->getMinimumIfdKeySize(QSsl::KeyAlgorithm::Dsa), 2000); + QCOMPARE(secureStorage->getMinimumIfdKeySize(QSsl::KeyAlgorithm::Dh), 2000); + QCOMPARE(secureStorage->getMinimumIfdKeySize(QSsl::KeyAlgorithm::Ec), 250); + + } + + }; QTEST_GUILESS_MAIN(test_SecureStorage) diff --git a/test/qt/secure_storage/test_TlsConfiguration.cpp b/test/qt/secure_storage/test_TlsConfiguration.cpp index ca4cfe562..5546d8322 100644 --- a/test/qt/secure_storage/test_TlsConfiguration.cpp +++ b/test/qt/secure_storage/test_TlsConfiguration.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,7 +11,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -68,8 +68,8 @@ class test_TlsConfiguration mTlsConfiguration.load(QJsonDocument::fromJson(config).object()); QCOMPARE(mTlsConfiguration.getCiphers().size(), 2); - QCOMPARE(mTlsConfiguration.getCiphers().at(0), QSslCipher("ECDHE-ECDSA-AES256-GCM-SHA384")); - QCOMPARE(mTlsConfiguration.getCiphers().at(1), QSslCipher("DHE-RSA-AES256-SHA256")); + QCOMPARE(mTlsConfiguration.getCiphers().at(0), QSslCipher("ECDHE-ECDSA-AES256-GCM-SHA384"_L1)); + QCOMPARE(mTlsConfiguration.getCiphers().at(1), QSslCipher("DHE-RSA-AES256-SHA256"_L1)); } @@ -82,8 +82,8 @@ class test_TlsConfiguration mTlsConfiguration.load(QJsonDocument::fromJson(config).object()); QCOMPARE(mTlsConfiguration.getEllipticCurves().size(), 2); - QCOMPARE(mTlsConfiguration.getEllipticCurves().at(0), QSslEllipticCurve::fromLongName("brainpoolP512r1")); - QCOMPARE(mTlsConfiguration.getEllipticCurves().at(1), QSslEllipticCurve::fromLongName("brainpoolP384r1")); + QCOMPARE(mTlsConfiguration.getEllipticCurves().at(0), QSslEllipticCurve::fromLongName("brainpoolP512r1"_L1)); + QCOMPARE(mTlsConfiguration.getEllipticCurves().at(1), QSslEllipticCurve::fromLongName("brainpoolP384r1"_L1)); } diff --git a/test/qt/services/test_AppUpdatData.cpp b/test/qt/services/test_AppUpdatData.cpp index 6d5b3451d..919797037 100644 --- a/test/qt/services/test_AppUpdatData.cpp +++ b/test/qt/services/test_AppUpdatData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_AppUpdatData @@ -25,7 +26,7 @@ class test_AppUpdatData data.setChecksum(QByteArray("broken"), QCryptographicHash::Sha1); QVERIFY(!data.isChecksumValid()); - const QString dummyFile(":/card/efCardAccess.hex"); + const QString dummyFile(":/card/efCardAccess.hex"_L1); QTest::ignoreMessage(QtDebugMsg, "Verify checksum with algorithm: QCryptographicHash::Sha1"); data.setUpdatePackagePath(dummyFile); QVERIFY(!data.isChecksumValid()); diff --git a/test/qt/services/test_AppUpdatr.cpp b/test/qt/services/test_AppUpdatr.cpp index f19478e14..69ff87f27 100644 --- a/test/qt/services/test_AppUpdatr.cpp +++ b/test/qt/services/test_AppUpdatr.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -62,6 +62,7 @@ const char* test_checksum = "85b1e5ba7c499ab30959febf8d9ea39d08c863617995d7dce20 } // namespace +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_AppUpdatr @@ -109,7 +110,7 @@ class test_AppUpdatr void setJsonItemField(QJsonDocument& pDocument, const QString& pField, const QString& pValue) { - auto itemArray = pDocument.object()["items"].toArray(); + auto itemArray = pDocument.object()["items"_L1].toArray(); int i = 0; for (auto item : itemArray) { @@ -119,7 +120,7 @@ class test_AppUpdatr i++; } QJsonObject newRootObject; - newRootObject[QLatin1String("items")] = itemArray; + newRootObject["items"_L1] = itemArray; pDocument.setObject(newRootObject); } @@ -127,27 +128,27 @@ class test_AppUpdatr QJsonValue getJsonItemField(QJsonDocument& pDocument, const QString& pField) { #ifdef Q_OS_WIN - QString platform = "win"; + const auto platform = "win"_L1; #endif #ifdef Q_OS_MACOS - QString platform = "mac"; + const auto platform = "mac"_L1; #endif #if !defined(Q_OS_MACOS) && !defined(Q_OS_WIN) - QString platform = "src"; + const auto platform = "src"_L1; #endif - auto itemArray = pDocument.object()["items"].toArray(); + auto itemArray = pDocument.object()["items"_L1].toArray(); for (auto item : itemArray) { QJsonObject itemObject = item.toObject(); - if (itemObject["platform"] == platform) + if (itemObject["platform"_L1] == platform) { return itemObject[pField]; } } - return QString("NO_INFO"); + return "NO_INFO"_L1; } private Q_SLOTS: @@ -157,7 +158,7 @@ class test_AppUpdatr mAppCastLocation = mAppUpdater.mAppUpdateJsonUrl; mJsonDocument = QJsonDocument::fromJson(test_jsonData); - mReleaseNoteLocation = getJsonItemField(mJsonDocument, "notes").toString(); + mReleaseNoteLocation = getJsonItemField(mJsonDocument, "notes"_L1).toString(); } @@ -167,10 +168,10 @@ class test_AppUpdatr mDownloader.setTestData(mAppCastLocation, test_jsonData); mDownloader.setTestData(mReleaseNoteLocation, test_releaseNotes); - mAppPackage = getJsonItemField(mJsonDocument, "url").toString(); + mAppPackage = getJsonItemField(mJsonDocument, "url"_L1).toString(); mDownloader.setTestData(mAppPackage, test_package); - mChecksum = getJsonItemField(mJsonDocument, "checksum").toString(); + mChecksum = getJsonItemField(mJsonDocument, "checksum"_L1).toString(); QByteArray checksum(test_checksum); checksum += mAppPackage.fileName().toUtf8(); mDownloader.setTestData(mChecksum, checksum); @@ -226,7 +227,7 @@ class test_AppUpdatr QVERIFY(!mAppUpdater.getUpdateData().isChecksumValid()); QCOMPARE(mAppUpdater.getUpdateData().getChecksum(), QByteArray("broken")); - const QString expectedDest = QDir::toNativeSeparators(dir.path() + QLatin1Char('/') + mAppPackage.fileName()); + const QString expectedDest = QDir::toNativeSeparators(dir.path() + '/'_L1 + mAppPackage.fileName()); QCOMPARE(mAppUpdater.getUpdateData().getUpdatePackagePath(), expectedDest); QVERIFY(QFile::exists(expectedDest)); } @@ -253,7 +254,7 @@ class test_AppUpdatr const QByteArray expectedChecksum("85b1e5ba7c499ab30959febf8d9ea39d08c863617995d7dce20ddc42cd0eb291"); QCOMPARE(mAppUpdater.getUpdateData().getChecksum(), expectedChecksum); - const QString expectedDest = QDir::toNativeSeparators(dir.path() + QLatin1Char('/') + mAppPackage.fileName()); + const QString expectedDest = QDir::toNativeSeparators(dir.path() + '/'_L1 + mAppPackage.fileName()); QCOMPARE(mAppUpdater.getUpdateData().getUpdatePackagePath(), expectedDest); QVERIFY(QFile::exists(expectedDest)); @@ -261,10 +262,10 @@ class test_AppUpdatr // trigger re-download but use downloaded package spyDownload.clear(); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Checksum file downloaded successfully: .*")); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Checksum file downloaded successfully: .*"_L1)); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Verify checksum with algorithm: QCryptographicHash::Sha256"); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package already exists: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package already exists: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Re-use valid package..."); QVERIFY(mAppUpdater.downloadUpdate()); checkDlResult(spyDownload, GlobalStatus::Code::No_Error); @@ -277,14 +278,14 @@ class test_AppUpdatr // trigger re-download and replace package spyDownload.clear(); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Checksum file downloaded successfully: .*")); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Checksum file downloaded successfully: .*"_L1)); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Verify checksum with algorithm: QCryptographicHash::Sha256"); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package already exists: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package already exists: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Checksum of package invalid..."); QTest::ignoreMessage(QtDebugMsg, "Download package..."); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package downloaded successfully: .*")); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Package downloaded successfully: .*"_L1)); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Data written to file: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Verify checksum with algorithm: QCryptographicHash::Sha256"); QVERIFY(mAppUpdater.downloadUpdate()); checkDlResult(spyDownload, GlobalStatus::Code::No_Error); @@ -302,12 +303,12 @@ class test_AppUpdatr checkResult(spy, true, GlobalStatus::Code::No_Error); AppUpdateData updateData = mAppUpdater.getUpdateData(); - QCOMPARE(updateData.getDate(), QDateTime::fromString(getJsonItemField(document, "date").toString(), Qt::ISODate)); - QCOMPARE(updateData.getVersion(), getJsonItemField(document, "version").toString()); - QCOMPARE(updateData.getNotesUrl(), QUrl(getJsonItemField(document, "notes").toString())); - QCOMPARE(updateData.getUrl(), QUrl(getJsonItemField(document, "url").toString())); - QCOMPARE(updateData.getChecksumUrl(), QUrl(getJsonItemField(document, "checksum").toString())); - QCOMPARE(updateData.getSize(), getJsonItemField(document, "size").toInt()); + QCOMPARE(updateData.getDate(), QDateTime::fromString(getJsonItemField(document, "date"_L1).toString(), Qt::ISODate)); + QCOMPARE(updateData.getVersion(), getJsonItemField(document, "version"_L1).toString()); + QCOMPARE(updateData.getNotesUrl(), QUrl(getJsonItemField(document, "notes"_L1).toString())); + QCOMPARE(updateData.getUrl(), QUrl(getJsonItemField(document, "url"_L1).toString())); + QCOMPARE(updateData.getChecksumUrl(), QUrl(getJsonItemField(document, "checksum"_L1).toString())); + QCOMPARE(updateData.getSize(), getJsonItemField(document, "size"_L1).toInt()); QVERIFY(mAppUpdater.getUpdateData().getNotes() != QString()); } @@ -337,34 +338,10 @@ class test_AppUpdatr } - void testSkipCurrentVersion() - { - QSignalSpy spy(&mAppUpdater, &AppUpdater::fireAppcastCheckFinished); - mAppUpdater.skipVersion(getJsonItemField(mJsonDocument, "version").toString()); - - QVERIFY(mAppUpdater.checkAppUpdate()); - - checkResult(spy, false, GlobalStatus::Code::No_Error); - mAppUpdater.skipVersion(""); - } - - - void testSkipCurrentVersionButDoNotRespectIt() - { - QSignalSpy spy(&mAppUpdater, &AppUpdater::fireAppcastCheckFinished); - mAppUpdater.skipVersion(getJsonItemField(mJsonDocument, "version").toString()); - - QVERIFY(mAppUpdater.checkAppUpdate(true)); - - checkResult(spy, true, GlobalStatus::Code::No_Error); - mAppUpdater.skipVersion(""); - } - - void testNoNewVersion() { QJsonDocument document = QJsonDocument::fromJson(test_jsonData); - setJsonItemField(document, QString("version"), QString(" ")); + setJsonItemField(document, "version"_L1, " "_L1); QByteArray newJson = document.toJson(); mDownloader.setTestData(mAppCastLocation, newJson); @@ -391,7 +368,7 @@ class test_AppUpdatr void testReleaseNoteDownloadFailed() { QJsonDocument document = QJsonDocument::fromJson(test_jsonData); - setJsonItemField(document, QString("notes"), QString("httb://notarealurl.org")); + setJsonItemField(document, "notes"_L1, "httb://notarealurl.org"_L1); mDownloader.setTestData(mAppCastLocation, document.toJson()); QSignalSpy spy(&mAppUpdater, &AppUpdater::fireAppcastCheckFinished); @@ -406,7 +383,7 @@ class test_AppUpdatr void testCheckSumDownloadFailed() { QJsonDocument document = QJsonDocument::fromJson(test_jsonData); - setJsonItemField(document, QString("checksum"), QString("httb://notarealurl.org/checksum")); + setJsonItemField(document, "checksum"_L1, "httb://notarealurl.org/checksum"_L1); mDownloader.setTestData(mAppCastLocation, document.toJson()); QSignalSpy spy(&mAppUpdater, &AppUpdater::fireAppcastCheckFinished); @@ -424,7 +401,7 @@ class test_AppUpdatr void testPackageDownloadFailed() { QJsonDocument document = QJsonDocument::fromJson(test_jsonData); - setJsonItemField(document, QString("url"), QString("httb://notarealurl.org/nonexisting")); + setJsonItemField(document, "url"_L1, "httb://notarealurl.org/nonexisting"_L1); mDownloader.setTestData(mAppCastLocation, document.toJson()); QSignalSpy spy(&mAppUpdater, &AppUpdater::fireAppcastCheckFinished); diff --git a/test/qt/settings/test_Backup.mm b/test/qt/settings/test_Backup.mm index cb219c54e..cd2549b57 100644 --- a/test/qt/settings/test_Backup.mm +++ b/test/qt/settings/test_Backup.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "Backup.h" diff --git a/test/qt/settings/test_GeneralSettings.cpp b/test/qt/settings/test_GeneralSettings.cpp index 3e0c732d6..6be5162a2 100644 --- a/test/qt/settings/test_GeneralSettings.cpp +++ b/test/qt/settings/test_GeneralSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -20,6 +20,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_GeneralSettings @@ -48,7 +49,7 @@ class test_GeneralSettings // init ctor of Singleton, otherwise the testcases are not // stable. There could be differences between a run of a // single testcase and the whole testsuite. - Env::getSingleton()->getGeneralSettings(); + Q_UNUSED(Env::getSingleton()->getGeneralSettings()) } @@ -72,6 +73,30 @@ class test_GeneralSettings } + void testAutoRedirectAfterAuthentication() + { + auto& settings = Env::getSingleton()->getGeneralSettings(); + QSignalSpy spy(&settings, &GeneralSettings::fireSettingsChanged); + QCOMPARE(settings.isAutoRedirectAfterAuthentication(), true); + + settings.setAutoRedirectAfterAuthentication(false); + QCOMPARE(spy.size(), 1); + QCOMPARE(settings.isAutoRedirectAfterAuthentication(), false); + + settings.setAutoRedirectAfterAuthentication(false); + QCOMPARE(spy.size(), 1); + QCOMPARE(settings.isAutoRedirectAfterAuthentication(), false); + + settings.setAutoRedirectAfterAuthentication(true); + QCOMPARE(spy.size(), 2); + QCOMPARE(settings.isAutoRedirectAfterAuthentication(), true); + + settings.setAutoRedirectAfterAuthentication(true); + QCOMPARE(spy.size(), 2); + QCOMPARE(settings.isAutoRedirectAfterAuthentication(), true); + } + + void testAutoCheck() { auto& settings = Env::getSingleton()->getGeneralSettings(); @@ -152,32 +177,20 @@ class test_GeneralSettings const auto& windowsBootUpSettings = AutoStart::getRegistryStore(); windowsBootUpSettings->setValue(QCoreApplication::applicationName(), QStringLiteral("dummy")); - QCOMPARE(windowsBootUpSettings->value(QCoreApplication::applicationName(), QString()).toString(), QString("dummy")); + QCOMPARE(windowsBootUpSettings->value(QCoreApplication::applicationName(), QString()).toString(), "dummy"_L1); QVERIFY(!AutoStart::enabled()); - QCOMPARE(windowsBootUpSettings->value(QCoreApplication::applicationName(), QString()).toString(), QString("dummy")); + QCOMPARE(windowsBootUpSettings->value(QCoreApplication::applicationName(), QString()).toString(), "dummy"_L1); QCOMPARE(AutoStart::set(true), !useSdkMode); QCOMPARE(AutoStart::enabled(), !useSdkMode); - const auto& expectedPath = useSdkMode ? QString("dummy") : AutoStart::appPath(); + const auto& expectedPath = useSdkMode ? "dummy"_L1 : AutoStart::appPath(); QCOMPARE(windowsBootUpSettings->value(QCoreApplication::applicationName(), QString()).toString(), expectedPath); } #endif - void testUseScreenKeyboard() - { - auto& settings = Env::getSingleton()->getGeneralSettings(); - bool initial = settings.isUseScreenKeyboard(); - - settings.setUseScreenKeyboard(!initial); - QCOMPARE(settings.isUseScreenKeyboard(), !initial); - - settings.setUseScreenKeyboard(initial); - QCOMPARE(settings.isUseScreenKeyboard(), initial); - } - void testVisualPrivacy() { @@ -255,10 +268,9 @@ class test_GeneralSettings QCOMPARE(settings.isDeveloperOptions(), false); QCOMPARE(settings.isDeveloperMode(), false); QCOMPARE(settings.useSelfAuthTestUri(), false); - QCOMPARE(settings.isUseScreenKeyboard(), false); QCOMPARE(settings.isEnableCanAllowed(), false); QCOMPARE(settings.isSkipRightsOnCanAllowed(), false); - QCOMPARE(settings.getStartupModule(), ""); + QCOMPARE(settings.getStartupModule(), ""_L1); QCOMPARE(settings.isShowInAppNotifications(), getNotificationsOsDefault()); QCOMPARE(settings.isRemindUserToClose(), true); QCOMPARE(settings.isTransportPinReminder(), true); @@ -529,6 +541,32 @@ class test_GeneralSettings } + void testAnimations() + { + auto& settings = Env::getSingleton()->getGeneralSettings(); + QSignalSpy animationsSpy(&settings, &GeneralSettings::fireUseAnimationsChanged); + + QCOMPARE(animationsSpy.count(), 0); + QCOMPARE(settings.isUseAnimations(), true); + + settings.setUseAnimations(false); + QCOMPARE(animationsSpy.count(), 1); + QCOMPARE(settings.isUseAnimations(), false); + + settings.setUseAnimations(false); + QCOMPARE(animationsSpy.count(), 1); + QCOMPARE(settings.isUseAnimations(), false); + + settings.setUseAnimations(true); + QCOMPARE(animationsSpy.count(), 2); + QCOMPARE(settings.isUseAnimations(), true); + + settings.setUseAnimations(true); + QCOMPARE(animationsSpy.count(), 2); + QCOMPARE(settings.isUseAnimations(), true); + } + + void testDarkMode() { auto& settings = Env::getSingleton()->getGeneralSettings(); diff --git a/test/qt/settings/test_KeyPair.cpp b/test/qt/settings/test_KeyPair.cpp index c850652a7..ac9baffd2 100644 --- a/test/qt/settings/test_KeyPair.cpp +++ b/test/qt/settings/test_KeyPair.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,13 +8,18 @@ #include "KeyPair.h" +#include "ResourceLoader.h" +#include "SecureStorage.h" #include "TlsChecker.h" #include +#include +#include #include using namespace governikus; +Q_DECLARE_METATYPE(KeyPair) class test_KeyPair : public QObject @@ -24,15 +29,26 @@ class test_KeyPair private: KeyPair pair1 = KeyPair::generate(); KeyPair pair2 = KeyPair::generate(); + const int defaultDeriveSize = 3072; private Q_SLOTS: + void initTestCase() + { + ResourceLoader::getInstance().init(); + } + + void validKey_data() { QTest::addColumn("algorithm"); QTest::addColumn("size"); QTest::addColumn("curve"); - QTest::newRow("RSA") << QSsl::Rsa << 2048 << QLatin1String(); + QTest::newRow("RSA 2048") << QSsl::Rsa << 2048 << QLatin1String(); +#ifndef Q_CC_MSVC + QTest::newRow("RSA 3072") << QSsl::Rsa << 3072 << QLatin1String(); + QTest::newRow("RSA 4096") << QSsl::Rsa << 4096 << QLatin1String(); +#endif QTest::newRow("prime256v1") << QSsl::Ec << 256 << QLatin1String("prime256v1"); QTest::newRow("secp384r1") << QSsl::Ec << 384 << QLatin1String("secp384r1"); QTest::newRow("brainpoolP512r1") << QSsl::Ec << 512 << QLatin1String("brainpoolP512r1"); @@ -45,7 +61,7 @@ class test_KeyPair QFETCH(int, size); QFETCH(QLatin1String, curve); - KeyPair pair = KeyPair::generate(curve.data()); + KeyPair pair = curve.isNull() ? KeyPair::generate(size) : KeyPair::generate(curve.data()); QVERIFY(pair.isValid()); const auto& key = pair.getKey(); QVERIFY(!key.isNull()); @@ -71,7 +87,9 @@ class test_KeyPair QTest::addColumn("size"); QTest::addColumn("curve"); - QTest::newRow("RSA") << QSsl::Rsa << 2048 << QLatin1String(); +#ifndef Q_CC_MSVC + QTest::newRow("RSA") << QSsl::Rsa << 3072 << QLatin1String(); +#endif QTest::newRow("prime256v1") << QSsl::Ec << 256 << QLatin1String("prime256v1"); QTest::newRow("secp384r1") << QSsl::Ec << 384 << QLatin1String("secp384r1"); QTest::newRow("brainpoolP512r1") << QSsl::Ec << 512 << QLatin1String("brainpoolP512r1"); @@ -84,7 +102,7 @@ class test_KeyPair QFETCH(int, size); QFETCH(QLatin1String, curve); - KeyPair pair = KeyPair::generate(curve.data()); + KeyPair pair = curve.isNull() ? KeyPair::generate(size) : KeyPair::generate(curve.data()); QVERIFY(pair.isValid()); const auto& cert = pair.getCertificate(); QVERIFY(!cert.isNull()); @@ -105,6 +123,7 @@ class test_KeyPair QCOMPARE(key.length(), size); QCOMPARE(key.algorithm(), algorithm); QCOMPARE(key.type(), QSsl::PublicKey); + QVERIFY(Env::getSingleton()->isValid()); QVERIFY(TlsChecker::hasValidCertificateKeyLength(cert)); QVERIFY(cert.expiryDate().isValid()); @@ -124,6 +143,97 @@ class test_KeyPair } + void certificateChain() + { + const KeyPair derived = KeyPair::generate(defaultDeriveSize, pair1.getKey().toPem(), pair1.getCertificate().toPem()); + + QVERIFY(derived.isValid()); + QVERIFY(!derived.getCertificate().isNull()); + const auto& derivedCert = derived.getCertificate(); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::SerialNumber).size(), 1); + QCOMPARE(pair1.getCertificate().issuerInfo(QSslCertificate::SerialNumber).size(), 1); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::SerialNumber).at(0), + pair1.getCertificate().issuerInfo(QSslCertificate::SerialNumber).at(0)); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::CommonName).size(), 1); + QCOMPARE(pair1.getCertificate().issuerInfo(QSslCertificate::CommonName).size(), 1); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::CommonName).at(0), + pair1.getCertificate().issuerInfo(QSslCertificate::CommonName).at(0)); + + QVERIFY(!derivedCert.isSelfSigned()); + } + + + void sslSocket_data() + { + QTest::addColumn("serverPair"); + QTest::addColumn("clientPair"); + QTest::addColumn>("serverCaStore"); + QTest::addColumn>("clientCaStore"); + + const KeyPair derived1 = KeyPair::generate(defaultDeriveSize, pair1.getKey().toPem(), pair1.getCertificate().toPem()); + const KeyPair derived2 = KeyPair::generate(defaultDeriveSize, pair2.getKey().toPem(), pair2.getCertificate().toPem()); + + QTest::newRow("root as truststore") << derived1 << derived2 + << QList({pair2.getCertificate()}) + << QList({pair1.getCertificate() + }); + + QTest::newRow("chain as truststore") << derived1 << derived2 + << QList({derived2.getCertificate(), pair2.getCertificate()}) + << QList({derived1.getCertificate(), pair1.getCertificate()}); + + } + + + void sslSocket() + { + QFETCH(KeyPair, serverPair); + QFETCH(KeyPair, clientPair); + QFETCH(QList, serverCaStore); + QFETCH(QList, clientCaStore); + + QSslConfiguration configServer; + configServer.setPrivateKey(serverPair.getKey()); + configServer.setLocalCertificate(serverPair.getCertificate()); + configServer.setCaCertificates(serverCaStore); + configServer.setPeerVerifyMode(QSslSocket::VerifyPeer); + QSslServer server; + server.setSslConfiguration(configServer); + QVERIFY(server.listen()); + + QSslConfiguration configClient; + configClient.setPrivateKey(clientPair.getKey()); + configClient.setLocalCertificate(clientPair.getCertificate()); + configClient.setCaCertificates(clientCaStore); + QList allowedErrors; + allowedErrors << QSslError(QSslError::HostNameMismatch, serverPair.getCertificate()); + QSslSocket client; + client.ignoreSslErrors(allowedErrors); + client.setSslConfiguration(configClient); + + QSignalSpy clientEncrypted(&client, &QSslSocket::encrypted); + + connect(&server, &QSslServer::peerVerifyError, this, [](QSslSocket* pSocket, const QSslError& pError){ + QVERIFY(pSocket); + QCOMPARE(pError.error(), QSslError::NoError); + }); + connect(&server, &QSslServer::sslErrors, this, [](QSslSocket* pSocket, const QList& pErrors){ + QVERIFY(pSocket); + QCOMPARE(pErrors, (QList())); + }); + connect(&client, &QSslSocket::sslErrors, this, [&allowedErrors](const QList& pErrors){ + QCOMPARE(pErrors, allowedErrors); + }); + client.connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + QTRY_COMPARE(clientEncrypted.count(), 1); + } + + }; QTEST_GUILESS_MAIN(test_KeyPair) diff --git a/test/qt/settings/test_PreVerificationSettings.cpp b/test/qt/settings/test_PreVerificationSettings.cpp index c59e42963..a863fe891 100644 --- a/test/qt/settings/test_PreVerificationSettings.cpp +++ b/test/qt/settings/test_PreVerificationSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -31,10 +32,10 @@ class test_PreVerificationSettings { ResourceLoader::getInstance().init(); - cvcs.append(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex", true)); - cvcs.append(TestFileHelper::readFile(":/card/cvca-DETESTeID00004_DETESTeID00002.hex", true)); - cvcs.append(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00035.hex", true)); - cvcs.append(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex", true)); + cvcs.append(TestFileHelper::readFile(":/card/cvca-DETESTeID00002_DETESTeID00001.hex"_L1, true)); + cvcs.append(TestFileHelper::readFile(":/card/cvca-DETESTeID00004_DETESTeID00002.hex"_L1, true)); + cvcs.append(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00035.hex"_L1, true)); + cvcs.append(TestFileHelper::readFile(":/card/cvat-DEDEMODEV00038.hex"_L1, true)); } diff --git a/test/qt/settings/test_RemoteServiceSettings.cpp b/test/qt/settings/test_RemoteServiceSettings.cpp index 168c8097a..3c6680a4d 100644 --- a/test/qt/settings/test_RemoteServiceSettings.cpp +++ b/test/qt/settings/test_RemoteServiceSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -37,34 +38,40 @@ class test_RemoteServiceSettings { RemoteServiceSettings settings; - QCOMPARE(settings.getServerName(), DeviceInfo::getName()); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); } - void testServerName() + void testDeviceName() { RemoteServiceSettings settings; - QCOMPARE(settings.getServerName(), DeviceInfo::getName()); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); - QCOMPARE(settings.getServerName(), DeviceInfo::getName()); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); - settings.setServerName(QStringLiteral(" ")); - QCOMPARE(settings.getServerName(), DeviceInfo::getName()); + settings.setDeviceName(QStringLiteral(" ")); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); - settings.setServerName(QStringLiteral(" \n ")); - QCOMPARE(settings.getServerName(), DeviceInfo::getName()); + settings.setDeviceName(QStringLiteral(" \n ")); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); - settings.setServerName(QStringLiteral("Google Pixel")); - QCOMPARE(settings.getServerName(), QLatin1String("Google Pixel")); + settings.setDeviceName(QStringLiteral("Google Pixel")); + QCOMPARE(settings.getDeviceName(), QLatin1String("Google Pixel")); - settings.setServerName(QStringLiteral(" Google Pixel")); - QCOMPARE(settings.getServerName(), QLatin1String("Google Pixel")); + settings.setDeviceName(QStringLiteral(" Google Pixel")); + QCOMPARE(settings.getDeviceName(), QLatin1String("Google Pixel")); - settings.setServerName(QStringLiteral("Google Pixel ")); - QCOMPARE(settings.getServerName(), QLatin1String("Google Pixel")); + settings.setDeviceName(QStringLiteral("Google Pixel ")); + QCOMPARE(settings.getDeviceName(), QLatin1String("Google Pixel")); - settings.setServerName(QStringLiteral("Google Pixel \n ")); - QCOMPARE(settings.getServerName(), QLatin1String("Google Pixel")); + settings.setDeviceName(QStringLiteral("Google Pixel \n ")); + QCOMPARE(settings.getDeviceName(), QLatin1String("Google Pixel")); + + settings.setDeviceName(QStringLiteral(" ")); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); + + settings.setDeviceName(QString()); + QCOMPARE(settings.getDeviceName(), DeviceInfo::getName()); } @@ -121,7 +128,7 @@ class test_RemoteServiceSettings RemoteServiceSettings settings; QVERIFY(settings.getTrustedCertificates().isEmpty()); QList certs; - certs << QSslCertificate(); + certs << pair3.getCertificate(); certs << pair1.getCertificate(); settings.setTrustedCertificates(certs); @@ -171,22 +178,47 @@ class test_RemoteServiceSettings { RemoteServiceSettings settings; QCOMPARE(settings.getKey(), QSslKey()); - QCOMPARE(settings.getCertificate(), QSslCertificate()); + QCOMPARE(settings.getCertificates().size(), 0); - QVERIFY(settings.checkAndGenerateKey()); + QVERIFY(settings.checkAndGenerateKey(2048)); + QCOMPARE(settings.getCertificates().size(), 1); const auto& key = settings.getKey(); - const auto& cert = settings.getCertificate(); + const auto cert = settings.getCertificates().at(0); QVERIFY(!key.isNull()); QVERIFY(!cert.isNull()); + QVERIFY(cert.isSelfSigned()); - QVERIFY(settings.checkAndGenerateKey()); + QVERIFY(settings.checkAndGenerateKey(2048)); + QCOMPARE(settings.getCertificates().size(), 1); QCOMPARE(settings.getKey(), key); - QCOMPARE(settings.getCertificate(), cert); + QCOMPARE(settings.getCertificates().at(0), cert); + + QCOMPARE(cert.effectiveDate(), QDateTime::fromString(QStringLiteral("1970-01-01T00:00:00Z"), Qt::ISODate)); + QCOMPARE(cert.expiryDate(), QDateTime::fromString(QStringLiteral("9999-12-31T23:59:59Z"), Qt::ISODate)); + QVERIFY(cert.effectiveDate().isValid()); + QVERIFY(cert.expiryDate().isValid()); + + QVERIFY(settings.checkAndGenerateKey(3072)); + QCOMPARE(settings.getCertificates().size(), 2); + const auto derivedCert = settings.getCertificates().at(0); + QVERIFY(settings.getKey() != key); + QCOMPARE(settings.getCertificates().at(1), cert); + QVERIFY(derivedCert != cert); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::SerialNumber).size(), 1); + QCOMPARE(cert.issuerInfo(QSslCertificate::SerialNumber).size(), 1); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::SerialNumber).at(0), + cert.issuerInfo(QSslCertificate::SerialNumber).at(0)); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::CommonName).size(), 1); + QCOMPARE(cert.issuerInfo(QSslCertificate::CommonName).size(), 1); + + QCOMPARE(derivedCert.issuerInfo(QSslCertificate::CommonName).at(0), + cert.issuerInfo(QSslCertificate::CommonName).at(0)); + + QVERIFY(!derivedCert.isSelfSigned()); - QCOMPARE(settings.getCertificate().effectiveDate(), QDateTime::fromString(QStringLiteral("1970-01-01T00:00:00Z"), Qt::ISODate)); - QCOMPARE(settings.getCertificate().expiryDate(), QDateTime::fromString(QStringLiteral("9999-12-31T23:59:59Z"), Qt::ISODate)); - QVERIFY(settings.getCertificate().effectiveDate().isValid()); - QVERIFY(settings.getCertificate().expiryDate().isValid()); } @@ -205,12 +237,13 @@ class test_RemoteServiceSettings void testCertificate() { RemoteServiceSettings settings; - QCOMPARE(settings.getCertificate(), QSslCertificate()); - QCOMPARE(settings.getCertificate(), QSslCertificate()); + QVERIFY(settings.getCertificates().isEmpty()); + QVERIFY(settings.getCertificates().isEmpty()); - settings.setCertificate(pair1.getCertificate()); - QCOMPARE(settings.getCertificate(), pair1.getCertificate()); - QVERIFY(!settings.getCertificate().isNull()); + settings.setCertificates({pair1.getCertificate()}); + QVERIFY(!settings.getCertificates().isEmpty()); + QCOMPARE(settings.getCertificates().constFirst(), pair1.getCertificate()); + QVERIFY(!settings.getCertificates().constFirst().isNull()); } @@ -235,11 +268,11 @@ class test_RemoteServiceSettings auto second = settings.getRemoteInfos().at(1); QCOMPARE(first, a); QCOMPARE(second, b); - QCOMPARE(first.getFingerprint(), QString("a")); - QCOMPARE(first.getNameEscaped(), QStringLiteral("dummy for A")); + QCOMPARE(first.getFingerprint(), "a"_L1); + QCOMPARE(first.getNameEscaped(), "dummy for A"_L1); QCOMPARE(first.getLastConnected(), current); - QCOMPARE(second.getFingerprint(), QString("b")); - QCOMPARE(second.getNameEscaped(), QStringLiteral("dummy for B")); + QCOMPARE(second.getFingerprint(), "b"_L1); + QCOMPARE(second.getNameEscaped(), "dummy for B"_L1); QCOMPARE(second.getLastConnected(), current); settings.setRemoteInfos({}); @@ -264,9 +297,9 @@ class test_RemoteServiceSettings QCOMPARE(settings.getRemoteInfos().at(0).getNameEscaped(), QString()); auto aInfo = settings.getRemoteInfo(a); - aInfo.setNameUnescaped(QString("dummy")); + aInfo.setNameUnescaped("dummy"_L1); QVERIFY(settings.updateRemoteInfo(aInfo)); - QCOMPARE(settings.getRemoteInfos().at(0).getNameEscaped(), QString("dummy")); + QCOMPARE(settings.getRemoteInfos().at(0).getNameEscaped(), "dummy"_L1); QCOMPARE(settings.getRemoteInfos().size(), 2); auto c = pair3.getCertificate(); @@ -276,12 +309,12 @@ class test_RemoteServiceSettings settings.addTrustedCertificate(c); cInfo = settings.getRemoteInfo(c); - cInfo.setNameUnescaped("c"); + cInfo.setNameUnescaped("c"_L1); settings.updateRemoteInfo(cInfo); QCOMPARE(settings.getRemoteInfos().size(), 3); - QCOMPARE(settings.getRemoteInfos().at(0).getNameEscaped(), QString("dummy")); + QCOMPARE(settings.getRemoteInfos().at(0).getNameEscaped(), "dummy"_L1); QCOMPARE(settings.getRemoteInfos().at(1).getNameEscaped(), QString()); - QCOMPARE(settings.getRemoteInfos().at(2).getNameEscaped(), QString("c")); + QCOMPARE(settings.getRemoteInfos().at(2).getNameEscaped(), "c"_L1); QCOMPARE(settings.getRemoteInfos().at(2).getFingerprint(), QString::fromLatin1(c.digest(QCryptographicHash::Sha256).toHex())); } @@ -297,7 +330,7 @@ class test_RemoteServiceSettings settings.addTrustedCertificate(a); auto aInfo = settings.getRemoteInfo(a); - aInfo.setNameUnescaped("hallo"); + aInfo.setNameUnescaped("hallo"_L1); QVERIFY(settings.updateRemoteInfo(aInfo)); QCOMPARE(settings.getRemoteInfos().size(), 1); diff --git a/test/qt/settings/test_SimulatorSettings.cpp b/test/qt/settings/test_SimulatorSettings.cpp new file mode 100644 index 000000000..1dddcde9a --- /dev/null +++ b/test/qt/settings/test_SimulatorSettings.cpp @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + + +#include "SimulatorSettings.h" + +#include "AppSettings.h" + +#include +#include + + +using namespace governikus; + + +class test_SimulatorSettings + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + // init ctor of Singleton, otherwise the testcases are not + // stable. There could be differences between a run of a + // single testcase and the whole testsuite. + Q_UNUSED(Env::getSingleton()->getSimulatorSettings()) + } + + + void init() + { + AbstractSettings::mTestDir.clear(); + } + + + void testEnabled() + { + auto& settings = Env::getSingleton()->getSimulatorSettings(); + QSignalSpy settingsSpy(&settings, &SimulatorSettings::fireEnabledChanged); + + QCOMPARE(settingsSpy.count(), 0); + QCOMPARE(settings.isEnabled(), false); + + settings.setEnabled(true); + QCOMPARE(settingsSpy.count(), 1); + QCOMPARE(settings.isEnabled(), true); + + settings.setEnabled(true); + QCOMPARE(settingsSpy.count(), 1); + QCOMPARE(settings.isEnabled(), true); + + settings.setEnabled(false); + QCOMPARE(settingsSpy.count(), 2); + QCOMPARE(settings.isEnabled(), false); + + settings.setEnabled(false); + QCOMPARE(settingsSpy.count(), 2); + QCOMPARE(settings.isEnabled(), false); + } + + + void testBasicReader() + { + auto& settings = Env::getSingleton()->getSimulatorSettings(); + QCOMPARE(settings.isBasicReader(), false); + + settings.setBasicReader(true); + QCOMPARE(settings.isBasicReader(), true); + + settings.setBasicReader(true); + QCOMPARE(settings.isBasicReader(), true); + + settings.setBasicReader(false); + QCOMPARE(settings.isBasicReader(), false); + + settings.setBasicReader(false); + QCOMPARE(settings.isBasicReader(), false); + } + + +}; + +QTEST_GUILESS_MAIN(test_SimulatorSettings) +#include "test_SimulatorSettings.moc" diff --git a/test/qt/settings/test_VolatileSettings.cpp b/test/qt/settings/test_VolatileSettings.cpp index 197e0f2a4..40d4f5944 100644 --- a/test/qt/settings/test_VolatileSettings.cpp +++ b/test/qt/settings/test_VolatileSettings.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -70,6 +70,36 @@ class test_VolatileSettings } + void test_Messages_data() + { + QTest::addColumn("started"); + QTest::addColumn("failed"); + QTest::addColumn("succeded"); + QTest::addColumn("progress"); + + QTest::addRow("empty") << QString() << QString() << QString() << QString(); + QTest::addRow("not empty") << QStringLiteral("a") << QStringLiteral("b") << QStringLiteral("c") << QStringLiteral("d"); + } + + + void test_Messages() + { + QFETCH(QString, started); + QFETCH(QString, failed); + QFETCH(QString, succeded); + QFETCH(QString, progress); + + VolatileSettings::Messages messages(started, failed, succeded, progress); + + QVERIFY(!messages.getSessionFailed().isNull()); + + QCOMPARE(messages.getSessionStarted(), started); + QCOMPARE(messages.getSessionFailed(), failed); + QCOMPARE(messages.getSessionSucceeded(), succeded); + QCOMPARE(messages.getSessionInProgress(), progress); + } + + }; QTEST_GUILESS_MAIN(test_VolatileSettings) diff --git a/test/qt/ui/automatic/test_UIPlugInAutomatic.cpp b/test/qt/ui/automatic/test_UiPluginAutomatic.cpp similarity index 86% rename from test/qt/ui/automatic/test_UIPlugInAutomatic.cpp rename to test/qt/ui/automatic/test_UiPluginAutomatic.cpp index d3e81e82c..4a53a963d 100644 --- a/test/qt/ui/automatic/test_UIPlugInAutomatic.cpp +++ b/test/qt/ui/automatic/test_UiPluginAutomatic.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UIPlugInAutomatic + * \brief Unit tests for \ref UiPluginAutomatic */ -#include "UIPlugInAutomatic.h" +#include "UiPluginAutomatic.h" #include "ReaderManager.h" #include "VolatileSettings.h" @@ -15,7 +15,7 @@ #include "states/StateSelectReader.h" #include "MockCardConnection.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "TestAuthContext.h" #include "TestWorkflowContext.h" #include "TestWorkflowController.h" @@ -24,13 +24,14 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QLatin1String) -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) class DummyUI - : public UIPlugIn + : public UiPlugin { Q_OBJECT @@ -57,7 +58,7 @@ void DummyUI::onWorkflowFinished(const QSharedPointer& pRequest } -class test_UIPlugInAutomatic +class test_UiPluginAutomatic : public QObject { Q_OBJECT @@ -65,7 +66,7 @@ class test_UIPlugInAutomatic private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -80,14 +81,14 @@ class test_UIPlugInAutomatic void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } void startUpShutDown() { - UIPlugInAutomatic ui; - QTest::failOnWarning(QRegularExpression(".*")); + UiPluginAutomatic ui; + QTest::failOnWarning(QRegularExpression(".*"_L1)); ui.onApplicationStarted(); ui.doShutdown(); } @@ -97,7 +98,7 @@ class test_UIPlugInAutomatic { DummyUI dummy; - UIPlugInAutomatic ui; + UiPluginAutomatic ui; QVERIFY(!ui.isDominated()); QVERIFY(ui.mDominator.isEmpty()); @@ -123,7 +124,7 @@ class test_UIPlugInAutomatic { DummyUI dummy; - UIPlugInAutomatic ui; + UiPluginAutomatic ui; ui.onUiDomination(&dummy, QString(), true); QVERIFY(ui.isDominated()); @@ -143,11 +144,11 @@ class test_UIPlugInAutomatic void workflowKilled() { - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); - QTest::ignoreMessage(QtDebugMsg, R"(Claim workflow by "governikus::UIPlugInAutomatic")"); + QTest::ignoreMessage(QtDebugMsg, R"(Claim workflow by "governikus::UiPluginAutomatic")"); QTest::ignoreMessage(QtWarningMsg, "Cannot handle context... abort automatic workflow"); QTest::ignoreMessage(QtWarningMsg, "Killing the current workflow."); ui.onWorkflowStarted(request); @@ -160,13 +161,13 @@ class test_UIPlugInAutomatic { Env::getSingleton()->setUsedAsSDK(false); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); QVERIFY(ui.mContext.isNull()); QVERIFY(!Env::getSingleton()->isUsedAsSDK()); - QTest::ignoreMessage(QtDebugMsg, R"(Claim workflow by "governikus::UIPlugInAutomatic")"); + QTest::ignoreMessage(QtDebugMsg, R"(Claim workflow by "governikus::UiPluginAutomatic")"); QTest::ignoreMessage(QtDebugMsg, "Fallback to full automatic UI"); ui.onWorkflowStarted(request); QVERIFY(!ui.mContext.isNull()); @@ -184,7 +185,7 @@ class test_UIPlugInAutomatic void stateChanged() { - UIPlugInAutomatic ui; + UiPluginAutomatic ui; ui.onStateChanged(QStringLiteral("do nothing")); const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); @@ -200,7 +201,8 @@ class test_UIPlugInAutomatic void insertNoCard() { - UIPlugInAutomatic ui; + MockReaderManagerPlugin::getInstance().setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); @@ -209,18 +211,19 @@ class test_UIPlugInAutomatic QTest::ignoreMessage(QtWarningMsg, "Cannot insert card... abort automatic workflow"); QTest::ignoreMessage(QtWarningMsg, "Killing the current workflow."); context->setCurrentState(StateBuilder::generateStateName()); - QVERIFY(context->isWorkflowKilled()); + QTRY_VERIFY(context->isWorkflowKilled()); // clazy:exclude=qstring-allocations } void insertCard() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader"); + MockReaderManagerPlugin::getInstance().setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader"_L1); reader->setCard(MockCardConfig()); QVERIFY(reader->getReaderInfo().hasEid()); QVERIFY(!reader->getReaderInfo().isInsertable()); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); @@ -235,8 +238,9 @@ class test_UIPlugInAutomatic void insertableCard() { - MockReader* unusedReader = MockReaderManagerPlugIn::getInstance().addReader("MockReader1"); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader2"); + MockReaderManagerPlugin::getInstance().setInitialScanState(ReaderManagerPluginInfo::InitialScan::SUCCEEDED); + MockReader* unusedReader = MockReaderManagerPlugin::getInstance().addReader("MockReader1"_L1); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader2"_L1); reader->setCard(MockCardConfig()); QSignalSpy spy(Env::getSingleton(), &ReaderManager::fireReaderPropertiesUpdated); @@ -253,7 +257,7 @@ class test_UIPlugInAutomatic QVERIFY(readerInfo.isInsertable()); QVERIFY(readerInfo.wasShelved()); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); @@ -273,7 +277,7 @@ class test_UIPlugInAutomatic void handlePasswordFailed() { - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); context->setLastPaceResult(CardReturnCode::PROTOCOL_ERROR); @@ -299,11 +303,11 @@ class test_UIPlugInAutomatic { QFETCH(CardReturnCode, returnCode); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader", ReaderManagerPlugInType::SIMULATOR); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader"_L1, ReaderManagerPluginType::SIMULATOR); reader->setCard(MockCardConfig()); reader->setInfoBasicReader(false); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); context->setLastPaceResult(returnCode); @@ -318,11 +322,11 @@ class test_UIPlugInAutomatic void handlePasswordNonBasic() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader"_L1); reader->setCard(MockCardConfig()); reader->setInfoBasicReader(false); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); context->setLastPaceResult(CardReturnCode::OK); @@ -392,11 +396,11 @@ class test_UIPlugInAutomatic qputenv(envVariable.data(), envValue); } - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader"_L1); reader->setCard(MockCardConfig()); reader->setInfoBasicReader(true); - UIPlugInAutomatic ui; + UiPluginAutomatic ui; const auto& request = TestWorkflowController::createWorkflowRequest(); const auto& context = request->getContext(); context->setLastPaceResult(CardReturnCode::OK); @@ -431,5 +435,5 @@ class test_UIPlugInAutomatic }; -QTEST_GUILESS_MAIN(test_UIPlugInAutomatic) -#include "test_UIPlugInAutomatic.moc" +QTEST_GUILESS_MAIN(test_UiPluginAutomatic) +#include "test_UiPluginAutomatic.moc" diff --git a/test/qt/ui/base/test_UiLoader.cpp b/test/qt/ui/base/test_UiLoader.cpp new file mode 100644 index 000000000..cd576f90a --- /dev/null +++ b/test/qt/ui/base/test_UiLoader.cpp @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiLoader.h" + +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + +class test_UiLoader + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void environment() + { + const QByteArray jsonString(R"( + {"IID":"governikus.UIPlugin", + "MetaData": { + "default":true, + "env":{"TEST_UILOADER":"dummy"}, + "userInteractive":true + }, + "className":"UIPluginQml"} + )"); + + QJsonParseError jsonError {}; + const auto& json = QJsonDocument::fromJson(jsonString, &jsonError); + QCOMPARE(jsonError.error, QJsonParseError::NoError); + const auto& obj = json.object(); + + const char* envVarName = "TEST_UILOADER"; + qunsetenv(envVarName); + + QTest::ignoreMessage(QtDebugMsg, "Set environment: \"TEST_UILOADER\" = \"dummy\""); + UiLoader::setEnvironment(obj); + QCOMPARE(qgetenv(envVarName), "dummy"); + } + + +}; + +QTEST_GUILESS_MAIN(test_UiLoader) +#include "test_UiLoader.moc" diff --git a/test/qt/ui/json/test_Message.cpp b/test/qt/ui/json/test_Message.cpp index b68b57be7..ee2fee794 100644 --- a/test/qt/ui/json/test_Message.cpp +++ b/test/qt/ui/json/test_Message.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,7 +17,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -98,7 +98,7 @@ class test_Message void createMsgHandlerReader() { MessageDispatcher dispatcher; - const auto& msg = dispatcher.processReaderChange(ReaderInfo("dummy reader")); + const auto& msg = dispatcher.processReaderChange(ReaderInfo("dummy reader"_L1)); QCOMPARE(msg.size(), 1); QCOMPARE(msg.first(), QByteArray(R"({"attached":false,"msg":"READER","name":"dummy reader"})")); } @@ -134,7 +134,7 @@ class test_Message MessageDispatcher dispatcher; QCOMPARE(dispatcher.init(context), MsgType::VOID); - context->setReaderName("dummy"); + context->setReaderName("dummy"_L1); QVERIFY(!context->isStateApproved()); QCOMPARE(dispatcher.processStateChange(QStringLiteral("SomeUnknownState")), QByteArray()); QVERIFY(context->isStateApproved()); @@ -224,9 +224,9 @@ class test_Message void finishAuthContext() { - const QSharedPointer context(new AuthContext(true, QUrl("http://dummy"))); + const QSharedPointer context(new AuthContext(true, QUrl("http://dummy"_L1))); context->setStatus(GlobalStatus::Code::No_Error); - context->setRefreshUrl(QUrl("http://dummy")); + context->setRefreshUrl(QUrl("http://dummy"_L1)); MessageDispatcher dispatcher; QCOMPARE(dispatcher.init(context), MsgType::AUTH); diff --git a/test/qt/ui/json/test_MsgContext.cpp b/test/qt/ui/json/test_MsgContext.cpp index 1f6623463..ff149f61e 100644 --- a/test/qt/ui/json/test_MsgContext.cpp +++ b/test/qt/ui/json/test_MsgContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,6 +18,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_MsgContext @@ -28,7 +29,7 @@ class test_MsgContext private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -94,7 +95,7 @@ class test_MsgContext QVERIFY(!ctx.getContext()); QVERIFY(!readOnly.getContext()); - ctx.setWorkflowContext(QSharedPointer(new AuthContext(true, QUrl("http://www.bla.de")))); + ctx.setWorkflowContext(QSharedPointer(new AuthContext(true, QUrl("http://www.bla.de"_L1)))); QVERIFY(readOnly.isActiveWorkflow()); QVERIFY(readOnly.getContext()); QVERIFY(ctx.getContext()); diff --git a/test/qt/ui/json/test_MsgHandler.cpp b/test/qt/ui/json/test_MsgHandler.cpp index 9b66dc2dd..5b6a2a0d2 100644 --- a/test/qt/ui/json/test_MsgHandler.cpp +++ b/test/qt/ui/json/test_MsgHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; namespace @@ -56,11 +57,11 @@ class test_MsgHandler MsgTest msg; QJsonObject dummy; - dummy["unused"] = "this will be ignored"; + dummy["unused"_L1] = "this will be ignored"_L1; msg.setRequest(dummy); QCOMPARE(msg.toJson(), QByteArray("{\"msg\":\"INVALID\"}")); - dummy["request"] = "hello world"; + dummy["request"_L1] = "hello world"_L1; msg.setRequest(dummy); QCOMPARE(msg.toJson(), QByteArray("{\"msg\":\"INVALID\",\"request\":\"hello world\"}")); } diff --git a/test/qt/ui/json/test_MsgHandlerAccessRights.cpp b/test/qt/ui/json/test_MsgHandlerAccessRights.cpp index 37826473c..f79314b1a 100644 --- a/test/qt/ui/json/test_MsgHandlerAccessRights.cpp +++ b/test/qt/ui/json/test_MsgHandlerAccessRights.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,7 +16,7 @@ #include "TestAuthContext.h" #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -42,7 +42,7 @@ class test_MsgHandlerAccessRights QSharedPointer getContextWithChat(bool pCanAllowed = false) { Env::getSingleton()->getGeneralSettings().setEnableCanAllowed(pCanAllowed); - auto context = QSharedPointer::create(":/paos/DIDAuthenticateEAC1.xml"); + auto context = QSharedPointer::create(":/paos/DIDAuthenticateEAC1.xml"_L1); context->setRequiredAccessRights({AccessRight::READ_DG01, AccessRight::READ_DG04, AccessRight::READ_DG17}); context->setOptionalAccessRights({AccessRight::AGE_VERIFICATION, AccessRight::READ_DG05}); Env::getSingleton()->getGeneralSettings().setEnableCanAllowed(false); @@ -75,7 +75,7 @@ class test_MsgHandlerAccessRights void nonExistingTransactionInfo() { - const auto& context = QSharedPointer::create(":/paos/DIDAuthenticateEAC1_2.xml"); + const auto& context = QSharedPointer::create(":/paos/DIDAuthenticateEAC1_2.xml"_L1); MessageDispatcher dispatcher; QCOMPARE(dispatcher.init(context), MsgType::AUTH); diff --git a/test/qt/ui/json/test_MsgHandlerApiLevel.cpp b/test/qt/ui/json/test_MsgHandlerApiLevel.cpp index 488516d37..40619ab89 100644 --- a/test/qt/ui/json/test_MsgHandlerApiLevel.cpp +++ b/test/qt/ui/json/test_MsgHandlerApiLevel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -25,7 +25,7 @@ class test_MsgHandlerApiLevel MsgContext context; context.setApiLevel(MsgLevel::v1); MsgHandlerApiLevel msg(std::as_const(context)); - QCOMPARE(msg.toJson(), QByteArray("{\"available\":[1,2],\"current\":1,\"msg\":\"API_LEVEL\"}")); + QCOMPARE(msg.toJson(), QByteArray("{\"available\":[1,2,3],\"current\":1,\"msg\":\"API_LEVEL\"}")); } @@ -34,7 +34,7 @@ class test_MsgHandlerApiLevel MsgContext context; context.setApiLevel(MsgHandler::DEFAULT_MSG_LEVEL); MsgHandlerApiLevel msg(std::as_const(context)); - QCOMPARE(msg.toJson(), QByteArray("{\"available\":[1,2],\"current\":2,\"msg\":\"API_LEVEL\"}")); + QCOMPARE(msg.toJson(), QByteArray("{\"available\":[1,2,3],\"current\":3,\"msg\":\"API_LEVEL\"}")); } @@ -42,7 +42,7 @@ class test_MsgHandlerApiLevel { MessageDispatcher dispatcher; QByteArray msg = R"({"cmd": "GET_API_LEVEL"})"; - QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"available\":[1,2],\"current\":2,\"msg\":\"API_LEVEL\"}")); + QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"available\":[1,2,3],\"current\":3,\"msg\":\"API_LEVEL\"}")); } @@ -50,14 +50,14 @@ class test_MsgHandlerApiLevel { QByteArray msg(R"({"cmd": "SET_API_LEVEL"})"); MessageDispatcher dispatcher; - QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"current\":2,\"error\":\"Level cannot be undefined\",\"msg\":\"API_LEVEL\"}")); + QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"current\":3,\"error\":\"Level cannot be undefined\",\"msg\":\"API_LEVEL\"}")); } void setInvalidLevel() { MessageDispatcher dispatcher; - QByteArray expected(R"({"current":2,"error":"Invalid level","msg":"API_LEVEL"})"); + QByteArray expected(R"({"current":3,"error":"Invalid level","msg":"API_LEVEL"})"); QByteArray msg(R"({"cmd": "SET_API_LEVEL", "level": ""})"); QCOMPARE(dispatcher.processCommand(msg), expected); @@ -79,7 +79,7 @@ class test_MsgHandlerApiLevel void setUnknownLevel() { MessageDispatcher dispatcher; - QByteArray expected(R"({"current":2,"error":"Unknown level","msg":"API_LEVEL"})"); + QByteArray expected(R"({"current":3,"error":"Unknown level","msg":"API_LEVEL"})"); QByteArray msg(R"({"cmd": "SET_API_LEVEL", "level": -1})"); QCOMPARE(dispatcher.processCommand(msg), expected); diff --git a/test/qt/ui/json/test_MsgHandlerAuth.cpp b/test/qt/ui/json/test_MsgHandlerAuth.cpp index 4e878e804..59b6633ed 100644 --- a/test/qt/ui/json/test_MsgHandlerAuth.cpp +++ b/test/qt/ui/json/test_MsgHandlerAuth.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,8 +11,8 @@ #include "AppSettings.h" #include "LanguageLoader.h" #include "MessageDispatcher.h" -#include "UILoader.h" -#include "UIPlugInJson.h" +#include "UiLoader.h" +#include "UiPluginJson.h" #include "VolatileSettings.h" #include "WorkflowRequest.h" #include "controller/AppController.h" @@ -24,9 +24,9 @@ #include -Q_IMPORT_PLUGIN(UIPlugInJson) - +Q_IMPORT_PLUGIN(UiPluginJson) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -47,7 +47,7 @@ class test_MsgHandlerAuth qRegisterMetaType>("QSharedPointer"); LanguageLoader::getInstance().setPath(mTranslationDir.path()); // avoid loaded translations - connect(Env::getSingleton(), &UILoader::fireLoadedPlugin, this, [](UIPlugIn* pUi){ + connect(Env::getSingleton(), &UiLoader::fireLoadedPlugin, this, [](UiPlugin* pUi){ pUi->setProperty("passive", QVariant()); // fake active UI for AppController::start }); } @@ -55,10 +55,10 @@ class test_MsgHandlerAuth void cleanup() { - auto* uiLoader = Env::getSingleton(); + auto* uiLoader = Env::getSingleton(); if (uiLoader->isLoaded()) { - QSignalSpy spyUi(uiLoader, &UILoader::fireRemovedAllPlugins); + QSignalSpy spyUi(uiLoader, &UiLoader::fireRemovedAllPlugins); uiLoader->shutdown(); QTRY_COMPARE(spyUi.count(), 1); // clazy:exclude=qstring-allocations } @@ -113,10 +113,10 @@ class test_MsgHandlerAuth void runAuthCmd() { - QVERIFY(Env::getSingleton()->load()); - auto jsonUi = Env::getSingleton()->getLoaded(); + QVERIFY(Env::getSingleton()->load()); + auto jsonUi = Env::getSingleton()->getLoaded(); QVERIFY(jsonUi); - QSignalSpy spy(jsonUi, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spy(jsonUi, &UiPlugin::fireWorkflowRequested); MessageDispatcher dispatcher; QByteArray msg = "{\"cmd\": \"RUN_AUTH\", \"tcTokenURL\": \"https://www.governikus.de/token?session=123abc\"}"; @@ -128,7 +128,7 @@ class test_MsgHandlerAuth QCOMPARE(request->getAction(), Action::AUTH); QVERIFY(request->getContext().objectCast()); QCOMPARE(request->getContext().objectCast()->getActivationUrl(), - QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Fwww.governikus.de%2Ftoken%3Fsession%3D123abc")); + QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Fwww.governikus.de%2Ftoken%3Fsession%3D123abc"_L1)); } @@ -139,7 +139,7 @@ class test_MsgHandlerAuth QCOMPARE(dispatcher.init(context), QByteArray()); QCOMPARE(dispatcher.finish(), QByteArray()); - const QSharedPointer authContext(new AuthContext(true, QUrl("http://dummy"))); + const QSharedPointer authContext(new AuthContext(true, QUrl("http://dummy"_L1))); QCOMPARE(dispatcher.init(authContext), QByteArray("{\"msg\":\"AUTH\"}")); } @@ -156,28 +156,28 @@ class test_MsgHandlerAuth void handleStatus() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, handleStatus); QFETCH(int, statusMessages); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([](const QString& pState){ return StateBuilder::isState(pState); }); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); static int firedStatusCount = 0; connect(&controller, &AppController::fireWorkflowStarted, this, [this, ui](const QSharedPointer& pRequest){ const auto& context = pRequest->getContext(); - context->claim(this); // UIPlugInJson is internal API and does not claim by itself + context->claim(this); // UiPluginJson is internal API and does not claim by itself connect(context.data(), &WorkflowContext::fireStateChanged, this, [ui](const QString& pState) { // do not CANCEL to early to get all STATUS messages and avoid flaky unit test @@ -188,7 +188,7 @@ class test_MsgHandlerAuth } }); }); - connect(ui, &UIPlugInJson::fireMessage, this, [](const QByteArray& pMsg){ + connect(ui, &UiPluginJson::fireMessage, this, [](const QByteArray& pMsg){ if (pMsg.contains(R"("msg":"STATUS")")) { ++firedStatusCount; @@ -216,10 +216,10 @@ class test_MsgHandlerAuth void runEncoded() { - QVERIFY(Env::getSingleton()->load()); - auto jsonUi = Env::getSingleton()->getLoaded(); + QVERIFY(Env::getSingleton()->load()); + auto jsonUi = Env::getSingleton()->getLoaded(); QVERIFY(jsonUi); - QSignalSpy spy(jsonUi, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spy(jsonUi, &UiPlugin::fireWorkflowRequested); MessageDispatcher dispatcher; QByteArray msg = "{\"cmd\": \"RUN_AUTH\", \"tcTokenURL\": \"https://test.governikus-eid.de/gov_autent/async?SAMLRequest=nVbZsppIGH4Vi7m0lEURsI4nBbIcV1TA7SbF0myy0wj49NMeTXIySWYyueTvf%2FuWrublUxNHnSsoyiBNJhjZJ7AOSOzUCRJvghm63GOxT68vpRlHVDbmK%2BgnO5BXoIQdVJiU48fJBKuKZJyaZVCOEzMG5RjaY41fLcdUnxhnRQpTO42wDl%2BWoIBo1DRNyioGhQaKa2ADY7ecYD6EWTnG8bqu3X50jfsOwJPMvA%2FFgZ3Gn9HHPYAXoMxQPcA6IlokSMx7x2%2F1EAX7XopAJcGlKnsgcO6tUOSzWUGQQNws28TGOjNxgjG2NaBphu3RnEX1hiQDepwzGvVIa8S6nM3ZBHBRZllWYJaU0EzgBKMIctQj2B7J6iQ1HpBjiukTLHPGOpsivQYOKNaIg58Cwjr7L1wjZrAns%2BP3%2FsVHSv%2BdUfMLj9jrT1h7wd9VeXb9qp7UIPB3ncvXF8TJWErsos0gcD7K%2BjXpuQxKfABBwlhl0Leq5J1NMBNxtH6DzPKtkWhC81l3P%2FhaiBTt14N%2BWng4RRAkTgxx5B6U8RfW0dvsSdVD%2Bl8kShGIkXT%2FGInArAD0U6fDR15aBNCPf2OoCUqSYnu2hTzwcPHvbou%2FvjjleAHaWeKmz1qn%2FMVIAie4O06nDLy%2FfuAKNfmfw79n%2B8%2BgF6XZIz%2FTGALyLt00yHxQ3HX7LrA3owq8nqchd%2FChs84FcV%2F7K2XeNSNam7c1zXHmaE01PIgXcC8dVEkwOF9cgKS6Gjw7z%2Fcm301Gy4G2U3ldYZNjokPNXknswARRE1X1eWSDZvgGGUNwzhS6g1yrGsui1cBFSMJwF8Do1rihPLyZPH%2B7haovT4eaFrDbAcB3ah6G24xiVGFr5%2BUlOxlvuORmrFaQuzIHyvE257rT0Qpe9xqlVeAYWIGhioZiWWcoRnVIadR5YbORNmUAawRruznL%2FsUN8GCjjEA7mpmLnAqrZRU5i22Sd91An2blxp2R7IY6VLcisRwhJslgyKjEleEbMO9yF4m4bQapCs8jnWblM6WpFru02fDCevopWnteylL1ZPKCf%2BD%2BQfV3oYccj6SvlxT5BcW%2Bue8HAf%2FMTQ8DPJYQZXuh7SMTD8zuydusrZJf86WxyozjgobSkWfDkMn5S3d7mFJTXKWEkXuKdWKGFnXOQrbYJwodtcXONjyt686N5T4ZCOtpO4PeJiLo0PDieXdIzt11lzLndd4KjLqkY3kqH287U2svdeN6852480LvYm4vTEUXbN0FOKMUtroeXtdRGHOncHqMtZTJcvEircycDWNFy89VumWnqsTBvT7jo60ypUYbLTkt97nbGOvGJm1wahNDk5q3Q93qNVgufWV6s66GlTnbzDVxejiq7ThcNUqs3FyfVmVCYbeOElnXzU0JL7wtIefm1Wwv4%2FQZF%2Bp0mCa6tiVO8qI2Z7kx8KKteIipPN7dToNqFzCU7s9xRStX25wkV3SVpjK1sXTeL%2FRmPuAovBL5dsaTDCFJSnwaDfNhxXXdZq%2BLZ1fGU8GxBHxJweVVONRvvnySDkyOV0P1EOf8fHAEx5vPnzPLSvnB4dJGAhzGbJAJFJnvDFGo9gBuzduaetsf4PHmOJc6APybfPkzDz6N%2Bd%2BPB3Lq85fh46PzJfbxvXn9Gw%3D%3D&RelayState=fc4b5fad-76fd-49d2-841b-b5cd39568029&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=jEVAVmY1XMMuNt2GJ%2BoaN6FaGj6ACZokOfme1OmkBiCPJyr%2B4rsg%2BrajIyMtSoUbtOoOaH63g1JP%0AqT7Wc%2Bucd%2FLcEYf7qU%2FJKN2uTMvssQblsSKuPHOWLJQUKPZHiSPA67%2F9JZhov8FXYM9uBYSs1Far%0AMRBpM49o1m1pRzwOKx3%2FcwOqc%2BT5mOWM78tNOj37mFFzwDTGuoB9iE2cZCUu1wfBbTPIvRZ2ND8Y%0AVYEO5FdR8W0sLR9LNOVjm64D%2Fl9u%2FjFJXntW4CPRPXiOiCr7TLlnFWVxXOTwywF5LTyLYQR5OjwB%0AK3cWmRPkN6OAejN%2F3Su3nWHDlGttrZuZBYzfag%3D%3D\"}"; @@ -231,7 +231,7 @@ class test_MsgHandlerAuth QCOMPARE(request->getAction(), Action::AUTH); QVERIFY(request->getContext().objectCast()); QCOMPARE(request->getContext().objectCast()->getActivationUrl(), - QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Ftest.governikus-eid.de%2Fgov_autent%2Fasync%3FSAMLRequest%3DnVbZsppIGH4Vi7m0lEURsI4nBbIcV1TA7SbF0myy0wj49NMeTXIySWYyueTvf%252FuWrublUxNHnSsoyiBNJhjZJ7AOSOzUCRJvghm63GOxT68vpRlHVDbmK%252BgnO5BXoIQdVJiU48fJBKuKZJyaZVCOEzMG5RjaY41fLcdUnxhnRQpTO42wDl%252BWoIBo1DRNyioGhQaKa2ADY7ecYD6EWTnG8bqu3X50jfsOwJPMvA%252FFgZ3Gn9HHPYAXoMxQPcA6IlokSMx7x2%252F1EAX7XopAJcGlKnsgcO6tUOSzWUGQQNws28TGOjNxgjG2NaBphu3RnEX1hiQDepwzGvVIa8S6nM3ZBHBRZllWYJaU0EzgBKMIctQj2B7J6iQ1HpBjiukTLHPGOpsivQYOKNaIg58Cwjr7L1wjZrAns%252BP3%252FsVHSv%252BdUfMLj9jrT1h7wd9VeXb9qp7UIPB3ncvXF8TJWErsos0gcD7K%252BjXpuQxKfABBwlhl0Leq5J1NMBNxtH6DzPKtkWhC81l3P%252FhaiBTt14N%252BWng4RRAkTgxx5B6U8RfW0dvsSdVD%252Bl8kShGIkXT%252FGInArAD0U6fDR15aBNCPf2OoCUqSYnu2hTzwcPHvbou%252FvjjleAHaWeKmz1qn%252FMVIAie4O06nDLy%252FfuAKNfmfw79n%252B8%252BgF6XZIz%252FTGALyLt00yHxQ3HX7LrA3owq8nqchd%252FChs84FcV%252F7K2XeNSNam7c1zXHmaE01PIgXcC8dVEkwOF9cgKS6Gjw7z%252Fcm301Gy4G2U3ldYZNjokPNXknswARRE1X1eWSDZvgGGUNwzhS6g1yrGsui1cBFSMJwF8Do1rihPLyZPH%252B7haovT4eaFrDbAcB3ah6G24xiVGFr5%252BUlOxlvuORmrFaQuzIHyvE257rT0Qpe9xqlVeAYWIGhioZiWWcoRnVIadR5YbORNmUAawRruznL%252FsUN8GCjjEA7mpmLnAqrZRU5i22Sd91An2blxp2R7IY6VLcisRwhJslgyKjEleEbMO9yF4m4bQapCs8jnWblM6WpFru02fDCevopWnteylL1ZPKCf%252BD%252BQfV3oYccj6SvlxT5BcW%252Bue8HAf%252FMTQ8DPJYQZXuh7SMTD8zuydusrZJf86WxyozjgobSkWfDkMn5S3d7mFJTXKWEkXuKdWKGFnXOQrbYJwodtcXONjyt686N5T4ZCOtpO4PeJiLo0PDieXdIzt11lzLndd4KjLqkY3kqH287U2svdeN6852480LvYm4vTEUXbN0FOKMUtroeXtdRGHOncHqMtZTJcvEircycDWNFy89VumWnqsTBvT7jo60ypUYbLTkt97nbGOvGJm1wahNDk5q3Q93qNVgufWV6s66GlTnbzDVxejiq7ThcNUqs3FyfVmVCYbeOElnXzU0JL7wtIefm1Wwv4%252FQZF%252Bp0mCa6tiVO8qI2Z7kx8KKteIipPN7dToNqFzCU7s9xRStX25wkV3SVpjK1sXTeL%252FRmPuAovBL5dsaTDCFJSnwaDfNhxXXdZq%252BLZ1fGU8GxBHxJweVVONRvvnySDkyOV0P1EOf8fHAEx5vPnzPLSvnB4dJGAhzGbJAJFJnvDFGo9gBuzduaetsf4PHmOJc6APybfPkzDz6N%252Bd%252BPB3Lq85fh46PzJfbxvXn9Gw%253D%253D%26RelayState%3Dfc4b5fad-76fd-49d2-841b-b5cd39568029%26SigAlg%3Dhttp%253A%252F%252Fwww.w3.org%252F2001%252F04%252Fxmldsig-more%2523rsa-sha256%26Signature%3DjEVAVmY1XMMuNt2GJ%252BoaN6FaGj6ACZokOfme1OmkBiCPJyr%252B4rsg%252BrajIyMtSoUbtOoOaH63g1JP%250AqT7Wc%252Bucd%252FLcEYf7qU%252FJKN2uTMvssQblsSKuPHOWLJQUKPZHiSPA67%252F9JZhov8FXYM9uBYSs1Far%250AMRBpM49o1m1pRzwOKx3%252FcwOqc%252BT5mOWM78tNOj37mFFzwDTGuoB9iE2cZCUu1wfBbTPIvRZ2ND8Y%250AVYEO5FdR8W0sLR9LNOVjm64D%252Fl9u%252FjFJXntW4CPRPXiOiCr7TLlnFWVxXOTwywF5LTyLYQR5OjwB%250AK3cWmRPkN6OAejN%252F3Su3nWHDlGttrZuZBYzfag%253D%253D")); + QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Ftest.governikus-eid.de%2Fgov_autent%2Fasync%3FSAMLRequest%3DnVbZsppIGH4Vi7m0lEURsI4nBbIcV1TA7SbF0myy0wj49NMeTXIySWYyueTvf%252FuWrublUxNHnSsoyiBNJhjZJ7AOSOzUCRJvghm63GOxT68vpRlHVDbmK%252BgnO5BXoIQdVJiU48fJBKuKZJyaZVCOEzMG5RjaY41fLcdUnxhnRQpTO42wDl%252BWoIBo1DRNyioGhQaKa2ADY7ecYD6EWTnG8bqu3X50jfsOwJPMvA%252FFgZ3Gn9HHPYAXoMxQPcA6IlokSMx7x2%252F1EAX7XopAJcGlKnsgcO6tUOSzWUGQQNws28TGOjNxgjG2NaBphu3RnEX1hiQDepwzGvVIa8S6nM3ZBHBRZllWYJaU0EzgBKMIctQj2B7J6iQ1HpBjiukTLHPGOpsivQYOKNaIg58Cwjr7L1wjZrAns%252BP3%252FsVHSv%252BdUfMLj9jrT1h7wd9VeXb9qp7UIPB3ncvXF8TJWErsos0gcD7K%252BjXpuQxKfABBwlhl0Leq5J1NMBNxtH6DzPKtkWhC81l3P%252FhaiBTt14N%252BWng4RRAkTgxx5B6U8RfW0dvsSdVD%252Bl8kShGIkXT%252FGInArAD0U6fDR15aBNCPf2OoCUqSYnu2hTzwcPHvbou%252FvjjleAHaWeKmz1qn%252FMVIAie4O06nDLy%252FfuAKNfmfw79n%252B8%252BgF6XZIz%252FTGALyLt00yHxQ3HX7LrA3owq8nqchd%252FChs84FcV%252F7K2XeNSNam7c1zXHmaE01PIgXcC8dVEkwOF9cgKS6Gjw7z%252Fcm301Gy4G2U3ldYZNjokPNXknswARRE1X1eWSDZvgGGUNwzhS6g1yrGsui1cBFSMJwF8Do1rihPLyZPH%252B7haovT4eaFrDbAcB3ah6G24xiVGFr5%252BUlOxlvuORmrFaQuzIHyvE257rT0Qpe9xqlVeAYWIGhioZiWWcoRnVIadR5YbORNmUAawRruznL%252FsUN8GCjjEA7mpmLnAqrZRU5i22Sd91An2blxp2R7IY6VLcisRwhJslgyKjEleEbMO9yF4m4bQapCs8jnWblM6WpFru02fDCevopWnteylL1ZPKCf%252BD%252BQfV3oYccj6SvlxT5BcW%252Bue8HAf%252FMTQ8DPJYQZXuh7SMTD8zuydusrZJf86WxyozjgobSkWfDkMn5S3d7mFJTXKWEkXuKdWKGFnXOQrbYJwodtcXONjyt686N5T4ZCOtpO4PeJiLo0PDieXdIzt11lzLndd4KjLqkY3kqH287U2svdeN6852480LvYm4vTEUXbN0FOKMUtroeXtdRGHOncHqMtZTJcvEircycDWNFy89VumWnqsTBvT7jo60ypUYbLTkt97nbGOvGJm1wahNDk5q3Q93qNVgufWV6s66GlTnbzDVxejiq7ThcNUqs3FyfVmVCYbeOElnXzU0JL7wtIefm1Wwv4%252FQZF%252Bp0mCa6tiVO8qI2Z7kx8KKteIipPN7dToNqFzCU7s9xRStX25wkV3SVpjK1sXTeL%252FRmPuAovBL5dsaTDCFJSnwaDfNhxXXdZq%252BLZ1fGU8GxBHxJweVVONRvvnySDkyOV0P1EOf8fHAEx5vPnzPLSvnB4dJGAhzGbJAJFJnvDFGo9gBuzduaetsf4PHmOJc6APybfPkzDz6N%252Bd%252BPB3Lq85fh46PzJfbxvXn9Gw%253D%253D%26RelayState%3Dfc4b5fad-76fd-49d2-841b-b5cd39568029%26SigAlg%3Dhttp%253A%252F%252Fwww.w3.org%252F2001%252F04%252Fxmldsig-more%2523rsa-sha256%26Signature%3DjEVAVmY1XMMuNt2GJ%252BoaN6FaGj6ACZokOfme1OmkBiCPJyr%252B4rsg%252BrajIyMtSoUbtOoOaH63g1JP%250AqT7Wc%252Bucd%252FLcEYf7qU%252FJKN2uTMvssQblsSKuPHOWLJQUKPZHiSPA67%252F9JZhov8FXYM9uBYSs1Far%250AMRBpM49o1m1pRzwOKx3%252FcwOqc%252BT5mOWM78tNOj37mFFzwDTGuoB9iE2cZCUu1wfBbTPIvRZ2ND8Y%250AVYEO5FdR8W0sLR9LNOVjm64D%252Fl9u%252FjFJXntW4CPRPXiOiCr7TLlnFWVxXOTwywF5LTyLYQR5OjwB%250AK3cWmRPkN6OAejN%252F3Su3nWHDlGttrZuZBYzfag%253D%253D"_L1)); } @@ -260,7 +260,7 @@ class test_MsgHandlerAuth { const QSharedPointer context(new AuthContext()); context->setStatus(GlobalStatus::Code::No_Error); - context->setRefreshUrl(QUrl("http://www.governikus.de")); + context->setRefreshUrl(QUrl("http://www.governikus.de"_L1)); MsgHandlerAuth msg(context); QCOMPARE(msg.toJson(), QByteArray("{\"msg\":\"AUTH\",\"result\":{\"major\":\"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok\"},\"url\":\"http://www.governikus.de\"}")); } @@ -295,15 +295,15 @@ class test_MsgHandlerAuth void iosScanDialogMessages() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); const auto& initialMessages = Env::getSingleton()->getMessages(); @@ -313,7 +313,7 @@ class test_MsgHandlerAuth QVERIFY(initialMessages.getSessionFailed().isEmpty()); QVERIFY(!initialMessages.getSessionFailed().isNull()); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -325,7 +325,7 @@ class test_MsgHandlerAuth return false; }); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -350,7 +350,7 @@ class test_MsgHandlerAuth QCOMPARE(request->getAction(), Action::AUTH); QVERIFY(request->getContext().objectCast()); QCOMPARE(request->getContext().objectCast()->getActivationUrl(), - QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc")); + QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc"_L1)); QTRY_COMPARE(spyStarted.count(), 1); // clazy:exclude=qstring-allocations auto messages = Env::getSingleton()->getMessages(); @@ -388,7 +388,7 @@ class test_MsgHandlerAuth void handleInterrupt() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, handleInterrupt); QFETCH(bool, handleInterruptExpected); @@ -396,16 +396,16 @@ class test_MsgHandlerAuth bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -417,8 +417,8 @@ class test_MsgHandlerAuth return false; }); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -442,7 +442,7 @@ class test_MsgHandlerAuth QCOMPARE(request->getAction(), Action::AUTH); QVERIFY(request->getContext().objectCast()); QCOMPARE(request->getContext().objectCast()->getActivationUrl(), - QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc")); + QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc"_L1)); QTRY_COMPARE(spyStarted.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(Env::getSingleton()->handleInterrupt(), handleInterruptExpected); @@ -468,23 +468,23 @@ class test_MsgHandlerAuth void handleInterruptDefault() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(bool, handleInterruptExpected); QFETCH(char, apiLevel); bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -496,8 +496,8 @@ class test_MsgHandlerAuth return false; }); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -537,23 +537,23 @@ class test_MsgHandlerAuth void handleDeveloperMode() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, developerMode); bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QCOMPARE(Env::getSingleton()->isDeveloperMode(), false); // default QCOMPARE(Env::getSingleton()->getGeneralSettings().isDeveloperMode(), false); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -565,7 +565,7 @@ class test_MsgHandlerAuth return false; }); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -588,7 +588,7 @@ class test_MsgHandlerAuth QCOMPARE(workFlowRequest->getAction(), Action::AUTH); auto authContext = workFlowRequest->getContext().objectCast(); auto url = authContext->getActivationUrl(); - QCOMPARE(url, QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc")); + QCOMPARE(url, QUrl("http://localhost/?tcTokenURL=https%3A%2F%2Flocalhost%2Ftoken%3Fsession%3D123abc"_L1)); QTRY_COMPARE(spyStarted.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(Env::getSingleton()->isDeveloperMode(), developerMode.toBool()); diff --git a/test/qt/ui/json/test_MsgHandlerCertificate.cpp b/test/qt/ui/json/test_MsgHandlerCertificate.cpp index 9a9531290..0fdee9fc4 100644 --- a/test/qt/ui/json/test_MsgHandlerCertificate.cpp +++ b/test/qt/ui/json/test_MsgHandlerCertificate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include "TestAuthContext.h" #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_MsgHandlerCertificate @@ -23,7 +24,7 @@ class test_MsgHandlerCertificate QSharedPointer getContext() { - QSharedPointer context(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + QSharedPointer context(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); context->setRequiredAccessRights({AccessRight::READ_DG01}); context->setOptionalAccessRights({AccessRight::AGE_VERIFICATION}); return context; diff --git a/test/qt/ui/json/test_MsgHandlerChangePin.cpp b/test/qt/ui/json/test_MsgHandlerChangePin.cpp index 0c4a61da2..2df1b6d98 100644 --- a/test/qt/ui/json/test_MsgHandlerChangePin.cpp +++ b/test/qt/ui/json/test_MsgHandlerChangePin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,8 +10,8 @@ #include "Env.h" #include "MessageDispatcher.h" -#include "UILoader.h" -#include "UIPlugInJson.h" +#include "UiLoader.h" +#include "UiPluginJson.h" #include "VolatileSettings.h" #include "controller/AppController.h" @@ -20,7 +20,7 @@ #include #include -Q_IMPORT_PLUGIN(UIPlugInJson) +Q_IMPORT_PLUGIN(UiPluginJson) using namespace governikus; @@ -34,7 +34,7 @@ class test_MsgHandlerChangePin { qRegisterMetaType>("QSharedPointer"); - connect(Env::getSingleton(), &UILoader::fireLoadedPlugin, this, [](UIPlugIn* pUi){ + connect(Env::getSingleton(), &UiLoader::fireLoadedPlugin, this, [](UiPlugin* pUi){ pUi->setProperty("passive", QVariant()); // fake active UI for AppController::start }); } @@ -42,10 +42,10 @@ class test_MsgHandlerChangePin void cleanup() { - auto* uiLoader = Env::getSingleton(); + auto* uiLoader = Env::getSingleton(); if (uiLoader->isLoaded()) { - QSignalSpy spyUi(uiLoader, &UILoader::fireRemovedAllPlugins); + QSignalSpy spyUi(uiLoader, &UiLoader::fireRemovedAllPlugins); uiLoader->shutdown(); QTRY_COMPARE(spyUi.count(), 1); // clazy:exclude=qstring-allocations } @@ -54,10 +54,10 @@ class test_MsgHandlerChangePin void runChangePinCmd() { - QVERIFY(Env::getSingleton()->load()); - auto ui = Env::getSingleton()->getLoaded(); + QVERIFY(Env::getSingleton()->load()); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); - QSignalSpy spy(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spy(ui, &UiPlugin::fireWorkflowRequested); MessageDispatcher dispatcher; const QByteArray msg = R"({"cmd": "RUN_CHANGE_PIN"})"; @@ -110,13 +110,13 @@ class test_MsgHandlerChangePin void cancelChangePin() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); @@ -136,9 +136,9 @@ class test_MsgHandlerChangePin void iosScanDialogMessages() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); @@ -149,14 +149,14 @@ class test_MsgHandlerChangePin QVERIFY(initialMessages.getSessionFailed().isEmpty()); QVERIFY(!initialMessages.getSessionFailed().isNull()); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); const QByteArray msg("{" @@ -207,27 +207,27 @@ class test_MsgHandlerChangePin void handleInterrupt() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, handleInterrupt); QFETCH(bool, handleInterruptExpected); QFETCH(char, apiLevel); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QByteArray msgApiLevel = R"({"cmd": "SET_API_LEVEL", "level": *})"; @@ -268,26 +268,26 @@ class test_MsgHandlerChangePin void handleInterruptDefault() { - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(bool, handleInterruptExpected); QFETCH(char, apiLevel); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QByteArray msgApiLevel = R"({"cmd": "SET_API_LEVEL", "level": *})"; diff --git a/test/qt/ui/json/test_MsgHandlerEnterCan.cpp b/test/qt/ui/json/test_MsgHandlerEnterCan.cpp index feaf03b21..8a796c1f4 100644 --- a/test/qt/ui/json/test_MsgHandlerEnterCan.cpp +++ b/test/qt/ui/json/test_MsgHandlerEnterCan.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,12 +13,12 @@ #include "MessageDispatcher.h" #include "ReaderManager.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) using namespace governikus; @@ -38,7 +38,7 @@ class test_MsgHandlerEnterCan private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -53,7 +53,7 @@ class test_MsgHandlerEnterCan void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } diff --git a/test/qt/ui/json/test_MsgHandlerEnterNewPin.cpp b/test/qt/ui/json/test_MsgHandlerEnterNewPin.cpp index 033a3ef1d..fb50cbc07 100644 --- a/test/qt/ui/json/test_MsgHandlerEnterNewPin.cpp +++ b/test/qt/ui/json/test_MsgHandlerEnterNewPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,15 +18,19 @@ #include "context/PersonalizationContext.h" #endif -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) + + +using namespace Qt::Literals::StringLiterals; using namespace governikus; + Q_DECLARE_METATYPE(QSharedPointer) @@ -48,7 +52,7 @@ class test_MsgHandlerEnterNewPin private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -63,7 +67,7 @@ class test_MsgHandlerEnterNewPin void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } @@ -143,7 +147,7 @@ class test_MsgHandlerEnterNewPin QTest::newRow("ChangePinContext") << QSharedPointer::create().objectCast(); #if __has_include("context/PersonalizationContext.h") - QTest::newRow("PersonalizationContext") << QSharedPointer::create(QString("dummy")).objectCast(); + QTest::newRow("PersonalizationContext") << QSharedPointer::create("dummy"_L1).objectCast(); #endif } diff --git a/test/qt/ui/json/test_MsgHandlerEnterPin.cpp b/test/qt/ui/json/test_MsgHandlerEnterPin.cpp index a920d0712..97ddcb484 100644 --- a/test/qt/ui/json/test_MsgHandlerEnterPin.cpp +++ b/test/qt/ui/json/test_MsgHandlerEnterPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,12 +14,12 @@ #include "ReaderManager.h" #include "context/ChangePinContext.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) using namespace governikus; @@ -39,7 +39,7 @@ class test_MsgHandlerEnterPin private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -54,7 +54,7 @@ class test_MsgHandlerEnterPin void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } diff --git a/test/qt/ui/json/test_MsgHandlerEnterPuk.cpp b/test/qt/ui/json/test_MsgHandlerEnterPuk.cpp index 151559a15..3272bc456 100644 --- a/test/qt/ui/json/test_MsgHandlerEnterPuk.cpp +++ b/test/qt/ui/json/test_MsgHandlerEnterPuk.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,12 +13,12 @@ #include "MessageDispatcher.h" #include "ReaderManager.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) using namespace governikus; @@ -38,7 +38,7 @@ class test_MsgHandlerEnterPuk private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -53,7 +53,7 @@ class test_MsgHandlerEnterPuk void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } diff --git a/test/qt/ui/json/test_MsgHandlerInfo.cpp b/test/qt/ui/json/test_MsgHandlerInfo.cpp index 5769ad479..960cd7c0d 100644 --- a/test/qt/ui/json/test_MsgHandlerInfo.cpp +++ b/test/qt/ui/json/test_MsgHandlerInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,13 +9,13 @@ #include "messages/MsgHandlerInfo.h" #include "MessageDispatcher.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "VersionInfo.h" #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) using namespace governikus; @@ -29,7 +29,7 @@ class test_MsgHandlerInfo private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -57,21 +57,6 @@ class test_MsgHandlerInfo } - void localIfd() - { - const QByteArray msg(R"({"cmd": "GET_INFO"})"); - MessageDispatcher dispatcher; - auto versionInfo = VersionInfo::getInstance().toJson(QJsonDocument::Compact); - - const auto& result = dispatcher.processCommand(msg); - QCOMPARE(result, MsgType::INFO); - const QByteArray data = result; - QVERIFY(data.contains(versionInfo)); - QVERIFY(data.contains(R"("msg":"INFO")")); - QVERIFY(data.contains(R"("AusweisApp")")); - } - - }; QTEST_GUILESS_MAIN(test_MsgHandlerInfo) diff --git a/test/qt/ui/json/test_MsgHandlerInsertCard.cpp b/test/qt/ui/json/test_MsgHandlerInsertCard.cpp index 62e4bea0c..b8d1f4fe5 100644 --- a/test/qt/ui/json/test_MsgHandlerInsertCard.cpp +++ b/test/qt/ui/json/test_MsgHandlerInsertCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,7 +9,7 @@ #include "messages/MsgHandlerInsertCard.h" #include "MessageDispatcher.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "states/StateSelectReader.h" @@ -19,8 +19,9 @@ #include #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_MsgHandlerInsertCard @@ -37,7 +38,7 @@ class test_MsgHandlerInsertCard private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -52,7 +53,7 @@ class test_MsgHandlerInsertCard void cleanup() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); } @@ -81,9 +82,9 @@ class test_MsgHandlerInsertCard void readerWithoutCard() { - MockReaderManagerPlugIn::getInstance().addReader("MockReader 1"); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 2"); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 3"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 1"_L1); + MockReaderManagerPlugin::getInstance().addReader("MockReader 2"_L1); + MockReaderManagerPlugin::getInstance().addReader("MockReader 3"_L1); MessageDispatcher dispatcher; setContext(dispatcher); @@ -94,8 +95,8 @@ class test_MsgHandlerInsertCard void readerWithCard() { - MockReaderManagerPlugIn::getInstance().addReader("MockReader 1"); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader CARD"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 1"_L1); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader CARD"_L1); reader->setCard(MockCardConfig()); MessageDispatcher dispatcher; @@ -126,12 +127,12 @@ class test_MsgHandlerInsertCard msg = R"({"cmd": "SET_CARD", "name": false})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"error":"Invalid name","msg":"INSERT_CARD"})")); - MockReaderManagerPlugIn::getInstance().addReader("MockReaderNfc", ReaderManagerPlugInType::NFC); + MockReaderManagerPlugin::getInstance().addReader("MockReaderNfc"_L1, ReaderManagerPluginType::NFC); msg = R"({"cmd": "SET_CARD", "name": "dummy"})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"error":"Unknown reader name","msg":"INSERT_CARD"})")); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReaderSmart", ReaderManagerPlugInType::SMART); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReaderSmart"_L1, ReaderManagerPluginType::SMART); msg = R"({"cmd": "SET_CARD", "name": "MockReaderSmart"})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"error":"Card is not insertable","msg":"INSERT_CARD"})")); @@ -151,7 +152,7 @@ class test_MsgHandlerInsertCard setContext(dispatcher); QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray(R"({"msg":"INSERT_CARD"})")); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReaderSimulator", ReaderManagerPlugInType::SIMULATOR); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReaderSimulator"_L1, ReaderManagerPluginType::SIMULATOR); auto info = reader->getReaderInfo(); info.setCardInfo(CardInfo(CardType::EID_CARD)); info.shelveCard(); diff --git a/test/qt/ui/json/test_MsgHandlerInternalError.cpp b/test/qt/ui/json/test_MsgHandlerInternalError.cpp index 517b71b15..cd2dc5761 100644 --- a/test/qt/ui/json/test_MsgHandlerInternalError.cpp +++ b/test/qt/ui/json/test_MsgHandlerInternalError.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ui/json/test_MsgHandlerPause.cpp b/test/qt/ui/json/test_MsgHandlerPause.cpp new file mode 100644 index 000000000..5a04b8f7e --- /dev/null +++ b/test/qt/ui/json/test_MsgHandlerPause.cpp @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "MessageDispatcher.h" +#include "MockReaderManagerPlugin.h" +#include "ReaderManager.h" +#include "states/StateSelectReader.h" +#include "states/StateUnfortunateCardPosition.h" + +#include "TestWorkflowContext.h" + +#include +#include +#include + +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + +class test_MsgHandlerPause + : public QObject +{ + Q_OBJECT + + static void setContext(MessageDispatcher& pDispatcher) + { + QSharedPointer context(new TestWorkflowContext()); + QCOMPARE(pDispatcher.init(context), MsgType::VOID); + } + + private Q_SLOTS: + void initTestCase() + { + auto* readerManager = Env::getSingleton(); + QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); + readerManager->init(); + QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations + } + + + void cleanupTestCase() + { + Env::getSingleton()->shutdown(); + } + + + void unfortunateCardPosition() + { + QSharedPointer context(new TestWorkflowContext()); + MessageDispatcher dispatcher; + QCOMPARE(dispatcher.init(context), MsgType::VOID); + + QByteArray msg(R"({"cmd": "SET_API_LEVEL", "level": 1})"); + QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"current":1,"msg":"API_LEVEL"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray()); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray()); + + msg = (R"({"cmd": "SET_API_LEVEL", "level": 2})"); + QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"current":2,"msg":"API_LEVEL"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray()); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray()); + + msg = (R"({"cmd": "SET_API_LEVEL", "level": 3})"); + QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"current":3,"msg":"API_LEVEL"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray(R"({"cause":"BadCardPosition","msg":"PAUSE"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray(R"({"cause":"BadCardPosition","msg":"PAUSE"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray(R"({"msg":"INSERT_CARD"})")); + QCOMPARE(QByteArray(dispatcher.processCommand(QByteArray(R"({"cmd":"CONTINUE"})"))), QByteArray(R"({"error":"CONTINUE","msg":"BAD_STATE"})")); + + context->setCurrentState(StateBuilder::generateStateName()); + QCOMPARE(dispatcher.processStateChange(StateBuilder::generateStateName()), QByteArray(R"({"cause":"BadCardPosition","msg":"PAUSE"})")); + QCOMPARE(QByteArray(dispatcher.processCommand(QByteArray(R"({"cmd":"CONTINUE"})"))), QByteArray()); + } + + +}; + +QTEST_GUILESS_MAIN(test_MsgHandlerPause) +#include "test_MsgHandlerPause.moc" diff --git a/test/qt/ui/json/test_MsgHandlerPersonalization.cpp b/test/qt/ui/json/test_MsgHandlerPersonalization.cpp index e0d135ccf..0dc302303 100644 --- a/test/qt/ui/json/test_MsgHandlerPersonalization.cpp +++ b/test/qt/ui/json/test_MsgHandlerPersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,8 +11,8 @@ #include "AppSettings.h" #include "MessageDispatcher.h" #include "ReaderManager.h" -#include "UILoader.h" -#include "UIPlugInJson.h" +#include "UiLoader.h" +#include "UiPluginJson.h" #include "VolatileSettings.h" #include "WorkflowRequest.h" #include "controller/AppController.h" @@ -25,10 +25,11 @@ #include -Q_IMPORT_PLUGIN(UIPlugInJson) -Q_IMPORT_PLUGIN(SmartReaderManagerPlugIn) +Q_IMPORT_PLUGIN(UiPluginJson) +Q_IMPORT_PLUGIN(SmartReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -50,15 +51,15 @@ class test_MsgHandlerPersonalization setSmartEidStatus(EidStatus::NO_PERSONALIZATION); qRegisterMetaType>("QSharedPointer"); - const auto& readerManager = Env::getSingleton(); - connect(readerManager, &ReaderManager::firePluginAdded, this, [this](const ReaderManagerPlugInInfo& pInfo) { - if (pInfo.getPlugInType() == ReaderManagerPlugInType::SMART && pInfo.isAvailable()) + const auto* readerManager = Env::getSingleton(); + connect(readerManager, &ReaderManager::firePluginAdded, this, [this](const ReaderManagerPluginInfo& pInfo) { + if (pInfo.getPluginType() == ReaderManagerPluginType::SMART && pInfo.isAvailable()) { mSmartAvailable = true; } }); - connect(Env::getSingleton(), &UILoader::fireLoadedPlugin, this, [](UIPlugIn* pUi){ + connect(Env::getSingleton(), &UiLoader::fireLoadedPlugin, this, [](UiPlugin* pUi){ pUi->setProperty("passive", QVariant()); // fake active UI for AppController::start }); } @@ -66,10 +67,10 @@ class test_MsgHandlerPersonalization void cleanup() { - auto* uiLoader = Env::getSingleton(); + auto* uiLoader = Env::getSingleton(); if (uiLoader->isLoaded()) { - QSignalSpy spyUi(uiLoader, &UILoader::fireRemovedAllPlugins); + QSignalSpy spyUi(uiLoader, &UiLoader::fireRemovedAllPlugins); uiLoader->shutdown(); QTRY_COMPARE(spyUi.count(), 1); // clazy:exclude=qstring-allocations } @@ -130,10 +131,10 @@ class test_MsgHandlerPersonalization void runPersoCmd() { - QVERIFY(Env::getSingleton()->load()); - auto jsonUi = Env::getSingleton()->getLoaded(); + QVERIFY(Env::getSingleton()->load()); + auto jsonUi = Env::getSingleton()->getLoaded(); QVERIFY(jsonUi); - QSignalSpy spy(jsonUi, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spy(jsonUi, &UiPlugin::fireWorkflowRequested); MessageDispatcher dispatcher; QByteArray msg = R"({"cmd": "RUN_PERSONALIZATION", "appletServiceURL": "https://www.governikus.de/token/%1"})"; @@ -147,7 +148,7 @@ class test_MsgHandlerPersonalization QCOMPARE(request->getAction(), Action::PERSONALIZATION); QVERIFY(request->getContext().objectCast()); QCOMPARE(request->getContext().objectCast()->getAppletServiceUrl(QStringLiteral("testMe")), - QUrl("https://www.governikus.de/token/testMe")); + QUrl("https://www.governikus.de/token/testMe"_L1)); #else QCOMPARE(dispatcher.processCommand(msg), QByteArray(R"({"error":"RUN_PERSONALIZATION","msg":"UNKNOWN_COMMAND"})")); @@ -189,7 +190,7 @@ class test_MsgHandlerPersonalization #if __has_include("context/PersonalizationContext.h") const auto& ctx = QSharedPointer::create(QString()); ctx->setStatus(GlobalStatus::Code::No_Error); - ctx->setRefreshUrl(QUrl("http://www.governikus.de")); // not provided in PERSONALIZATION, like in AUTH + ctx->setRefreshUrl(QUrl("http://www.governikus.de"_L1)); // not provided in PERSONALIZATION, like in AUTH MsgHandlerPersonalization msg(ctx); QByteArray response = R"({"msg":"PERSONALIZATION","result":{"major":"http://www.bsi.bund.de/ecard/api/1.1/resultmajor#ok"}})"; @@ -231,13 +232,13 @@ class test_MsgHandlerPersonalization bool reachedStateGetTcToken = false; #if __has_include("context/PersonalizationContext.h") - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QTRY_VERIFY(mSmartAvailable); // clazy:exclude=qstring-allocations @@ -249,7 +250,7 @@ class test_MsgHandlerPersonalization QVERIFY(initialMessages.getSessionFailed().isEmpty()); QVERIFY(!initialMessages.getSessionFailed().isNull()); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -261,7 +262,7 @@ class test_MsgHandlerPersonalization return false; }); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -326,7 +327,7 @@ class test_MsgHandlerPersonalization void handleInterrupt() { #if __has_include("context/PersonalizationContext.h") - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, handleInterrupt); QFETCH(bool, handleInterruptExpected); @@ -334,18 +335,18 @@ class test_MsgHandlerPersonalization bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QTRY_VERIFY(mSmartAvailable); // clazy:exclude=qstring-allocations QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -357,8 +358,8 @@ class test_MsgHandlerPersonalization return false; }); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -410,25 +411,25 @@ class test_MsgHandlerPersonalization void handleInterruptDefault() { #if __has_include("context/PersonalizationContext.h") - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(bool, handleInterruptExpected); QFETCH(char, apiLevel); bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QTRY_VERIFY(mSmartAvailable); // clazy:exclude=qstring-allocations QCOMPARE(Env::getSingleton()->handleInterrupt(), false); // default - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -440,8 +441,8 @@ class test_MsgHandlerPersonalization return false; }); - QSignalSpy spyMessage(ui, &UIPlugInJson::fireMessage); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyMessage(ui, &UiPluginJson::fireMessage); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); @@ -485,17 +486,17 @@ class test_MsgHandlerPersonalization void handleDeveloperMode() { #if __has_include("context/PersonalizationContext.h") - QVERIFY(!Env::getSingleton()->isLoaded()); + QVERIFY(!Env::getSingleton()->isLoaded()); QFETCH(QVariant, developerMode); bool reachedStateGetTcToken = false; - UILoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("json")}); AppController controller; controller.start(); connect(&controller, &AppController::fireWorkflowStarted, this, [this](const QSharedPointer& pRequest){ - pRequest->getContext()->claim(this); // UIPlugInJson is internal API and does not claim by itself + pRequest->getContext()->claim(this); // UiPluginJson is internal API and does not claim by itself }); QTRY_VERIFY(mSmartAvailable); // clazy:exclude=qstring-allocations @@ -503,7 +504,7 @@ class test_MsgHandlerPersonalization QCOMPARE(Env::getSingleton()->isDeveloperMode(), false); // default QCOMPARE(Env::getSingleton()->getGeneralSettings().isDeveloperMode(), false); - auto ui = Env::getSingleton()->getLoaded(); + auto ui = Env::getSingleton()->getLoaded(); QVERIFY(ui); ui->setEnabled(true); ui->mMessageDispatcher.setSkipStateApprovedHook([&reachedStateGetTcToken](const QString& pState){ @@ -515,7 +516,7 @@ class test_MsgHandlerPersonalization return false; }); - QSignalSpy spyUi(ui, &UIPlugIn::fireWorkflowRequested); + QSignalSpy spyUi(ui, &UiPlugin::fireWorkflowRequested); QSignalSpy spyStarted(&controller, &AppController::fireWorkflowStarted); QSignalSpy spyFinished(&controller, &AppController::fireWorkflowFinished); diff --git a/test/qt/ui/json/test_MsgHandlerReader.cpp b/test/qt/ui/json/test_MsgHandlerReader.cpp index b1b0c0b0e..8c85e4df3 100644 --- a/test/qt/ui/json/test_MsgHandlerReader.cpp +++ b/test/qt/ui/json/test_MsgHandlerReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,14 +9,15 @@ #include "messages/MsgHandlerReader.h" #include "MessageDispatcher.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "TestFileHelper.h" #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(ReaderInfo) @@ -35,7 +36,7 @@ class test_MsgHandlerReader private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -50,15 +51,15 @@ class test_MsgHandlerReader void ctor() { - QSignalSpy spy(&MockReaderManagerPlugIn::getInstance(), &ReaderManagerPlugIn::fireReaderAdded); - MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + QSignalSpy spy(&MockReaderManagerPlugin::getInstance(), &ReaderManagerPlugin::fireReaderAdded); + MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); QCOMPARE(spy.count(), 1); ReaderInfo info = qvariant_cast(spy.takeFirst().at(0)); - MsgHandlerReader noReader(ReaderInfo("MockReader")); + MsgHandlerReader noReader(ReaderInfo("MockReader"_L1), MsgContext()); QCOMPARE(noReader.toJson(), QByteArray("{\"attached\":false,\"msg\":\"READER\",\"name\":\"MockReader\"}")); - MsgHandlerReader reader(info); + MsgHandlerReader reader(info, MsgContext()); QCOMPARE(reader.toJson(), QByteArray("{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"MockReader 0815\"}")); } @@ -76,7 +77,7 @@ class test_MsgHandlerReader void oneReaderWithoutCard() { - MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); MessageDispatcher dispatcher; QByteArray msg(R"({"cmd": "GET_READER", "name": "MockReader 081"})"); @@ -85,7 +86,7 @@ class test_MsgHandlerReader msg = R"({"cmd": "GET_READER", "name": "MockReader 0815"})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"MockReader 0815\"}")); - MockReaderManagerPlugIn::getInstance().removeReader("MockReader 0815"); + MockReaderManagerPlugin::getInstance().removeReader("MockReader 0815"_L1); msg = R"({"cmd": "GET_READER", "name": "MockReader 0815"})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":false,\"msg\":\"READER\",\"name\":\"MockReader 0815\"}")); } @@ -93,7 +94,7 @@ class test_MsgHandlerReader void oneReaderWithCard() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); reader->setCard(MockCardConfig()); MessageDispatcher dispatcher; @@ -102,28 +103,43 @@ class test_MsgHandlerReader } + void multipleReaderWithCard_data() + { + QTest::addColumn("msgLevel"); + + QTest::newRow("v2") << MsgLevel::v2; + QTest::newRow("v3") << MsgLevel::v3; + } + + void multipleReaderWithCard() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + QFETCH(MsgLevel, msgLevel); + + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); reader->setCard(MockCardConfig()); - reader = MockReaderManagerPlugIn::getInstance().addReader("ReaderMock"); + reader = MockReaderManagerPlugin::getInstance().addReader("ReaderMock"_L1); reader->setCard(MockCardConfig()); - MockReaderManagerPlugIn::getInstance().addReader("ReaderMockXYZ"); + MockReaderManagerPlugin::getInstance().addReader("ReaderMockXYZ"_L1); - reader = MockReaderManagerPlugIn::getInstance().addReader("SpecialMock"); + reader = MockReaderManagerPlugin::getInstance().addReader("SpecialMock"_L1); reader->setCard(MockCardConfig()); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(CardInfo(CardType::UNKNOWN)); reader->setReaderInfo(info); - reader = MockReaderManagerPlugIn::getInstance().addReader("SpecialMockWithGermanCard"); + reader = MockReaderManagerPlugin::getInstance().addReader("SpecialMockWithGermanCard"_L1); reader->setCard(MockCardConfig()); - auto cardInfo = CardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + auto cardInfo = CardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); MessageDispatcher dispatcher; + QByteArray setApiLevel(R"({"cmd": "SET_API_LEVEL", "level": })"); + setApiLevel.replace(QByteArray(""), QByteArray::number(Enum::getValue(msgLevel))); + Q_UNUSED(dispatcher.processCommand(setApiLevel)) + QByteArray msg(R"({"cmd": "GET_READER", "name": "MockReader 0815"})"); QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":true,\"card\":{\"deactivated\":false," + mEidType + "\"inoperative\":false,\"retryCounter\":-1},\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"MockReader 0815\"}")); @@ -134,7 +150,9 @@ class test_MsgHandlerReader QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"ReaderMockXYZ\"}")); msg = R"({"cmd": "GET_READER", "name": "SpecialMock"})"; - QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"SpecialMock\"}")); + QByteArray expected("{\"attached\":true,\"card\":,\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"SpecialMock\"}"); + expected.replace("", msgLevel > MsgLevel::v2 ? "{}" : "null"); + QCOMPARE(dispatcher.processCommand(msg), expected); msg = R"({"cmd": "GET_READER", "name": "SpecialMockWithGermanCard"})"; QCOMPARE(dispatcher.processCommand(msg), QByteArray("{\"attached\":true,\"card\":{\"deactivated\":true," + mEidType + "\"inoperative\":false,\"retryCounter\":3},\"insertable\":false,\"keypad\":false,\"msg\":\"READER\",\"name\":\"SpecialMockWithGermanCard\"}")); @@ -147,8 +165,8 @@ class test_MsgHandlerReader QTest::addColumn("efCardAccess"); QTest::addColumn("eidType"); - QTest::newRow("CARD_CERTIFIED") << TestFileHelper::readFile(":/card/efCardAccess.hex") << QByteArray("CARD_CERTIFIED"); - QTest::newRow("SE_ENDORSED") << TestFileHelper::readFile(":/card/smartEfCardAccess.hex") << QByteArray("SE_ENDORSED"); + QTest::newRow("CARD_CERTIFIED") << TestFileHelper::readFile(":/card/efCardAccess.hex"_L1) << QByteArray("CARD_CERTIFIED"); + QTest::newRow("SE_ENDORSED") << TestFileHelper::readFile(":/card/smartEfCardAccess.hex"_L1) << QByteArray("SE_ENDORSED"); } @@ -157,7 +175,7 @@ class test_MsgHandlerReader QFETCH(QByteArray, efCardAccess); QFETCH(QByteArray, eidType); - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); reader->setCard(MockCardConfig(), EFCardAccess::decode(QByteArray::fromHex(efCardAccess)), CardType::SMART_EID); MessageDispatcher dispatcher; diff --git a/test/qt/ui/json/test_MsgHandlerReaderList.cpp b/test/qt/ui/json/test_MsgHandlerReaderList.cpp index f13bad455..f76579a0c 100644 --- a/test/qt/ui/json/test_MsgHandlerReaderList.cpp +++ b/test/qt/ui/json/test_MsgHandlerReaderList.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -7,14 +7,15 @@ */ #include "MessageDispatcher.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "messages/MsgHandlerReader.h" #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_MsgHandlerReaderList @@ -31,7 +32,7 @@ class test_MsgHandlerReaderList private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -66,7 +67,7 @@ class test_MsgHandlerReaderList void oneReaderWithoutCard() { - MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); MessageDispatcher dispatcher; QByteArray msg(R"({"cmd": "GET_READER_LIST"})"); @@ -76,7 +77,7 @@ class test_MsgHandlerReaderList void oneReaderWithCard() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); reader->setCard(MockCardConfig()); MessageDispatcher dispatcher; @@ -85,39 +86,53 @@ class test_MsgHandlerReaderList } + void multipleReaderWithCard_data() + { + QTest::addColumn("msgLevel"); + + QTest::newRow("v2") << MsgLevel::v2; + QTest::newRow("v3") << MsgLevel::v3; + } + + void multipleReaderWithCard() { - MockReader* reader = MockReaderManagerPlugIn::getInstance().addReader("MockReader 0815"); + QFETCH(MsgLevel, msgLevel); + + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); reader->setCard(MockCardConfig()); - reader = MockReaderManagerPlugIn::getInstance().addReader("ReaderMock"); + reader = MockReaderManagerPlugin::getInstance().addReader("ReaderMock"_L1); reader->setCard(MockCardConfig()); - MockReaderManagerPlugIn::getInstance().addReader("ReaderMockXYZ"); + MockReaderManagerPlugin::getInstance().addReader("ReaderMockXYZ"_L1); - reader = MockReaderManagerPlugIn::getInstance().addReader("SpecialMock"); + reader = MockReaderManagerPlugin::getInstance().addReader("SpecialMock"_L1); reader->setCard(MockCardConfig()); ReaderInfo info = reader->getReaderInfo(); info.setCardInfo(CardInfo(CardType::UNKNOWN)); reader->setReaderInfo(info); - reader = MockReaderManagerPlugIn::getInstance().addReader("SpecialMockWithGermanCard"); + reader = MockReaderManagerPlugin::getInstance().addReader("SpecialMockWithGermanCard"_L1); reader->setCard(MockCardConfig()); - auto cardInfo = CardInfo(CardType::EID_CARD, QSharedPointer(), 3, true); + auto cardInfo = CardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true); info = reader->getReaderInfo(); info.setCardInfo(cardInfo); reader->setReaderInfo(info); MessageDispatcher dispatcher; - QByteArray msg(R"({"cmd": "GET_READER_LIST"})"); + QByteArray setApiLevel(R"({"cmd": "SET_API_LEVEL", "level": })"); + setApiLevel.replace(QByteArray(""), QByteArray::number(Enum::getValue(msgLevel))); + Q_UNUSED(dispatcher.processCommand(setApiLevel)) + QByteArray msg(R"({"cmd": "GET_READER_LIST"})"); QByteArray expected("{\"msg\":\"READER_LIST\",\"readers\":[" "{\"attached\":true,\"card\":{\"deactivated\":false,\"inoperative\":false,\"retryCounter\":-1},\"insertable\":false,\"keypad\":false,\"name\":\"MockReader 0815\"}," "{\"attached\":true,\"card\":{\"deactivated\":false,\"inoperative\":false,\"retryCounter\":-1},\"insertable\":false,\"keypad\":false,\"name\":\"ReaderMock\"}," "{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"name\":\"ReaderMockXYZ\"}," - "{\"attached\":true,\"card\":null,\"insertable\":false,\"keypad\":false,\"name\":\"SpecialMock\"}," + "{\"attached\":true,\"card\":,\"insertable\":false,\"keypad\":false,\"name\":\"SpecialMock\"}," "{\"attached\":true,\"card\":{\"deactivated\":true,\"inoperative\":false,\"retryCounter\":3},\"insertable\":false,\"keypad\":false,\"name\":\"SpecialMockWithGermanCard\"}" "]}"); expected.replace("", mEidType); - + expected.replace("", msgLevel > MsgLevel::v2 ? "{}" : "null"); QCOMPARE(dispatcher.processCommand(msg), expected); } diff --git a/test/qt/ui/json/test_MsgHandlerStatus.cpp b/test/qt/ui/json/test_MsgHandlerStatus.cpp index 206398f4e..bf37db2f2 100644 --- a/test/qt/ui/json/test_MsgHandlerStatus.cpp +++ b/test/qt/ui/json/test_MsgHandlerStatus.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -27,6 +27,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_MsgHandlerStatus @@ -46,7 +47,7 @@ class test_MsgHandlerStatus private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -148,7 +149,7 @@ class test_MsgHandlerStatus void stateAccessRights() { - const QSharedPointer context(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + const QSharedPointer context(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); MessageDispatcher dispatcher; QCOMPARE(dispatcher.init(context), MsgType::AUTH); diff --git a/test/qt/ui/json/test_UIPlugInJson.cpp b/test/qt/ui/json/test_UIPlugInJson.cpp deleted file mode 100644 index 476ba0f5b..000000000 --- a/test/qt/ui/json/test_UIPlugInJson.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Unit tests for \ref UIPlugInJsonApi - */ - -#include "UIPlugInJson.h" - -#include "LogHandler.h" - -#include - -using namespace governikus; - -class test_UIPlugInJson - : public QObject -{ - Q_OBJECT - - private: - QJsonObject getJsonObject(const QByteArray& pData) - { - QJsonParseError jsonError {}; - const auto& json = QJsonDocument::fromJson(pData, &jsonError); - if (jsonError.error == QJsonParseError::NoError) - { - return json.object(); - } - - return QJsonObject(); - } - - private Q_SLOTS: - void cleanup() - { - Env::getSingleton()->reset(); - } - - - void log() - { - Env::getSingleton()->init(); - const QLatin1String testDummy("Yeah, piece of cake!"); - qDebug() << testDummy; - - const QByteArray msg(R"({"cmd": "GET_LOG"})"); - QByteArray result; - UIPlugInJson api; - connect(&api, &UIPlugInJson::fireMessage, this, [&result](const QByteArray& pMsg){result = pMsg;}); - api.setEnabled(); - - api.doMessageProcessing(msg); - QVERIFY(!result.isEmpty()); - QVERIFY(result.contains(R"("msg":"LOG")")); - auto json = getJsonObject(result); - QVERIFY(!json.isEmpty()); - auto data = json["data"].toString(); - QVERIFY(!data.isEmpty()); - - const QLatin1String loggedType("Process type: GET_LOG"); - QCOMPARE(data.count(loggedType), 1); - QCOMPARE(data.count(testDummy), 1); - - result.clear(); - api.doMessageProcessing(msg); - QVERIFY(!result.isEmpty()); - json = getJsonObject(result); - QVERIFY(!json.isEmpty()); - data = json["data"].toString(); - QVERIFY(!data.isEmpty()); - QCOMPARE(data.count(loggedType), 2); - QCOMPARE(data.count(testDummy), 1); - } - - -}; - -QTEST_GUILESS_MAIN(test_UIPlugInJson) -#include "test_UIPlugInJson.moc" diff --git a/test/qt/ui/json/test_UILoader.cpp b/test/qt/ui/json/test_UiLoader.cpp similarity index 53% rename from test/qt/ui/json/test_UILoader.cpp rename to test/qt/ui/json/test_UiLoader.cpp index 8c43f2fe8..904a3d2af 100644 --- a/test/qt/ui/json/test_UILoader.cpp +++ b/test/qt/ui/json/test_UiLoader.cpp @@ -1,24 +1,25 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UILoader + * \brief Unit tests for \ref UiLoader */ -#include "UILoader.h" +#include "UiLoader.h" -#include "UIPlugInJson.h" +#include "UiPluginJson.h" #include #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; -Q_IMPORT_PLUGIN(UIPlugInJson) +Q_IMPORT_PLUGIN(UiPluginJson) -class test_UILoader +class test_UiLoader : public QObject { Q_OBJECT @@ -26,25 +27,25 @@ class test_UILoader private Q_SLOTS: void isLoaded() { - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); - QVERIFY(loader.load()); + QVERIFY(loader.load()); QVERIFY(loader.isLoaded()); - QVERIFY(loader.load()); // already loaded - QVERIFY(loader.getLoaded()); + QVERIFY(loader.load()); // already loaded + QVERIFY(loader.getLoaded()); QCOMPARE(spyLoaded.count(), 1); QVERIFY(loader.initialize()); QVERIFY(loader.requiresReaderManager()); - const auto* ui = loader.getLoaded(); + const auto* ui = loader.getLoaded(); QCOMPARE(ui->property("default"), QVariant()); QCOMPARE(ui->property("passive"), QVariant(true)); QCOMPARE(ui->property("userInteractive"), QVariant()); QCOMPARE(ui->property("readerManager"), QVariant()); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("json"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("json"))"); } @@ -52,71 +53,71 @@ class test_UILoader { // DO NOT remove the whitespace, otherwise QCommandLineParser // won't accept user values. - QCOMPARE(UILoader::getDefault(), QStringLiteral(" ")); + QCOMPARE(UiLoader::getDefault(), QStringLiteral(" ")); // not default plugins exists, see missing Q_IMPORT_PLUGIN - UILoader loader; + UiLoader loader; QVERIFY(!loader.load()); QVERIFY(!loader.isLoaded()); - QTest::ignoreMessage(QtDebugMsg, "Shutdown UILoader: QList()"); + QTest::ignoreMessage(QtDebugMsg, "Shutdown UiLoader: QList()"); loader.shutdown(); } void userRequestLoaded() // json can be loaded { - UILoader::setUserRequest({QStringLiteral("crap"), QStringLiteral("json")}); + UiLoader::setUserRequest({QStringLiteral("crap"), QStringLiteral("json")}); - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); QVERIFY(loader.load()); QVERIFY(loader.isLoaded()); QCOMPARE(spyLoaded.count(), 1); - QVERIFY(loader.getLoaded()); + QVERIFY(loader.getLoaded()); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("json"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("json"))"); } void userRequestReset() // reset to initial default { - UILoader::setUserRequest({QStringLiteral("json")}); - UILoader::setUserRequest({}); - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({}); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QVERIFY(!loader.load()); QVERIFY(!loader.isLoaded()); QVERIFY(loader.initialize()); // empty list is ok QCOMPARE(spyLoaded.count(), 0); - QTest::ignoreMessage(QtDebugMsg, "Shutdown UILoader: QList()"); + QTest::ignoreMessage(QtDebugMsg, "Shutdown UiLoader: QList()"); loader.shutdown(); } void userRequestFallback() // user request has no valid plugin, fallback to initial default, too. { - UILoader::setUserRequest({QStringLiteral("crap"), QStringLiteral("only")}); - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader::setUserRequest({QStringLiteral("crap"), QStringLiteral("only")}); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QVERIFY(!loader.load()); QVERIFY(!loader.isLoaded()); QCOMPARE(spyLoaded.count(), 0); - QTest::ignoreMessage(QtDebugMsg, "Shutdown UILoader: QList()"); + QTest::ignoreMessage(QtDebugMsg, "Shutdown UiLoader: QList()"); loader.shutdown(); } void fireShutdownNoUi() // no ui loaded { - auto loader = QSharedPointer::create(); - QSignalSpy spyShutdown(loader.get(), &UILoader::fireRemovedAllPlugins); + auto loader = QSharedPointer::create(); + QSignalSpy spyShutdown(loader.get(), &UiLoader::fireRemovedAllPlugins); - QTest::ignoreMessage(QtDebugMsg, "Shutdown UILoader: QList()"); + QTest::ignoreMessage(QtDebugMsg, "Shutdown UiLoader: QList()"); loader->shutdown(); QCoreApplication::processEvents(); // cannot use QTRY_COMPARE here QCOMPARE(spyShutdown.count(), 0); @@ -125,13 +126,13 @@ class test_UILoader void fireShutdownBeforeDtor() // ui loaded, shutdown before dtor { - auto loader = QSharedPointer::create(); - QSignalSpy spyShutdown(loader.data(), &UILoader::fireRemovedAllPlugins); + auto loader = QSharedPointer::create(); + QSignalSpy spyShutdown(loader.data(), &UiLoader::fireRemovedAllPlugins); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); - QVERIFY(loader->load()); + QVERIFY(loader->load()); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("json"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("json"))"); QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UI: "json")"); loader->shutdown(); QTRY_COMPARE(spyShutdown.count(), 1); // clazy:exclude=qstring-allocations @@ -143,13 +144,13 @@ class test_UILoader void noFireShutdownDtor() // ui loaded, but dtor won't fire { - auto loader = QSharedPointer::create(); - QSignalSpy spyShutdown(loader.data(), &UILoader::fireRemovedAllPlugins); + auto loader = QSharedPointer::create(); + QSignalSpy spyShutdown(loader.data(), &UiLoader::fireRemovedAllPlugins); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); - QVERIFY(loader->load()); + QVERIFY(loader->load()); - QSignalSpy spyDestroyed(loader->getLoaded(), &QObject::destroyed); + QSignalSpy spyDestroyed(loader->getLoaded(), &QObject::destroyed); loader.reset(); QTRY_COMPARE(spyDestroyed.count(), 1); // clazy:exclude=qstring-allocations @@ -164,25 +165,25 @@ class test_UILoader void getName_data() { - QTest::addColumn("name"); - - QTest::newRow("qml") << QString("UIPlugInQml"); - QTest::newRow("json") << QString("governikus::UIPlugInJson"); - QTest::newRow("websocket") << QString("WebSocket"); - QTest::newRow("localifd") << QString("UIPlugInLocalIfd"); - QTest::newRow("aidl") << QString("governikus::uipluginAidl"); - QTest::newRow("functional") << QString("UIPluginFunctional"); + QTest::addColumn("name"); + + QTest::newRow("qml") << "UiPluginQml"_L1; + QTest::newRow("json") << "governikus::UiPluginJson"_L1; + QTest::newRow("websocket") << "WebSocket"_L1; + QTest::newRow("localifd") << "UiPluginLocalIfd"_L1; + QTest::newRow("aidl") << "governikus::uipluginAidl"_L1; + QTest::newRow("functional") << "UIPluginFunctional"_L1; } void getName() { - QFETCH(QString, name); - QCOMPARE(UILoader::unify(name), QString::fromLatin1(QTest::currentDataTag())); + QFETCH(QLatin1String, name); + QCOMPARE(UiLoader::unify(name), QString::fromLatin1(QTest::currentDataTag())); } }; -QTEST_GUILESS_MAIN(test_UILoader) -#include "test_UILoader.moc" +QTEST_GUILESS_MAIN(test_UiLoader) +#include "test_UiLoader.moc" diff --git a/test/qt/ui/json/test_UiPluginJson.cpp b/test/qt/ui/json/test_UiPluginJson.cpp new file mode 100644 index 000000000..2e0e5c6d9 --- /dev/null +++ b/test/qt/ui/json/test_UiPluginJson.cpp @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiPluginJson.h" + +#include "LogHandler.h" +#include "ReaderManager.h" +#include "SmartCardDefinitions.h" + +#include "MockReader.h" +#include "MockReaderManagerPlugin.h" + +#include +#include + +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +class test_UiPluginJson + : public QObject +{ + Q_OBJECT + + private: + QJsonObject getJsonObject(const QByteArray& pData) + { + QJsonParseError jsonError {}; + const auto& json = QJsonDocument::fromJson(pData, &jsonError); + if (jsonError.error == QJsonParseError::NoError) + { + return json.object(); + } + + return QJsonObject(); + } + + private Q_SLOTS: + void initTestCase() + { + auto* readerManager = Env::getSingleton(); + QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); + readerManager->init(); + QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations + } + + + void cleanup() + { + Env::getSingleton()->reset(); + } + + + void log() + { + Env::getSingleton()->init(); + const QLatin1String testDummy("Yeah, piece of cake!"); + qDebug() << testDummy; + + const QByteArray msg(R"({"cmd": "GET_LOG"})"); + QByteArray result; + UiPluginJson api; + connect(&api, &UiPluginJson::fireMessage, this, [&result](const QByteArray& pMsg){result = pMsg;}); + api.setEnabled(); + + api.doMessageProcessing(msg); + QVERIFY(!result.isEmpty()); + QVERIFY(result.contains(R"("msg":"LOG")")); + auto json = getJsonObject(result); + QVERIFY(!json.isEmpty()); + auto data = json["data"_L1].toString(); + QVERIFY(!data.isEmpty()); + + const QLatin1String loggedType("Process type: GET_LOG"); + QCOMPARE(data.count(loggedType), 1); + QCOMPARE(data.count(testDummy), 1); + + result.clear(); + api.doMessageProcessing(msg); + QVERIFY(!result.isEmpty()); + json = getJsonObject(result); + QVERIFY(!json.isEmpty()); + data = json["data"_L1].toString(); + QVERIFY(!data.isEmpty()); + QCOMPARE(data.count(loggedType), 2); + QCOMPARE(data.count(testDummy), 1); + } + + + void newCard_data() + { +#if __has_include("SmartManager.h") + const QByteArray eidType = QByteArray(R"("eidType":"CARD_CERTIFIED",)"); +#else + const QByteArray eidType; +#endif + const QByteArray unknownCard(R"({"attached":true,"card":{},"insertable":false,"keypad":false,"msg":"READER","name":"Reader"})"); + const QByteArray knownCard(R"({"attached":true,"card":{"deactivated":false,)" + eidType + R"("inoperative":false,"retryCounter":-1},"insertable":false,"keypad":false,"msg":"READER","name":"Reader"})"); + + QTest::addColumn("msgLevel"); + QTest::addColumn("cardType"); + QTest::addColumn("result"); + + QTest::newRow("NONE v2") << MsgLevel::v2 << CardType::NONE << QByteArray(); + QTest::newRow("NONE v3") << MsgLevel::v3 << CardType::NONE << QByteArray(); + QTest::newRow("UNKNOWN v2") << MsgLevel::v2 << CardType::UNKNOWN << QByteArray(); + QTest::newRow("UNKNOWN v3") << MsgLevel::v3 << CardType::UNKNOWN << unknownCard; + QTest::newRow("EID_CARD v2") << MsgLevel::v2 << CardType::EID_CARD << knownCard; + QTest::newRow("EID_CARD v3") << MsgLevel::v3 << CardType::EID_CARD << knownCard; + QTest::newRow("SMART_EID v2") << MsgLevel::v2 << CardType::SMART_EID << knownCard; + QTest::newRow("SMART_EID v3") << MsgLevel::v3 << CardType::SMART_EID << knownCard; + } + + + void newCard() + { + QFETCH(MsgLevel, msgLevel); + QFETCH(CardType, cardType); + QFETCH(QByteArray, result); + + UiPluginJson api; + api.setEnabled(true); + QByteArray setApiLevel(R"({"cmd": "SET_API_LEVEL", "level": })"); + setApiLevel.replace("", QByteArray::number(Enum::getValue(msgLevel))); + api.doMessageProcessing(setApiLevel); + + QSignalSpy spy(&api, &UiPluginJson::fireMessage); + ReaderInfo info(QStringLiteral("Reader"), ReaderManagerPluginType::PCSC, CardInfo(cardType)); + api.onCardInserted(info); + if (result.isNull()) + { + QCOMPARE(spy.size(), 0); + } + else + { + QCOMPARE(spy.size(), 1); + QCOMPARE(spy.at(0).at(0).toByteArray(), result); + } + } + + + void enabledOnce() + { + UiPluginJson api; + api.setEnabled(true); + api.setEnabled(true); + api.setEnabled(false); + api.setEnabled(false); + api.setEnabled(true); + + QSignalSpy spy(&api, &UiPluginJson::fireMessage); + + MockReader* reader = MockReaderManagerPlugin::getInstance().addReader("MockReader 0815"_L1); + reader->setCard(MockCardConfig()); + + QCOMPARE(spy.size(), 2); + const auto notAttached = R"({"attached":true,"card":null,"insertable":false,"keypad":false,"msg":"READER","name":"MockReader 0815"})"; +#if __has_include("SmartManager.h") + const QByteArray eidType = QByteArray(R"("eidType":"CARD_CERTIFIED",)"); +#else + const QByteArray eidType; +#endif + const auto attached = R"({"attached":true,"card":{"deactivated":false,)" + eidType + R"("inoperative":false,"retryCounter":-1},"insertable":false,"keypad":false,"msg":"READER","name":"MockReader 0815"})"; + QCOMPARE(spy.at(0).at(0).toByteArray(), notAttached); + QCOMPARE(spy.at(1).at(0).toByteArray(), attached); + } + + +}; + +QTEST_GUILESS_MAIN(test_UiPluginJson) +#include "test_UiPluginJson.moc" diff --git a/test/qt/ui/proxy/test_RedirectRequest.cpp b/test/qt/ui/proxy/test_RedirectRequest.cpp index 57b9ebc73..7b235154c 100644 --- a/test/qt/ui/proxy/test_RedirectRequest.cpp +++ b/test/qt/ui/proxy/test_RedirectRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "RedirectRequest.h" diff --git a/test/qt/ui/proxy/test_UILoader.cpp b/test/qt/ui/proxy/test_UiLoader.cpp similarity index 50% rename from test/qt/ui/proxy/test_UILoader.cpp rename to test/qt/ui/proxy/test_UiLoader.cpp index 6b2f1c5cc..541cf6e55 100644 --- a/test/qt/ui/proxy/test_UILoader.cpp +++ b/test/qt/ui/proxy/test_UiLoader.cpp @@ -1,23 +1,23 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UILoader + * \brief Unit tests for \ref UiLoader */ -#include "UILoader.h" +#include "UiLoader.h" -#include "UIPlugInProxy.h" +#include "UiPluginProxy.h" #include #include using namespace governikus; -Q_IMPORT_PLUGIN(UIPlugInProxy) +Q_IMPORT_PLUGIN(UiPluginProxy) -class test_UILoader +class test_UiLoader : public QObject { Q_OBJECT @@ -25,27 +25,27 @@ class test_UILoader private Q_SLOTS: void isLoaded() { - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "proxy")"); - QVERIFY(loader.load()); + QVERIFY(loader.load()); QVERIFY(loader.isLoaded()); - QVERIFY(loader.getLoaded()); + QVERIFY(loader.getLoaded()); QCOMPARE(spyLoaded.count(), 1); QVERIFY(loader.initialize()); QVERIFY(!loader.requiresReaderManager()); - const auto* ui = loader.getLoaded(); + const auto* ui = loader.getLoaded(); QCOMPARE(ui->property("default"), QVariant()); QCOMPARE(ui->property("passive"), QVariant()); QCOMPARE(ui->property("readerManager"), QVariant(false)); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("proxy"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("proxy"))"); } }; -QTEST_GUILESS_MAIN(test_UILoader) -#include "test_UILoader.moc" +QTEST_GUILESS_MAIN(test_UiLoader) +#include "test_UiLoader.moc" diff --git a/test/qt/ui/proxy/test_UIPlugInProxy.cpp b/test/qt/ui/proxy/test_UiPluginProxy.cpp similarity index 68% rename from test/qt/ui/proxy/test_UIPlugInProxy.cpp rename to test/qt/ui/proxy/test_UiPluginProxy.cpp index 650027ab1..de590fb16 100644 --- a/test/qt/ui/proxy/test_UIPlugInProxy.cpp +++ b/test/qt/ui/proxy/test_UiPluginProxy.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInProxy.h" +#include "UiPluginProxy.h" #include "Env.h" #include "HttpServer.h" @@ -11,7 +11,7 @@ using namespace governikus; -class test_UIPlugInProxy +class test_UiPluginProxy : public QObject { Q_OBJECT @@ -25,8 +25,8 @@ class test_UIPlugInProxy void initialize() { - UIPlugInProxy proxy; - QSignalSpy logSpy(&proxy, &UIPlugInProxy::fireUiDominationRequest); + UiPluginProxy proxy; + QSignalSpy logSpy(&proxy, &UiPluginProxy::fireUiDominationRequest); QVERIFY(proxy.initialize()); QCOMPARE(logSpy.count(), 1); @@ -38,7 +38,7 @@ class test_UIPlugInProxy void enabledDisabled() { - UIPlugInProxy proxy; + UiPluginProxy proxy; QVERIFY(proxy.initialize()); QTest::ignoreMessage(QtDebugMsg, "Reverse proxy enabled"); @@ -51,5 +51,5 @@ class test_UIPlugInProxy }; -QTEST_GUILESS_MAIN(test_UIPlugInProxy) -#include "test_UIPlugInProxy.moc" +QTEST_GUILESS_MAIN(test_UiPluginProxy) +#include "test_UiPluginProxy.moc" diff --git a/test/qt/ui/qml/smart/test_PersonalizationModel.cpp b/test/qt/ui/qml/smart/test_PersonalizationModel.cpp index 4f1897463..55d50ae52 100644 --- a/test/qt/ui/qml/smart/test_PersonalizationModel.cpp +++ b/test/qt/ui/qml/smart/test_PersonalizationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ui/qml/smart/test_SmartModel.cpp b/test/qt/ui/qml/smart/test_SmartModel.cpp index ca044c977..9f0fe7b49 100644 --- a/test/qt/ui/qml/smart/test_SmartModel.cpp +++ b/test/qt/ui/qml/smart/test_SmartModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,7 +9,7 @@ #include "SmartModel.h" #include "Env.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "mock/eid_applet_interface_mock.h" @@ -17,9 +17,10 @@ #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -41,26 +42,26 @@ class test_SmartModel Q_ASSERT(mSmartReader); auto info = mSmartReader->getReaderInfo(); - info.setCardInfo(CardInfo(CardType::SMART_EID, QSharedPointer(), pRetryCounter, false, false, pPinInitial)); + info.setCardInfo(CardInfo(CardType::SMART_EID, FileRef(), QSharedPointer(), pRetryCounter, false, false, pPinInitial)); mSmartReader->setReaderInfo(info); } private Q_SLOTS: void initTestCase() { - MockReader::cMOCKED_READERMANAGER_TYPE = ReaderManagerPlugInType::SMART; - const auto readerManager = Env::getSingleton(); + MockReader::cMOCKED_READERMANAGER_TYPE = ReaderManagerPluginType::SMART; + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations setSmartEidStatus(EidStatus::PERSONALIZED); - mSmartReader = MockReaderManagerPlugIn::getInstance().addReader("SmartReader"); + mSmartReader = MockReaderManagerPlugin::getInstance().addReader("SmartReader"_L1); setupSmartReader(false, 3); const auto& smartModel = Env::getSingleton(); // just to wait until initialization of SmartModel is finished - QTRY_COMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_READY); + QTRY_COMPARE(smartModel->getState(), SmartModel::State::READY); } @@ -69,42 +70,42 @@ class test_SmartModel setupSmartReader(false, 3); setSmartEidSupportStatusResult({EidServiceResult::SUCCESS, EidSupportStatus::AVAILABLE}); setSmartEidStatus(EidStatus::PERSONALIZED); - Env::getSingleton()->mStatus = SmartModel::QmlSmartState::SMART_READY; + Env::getSingleton()->mStatus = SmartModel::State::READY; } void cleanupTestCase() { - MockReaderManagerPlugIn::getInstance().removeAllReader(); + MockReaderManagerPlugin::getInstance().removeAllReader(); Env::getSingleton()->shutdown(); } - void test_getSmartState_data() + void test_getState_data() { QTest::addColumn("eidStatus"); QTest::addColumn("pinInitial"); QTest::addColumn("retryCounter"); - QTest::addColumn("smartState"); + QTest::addColumn("state"); - QTest::newRow("Unusable") << EidStatus::UNUSABLE << false << 3 << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("Internal error") << EidStatus::INTERNAL_ERROR << false << 3 << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("No personalization") << EidStatus::NO_PERSONALIZATION << false << 3 << SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION; - QTest::newRow("No provisioning") << EidStatus::NO_PROVISIONING << false << 3 << SmartModel::QmlSmartState::SMART_NO_PROVISIONING; - QTest::newRow("Personalized") << EidStatus::PERSONALIZED << false << 3 << SmartModel::QmlSmartState::SMART_READY; - QTest::newRow("cert_expired") << EidStatus::CERT_EXPIRED << false << 3 << SmartModel::QmlSmartState::SMART_UNUSABLE; + QTest::newRow("Unusable") << EidStatus::UNUSABLE << false << 3 << SmartModel::State::UNUSABLE; + QTest::newRow("Internal error") << EidStatus::INTERNAL_ERROR << false << 3 << SmartModel::State::UNAVAILABLE; + QTest::newRow("No personalization") << EidStatus::NO_PERSONALIZATION << false << 3 << SmartModel::State::NO_PERSONALIZATION; + QTest::newRow("No provisioning") << EidStatus::NO_PROVISIONING << false << 3 << SmartModel::State::NO_PROVISIONING; + QTest::newRow("Personalized") << EidStatus::PERSONALIZED << false << 3 << SmartModel::State::READY; + QTest::newRow("cert_expired") << EidStatus::CERT_EXPIRED << false << 3 << SmartModel::State::UNUSABLE; - QTest::newRow("Personalized - Retry Counter 0") << EidStatus::PERSONALIZED << false << 0 << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("Personalized - Retry Counter -1") << EidStatus::PERSONALIZED << false << -1 << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("Personalized - Initial PIN") << EidStatus::PERSONALIZED << true << 3 << SmartModel::QmlSmartState::SMART_UNUSABLE; + QTest::newRow("Personalized - Retry Counter 0") << EidStatus::PERSONALIZED << false << 0 << SmartModel::State::UNUSABLE; + QTest::newRow("Personalized - Retry Counter -1") << EidStatus::PERSONALIZED << false << -1 << SmartModel::State::UNUSABLE; + QTest::newRow("Personalized - Initial PIN") << EidStatus::PERSONALIZED << true << 3 << SmartModel::State::UNUSABLE; } - void test_getSmartState() + void test_getState() { QFETCH(EidStatus, eidStatus); - QFETCH(SmartModel::QmlSmartState, smartState); + QFETCH(SmartModel::State, state); QFETCH(bool, pinInitial); QFETCH(int, retryCounter); @@ -114,16 +115,16 @@ class test_SmartModel // Allow an independent test execution. Without this the row // "Personalized" will fail because no update of QmlSmartState // is required and the signal is missing. - smartModel->mStatus = SmartModel::QmlSmartState::SMART_UNUSABLE; + smartModel->mStatus = SmartModel::State::UNUSABLE; } - QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireSmartStateChanged); + QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireStateChanged); setSmartEidStatus(eidStatus); setupSmartReader(pinInitial, retryCounter); smartModel->updateStatus(); QTRY_COMPARE(spySmartStateChanged.count(), 2); - QCOMPARE(smartModel->getSmartState(), smartState); + QCOMPARE(smartModel->getState(), state); } @@ -131,14 +132,14 @@ class test_SmartModel { const auto& smartModel = Env::getSingleton(); QSignalSpy spyDeletePersonalizationDone(smartModel, &SmartModel::fireDeletePersonalizationDone); - QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireSmartStateChanged); + QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireStateChanged); setDeletePersonalizationResult(EidServiceResult::SUCCESS); smartModel->deletePersonalization(); QTRY_COMPARE(spyDeletePersonalizationDone.count(), 1); QTRY_COMPARE(spySmartStateChanged.count(), 2); - QCOMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION); + QCOMPARE(smartModel->getState(), SmartModel::State::NO_PERSONALIZATION); } @@ -146,14 +147,14 @@ class test_SmartModel { const auto& smartModel = Env::getSingleton(); QSignalSpy spyDeleteSmartDone(smartModel, &SmartModel::fireDeleteSmartDone); - QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireSmartStateChanged); + QSignalSpy spySmartStateChanged(smartModel, &SmartModel::fireStateChanged); setDeleteSmartEidResult(EidServiceResult::SUCCESS); smartModel->deleteSmart(); QTRY_COMPARE(spyDeleteSmartDone.count(), 1); QTRY_COMPARE(spySmartStateChanged.count(), 2); - QCOMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_NO_PROVISIONING); + QCOMPARE(smartModel->getState(), SmartModel::State::NO_PROVISIONING); } @@ -165,17 +166,17 @@ class test_SmartModel int signalCount = 0; - const auto connection = connect(smartModel, &SmartModel::fireSmartStateChanged, [&signalCount, smartModel](){ + const auto connection = connect(smartModel, &SmartModel::fireStateChanged, this, [&signalCount, smartModel](){ signalCount++; switch (signalCount) { case 1: - QCOMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_UPDATING_STATUS); + QCOMPARE(smartModel->getState(), SmartModel::State::UPDATING_STATUS); break; case 2: - QCOMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION); + QCOMPARE(smartModel->getState(), SmartModel::State::NO_PERSONALIZATION); break; default: @@ -193,26 +194,26 @@ class test_SmartModel void test_onStatusChanged_data() { - QTest::addColumn("plugInType"); + QTest::addColumn("pluginType"); QTest::addColumn("expectSignal"); - QTest::addRow("SMART") << ReaderManagerPlugInType::SMART << true; - QTest::addRow("NFC") << ReaderManagerPlugInType::NFC << false; - QTest::addRow("PCSC") << ReaderManagerPlugInType::PCSC << false; - QTest::addRow("UNKNOWN") << ReaderManagerPlugInType::UNKNOWN << false; + QTest::addRow("SMART") << ReaderManagerPluginType::SMART << true; + QTest::addRow("NFC") << ReaderManagerPluginType::NFC << false; + QTest::addRow("PCSC") << ReaderManagerPluginType::PCSC << false; + QTest::addRow("UNKNOWN") << ReaderManagerPluginType::UNKNOWN << false; } void test_onStatusChanged() { - QFETCH(ReaderManagerPlugInType, plugInType); + QFETCH(ReaderManagerPluginType, pluginType); QFETCH(bool, expectSignal); const auto& smartModel = Env::getSingleton(); QSignalSpy spy(smartModel, &SmartModel::fireScanRunningChanged); - smartModel->onStatusChanged(ReaderManagerPlugInInfo(plugInType)); + smartModel->onStatusChanged(ReaderManagerPluginInfo(pluginType)); QCOMPARE(spy.count(), expectSignal ? 1 : 0); } @@ -221,28 +222,28 @@ class test_SmartModel { QTest::addColumn("eidSupportStatus"); QTest::addColumn("eidStatus"); - QTest::addColumn("smartState"); - - QTest::newRow("Unavailable1") << EidSupportStatus::UNAVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("Unavailable2") << EidSupportStatus::UNAVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("Unavailable3") << EidSupportStatus::UNAVAILABLE << EidStatus::PERSONALIZED << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("Unavailable4") << EidSupportStatus::UNAVAILABLE << EidStatus::UNUSABLE << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("Available1") << EidSupportStatus::AVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::QmlSmartState::SMART_NO_PROVISIONING; - QTest::newRow("Available2") << EidSupportStatus::AVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION; - QTest::newRow("Available3") << EidSupportStatus::AVAILABLE << EidStatus::PERSONALIZED << SmartModel::QmlSmartState::SMART_READY; - QTest::newRow("Available4") << EidSupportStatus::AVAILABLE << EidStatus::UNUSABLE << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("UpToDate1") << EidSupportStatus::UP_TO_DATE << EidStatus::NO_PROVISIONING << SmartModel::QmlSmartState::SMART_NO_PROVISIONING; - QTest::newRow("UpToDate2") << EidSupportStatus::UP_TO_DATE << EidStatus::NO_PERSONALIZATION << SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION; - QTest::newRow("UpToDate3") << EidSupportStatus::UP_TO_DATE << EidStatus::PERSONALIZED << SmartModel::QmlSmartState::SMART_READY; - QTest::newRow("UpToDate4") << EidSupportStatus::UP_TO_DATE << EidStatus::UNUSABLE << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("UpdateAvailable1") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::QmlSmartState::SMART_NO_PROVISIONING; - QTest::newRow("UpdateAvailable2") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::QmlSmartState::SMART_NO_PERSONALIZATION; - QTest::newRow("UpdateAvailable3") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::PERSONALIZED << SmartModel::QmlSmartState::SMART_READY; - QTest::newRow("UpdateAvailable4") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::UNUSABLE << SmartModel::QmlSmartState::SMART_UNUSABLE; - QTest::newRow("InternalError1") << EidSupportStatus::INTERNAL_ERROR << EidStatus::NO_PROVISIONING << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("InternalError2") << EidSupportStatus::INTERNAL_ERROR << EidStatus::NO_PERSONALIZATION << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("InternalError3") << EidSupportStatus::INTERNAL_ERROR << EidStatus::PERSONALIZED << SmartModel::QmlSmartState::SMART_UNAVAILABLE; - QTest::newRow("InternalError4") << EidSupportStatus::INTERNAL_ERROR << EidStatus::UNUSABLE << SmartModel::QmlSmartState::SMART_UNAVAILABLE; + QTest::addColumn("smartState"); + + QTest::newRow("Unavailable1") << EidSupportStatus::UNAVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::State::UNAVAILABLE; + QTest::newRow("Unavailable2") << EidSupportStatus::UNAVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::State::UNAVAILABLE; + QTest::newRow("Unavailable3") << EidSupportStatus::UNAVAILABLE << EidStatus::PERSONALIZED << SmartModel::State::UNAVAILABLE; + QTest::newRow("Unavailable4") << EidSupportStatus::UNAVAILABLE << EidStatus::UNUSABLE << SmartModel::State::UNAVAILABLE; + QTest::newRow("Available1") << EidSupportStatus::AVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::State::NO_PROVISIONING; + QTest::newRow("Available2") << EidSupportStatus::AVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::State::NO_PERSONALIZATION; + QTest::newRow("Available3") << EidSupportStatus::AVAILABLE << EidStatus::PERSONALIZED << SmartModel::State::READY; + QTest::newRow("Available4") << EidSupportStatus::AVAILABLE << EidStatus::UNUSABLE << SmartModel::State::UNUSABLE; + QTest::newRow("UpToDate1") << EidSupportStatus::UP_TO_DATE << EidStatus::NO_PROVISIONING << SmartModel::State::NO_PROVISIONING; + QTest::newRow("UpToDate2") << EidSupportStatus::UP_TO_DATE << EidStatus::NO_PERSONALIZATION << SmartModel::State::NO_PERSONALIZATION; + QTest::newRow("UpToDate3") << EidSupportStatus::UP_TO_DATE << EidStatus::PERSONALIZED << SmartModel::State::READY; + QTest::newRow("UpToDate4") << EidSupportStatus::UP_TO_DATE << EidStatus::UNUSABLE << SmartModel::State::UNUSABLE; + QTest::newRow("UpdateAvailable1") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::NO_PROVISIONING << SmartModel::State::NO_PROVISIONING; + QTest::newRow("UpdateAvailable2") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::NO_PERSONALIZATION << SmartModel::State::NO_PERSONALIZATION; + QTest::newRow("UpdateAvailable3") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::PERSONALIZED << SmartModel::State::READY; + QTest::newRow("UpdateAvailable4") << EidSupportStatus::UPDATE_AVAILABLE << EidStatus::UNUSABLE << SmartModel::State::UNUSABLE; + QTest::newRow("InternalError1") << EidSupportStatus::INTERNAL_ERROR << EidStatus::NO_PROVISIONING << SmartModel::State::UNAVAILABLE; + QTest::newRow("InternalError2") << EidSupportStatus::INTERNAL_ERROR << EidStatus::NO_PERSONALIZATION << SmartModel::State::UNAVAILABLE; + QTest::newRow("InternalError3") << EidSupportStatus::INTERNAL_ERROR << EidStatus::PERSONALIZED << SmartModel::State::UNAVAILABLE; + QTest::newRow("InternalError4") << EidSupportStatus::INTERNAL_ERROR << EidStatus::UNUSABLE << SmartModel::State::UNAVAILABLE; } @@ -250,16 +251,16 @@ class test_SmartModel { QFETCH(EidSupportStatus, eidSupportStatus); QFETCH(EidStatus, eidStatus); - QFETCH(SmartModel::QmlSmartState, smartState); + QFETCH(SmartModel::State, smartState); const auto& smartModel = Env::getSingleton(); - smartModel->mStatus = SmartModel::QmlSmartState::SMART_NO_PROVISIONING; + smartModel->mStatus = SmartModel::State::NO_PROVISIONING; setSmartEidSupportStatus(eidSupportStatus); setSmartEidStatus(eidStatus); smartModel->updateSupportInfo(); - QCOMPARE(smartModel->getSmartState(), SmartModel::QmlSmartState::SMART_UPDATING_STATUS); - QTRY_COMPARE(smartModel->getSmartState(), smartState); + QCOMPARE(smartModel->getState(), SmartModel::State::UPDATING_STATUS); + QTRY_COMPARE(smartModel->getState(), smartState); } @@ -285,9 +286,9 @@ class test_SmartModel setSmartEidSupportStatusResult({serviceResult, EidSupportStatus::AVAILABLE}); auto* smartModel = Env::getSingleton(); - smartModel->mStatus = SmartModel::QmlSmartState::SMART_NO_PROVISIONING; + smartModel->mStatus = SmartModel::State::NO_PROVISIONING; smartModel->updateSupportInfo(); - QTRY_VERIFY(smartModel->getSmartState() != SmartModel::QmlSmartState::SMART_UPDATING_STATUS); + QTRY_VERIFY(smartModel->getState() != SmartModel::State::UPDATING_STATUS); QCOMPARE(smartModel->getErrorString().isEmpty(), serviceResult == EidServiceResult::SUCCESS); } diff --git a/test/qt/ui/qml/test_ApplicationModel.cpp b/test/qt/ui/qml/test_ApplicationModel.cpp index daf89c637..a2c55fdd3 100644 --- a/test/qt/ui/qml/test_ApplicationModel.cpp +++ b/test/qt/ui/qml/test_ApplicationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -56,13 +56,13 @@ class test_ApplicationModel QTest::addColumn>("context"); QTest::addColumn("workflow"); - QTest::addRow("No Context") << QSharedPointer() << ApplicationModel::Workflow::WORKFLOW_NONE; - QTest::addRow("AuthContext") << QSharedPointer(new AuthContext()) << ApplicationModel::Workflow::WORKFLOW_AUTHENTICATION; - QTest::addRow("ChangePinContext") << QSharedPointer(new ChangePinContext()) << ApplicationModel::Workflow::WORKFLOW_CHANGE_PIN; - QTest::addRow("IfdServiceContext") << QSharedPointer(new IfdServiceContext(QSharedPointer::create())) << ApplicationModel::Workflow::WORKFLOW_REMOTE_SERVICE; - QTest::addRow("SelfAuthContext") << QSharedPointer(new SelfAuthContext()) << ApplicationModel::Workflow::WORKFLOW_SELF_AUTHENTICATION; + QTest::addRow("No Context") << QSharedPointer() << ApplicationModel::Workflow::NONE; + QTest::addRow("AuthContext") << QSharedPointer(new AuthContext()) << ApplicationModel::Workflow::AUTHENTICATION; + QTest::addRow("ChangePinContext") << QSharedPointer(new ChangePinContext()) << ApplicationModel::Workflow::CHANGE_PIN; + QTest::addRow("IfdServiceContext") << QSharedPointer(new IfdServiceContext(QSharedPointer::create())) << ApplicationModel::Workflow::REMOTE_SERVICE; + QTest::addRow("SelfAuthContext") << QSharedPointer(new SelfAuthContext()) << ApplicationModel::Workflow::SELF_AUTHENTICATION; #if __has_include("context/PersonalizationContext.h") - QTest::addRow("PersonalizationContext") << QSharedPointer(new PersonalizationContext(QString())) << ApplicationModel::Workflow::WORKFLOW_SMART; + QTest::addRow("PersonalizationContext") << QSharedPointer(new PersonalizationContext(QString())) << ApplicationModel::Workflow::SMART; #endif } diff --git a/test/qt/ui/qml/test_AuthModel.cpp b/test/qt/ui/qml/test_AuthModel.cpp index 01ba1fd41..4840c19a5 100644 --- a/test/qt/ui/qml/test_AuthModel.cpp +++ b/test/qt/ui/qml/test_AuthModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -9,6 +9,7 @@ #include "AuthModel.h" #include "context/AuthContext.h" +#include "context/SelfAuthContext.h" #include "paos/retrieve/DidAuthenticateEac1Parser.h" @@ -18,6 +19,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -29,7 +31,7 @@ class test_AuthModel private Q_SLOTS: void test_ResetContext() { - const auto model = Env::getSingleton(); + auto* const model = Env::getSingleton(); const QSharedPointer context(new AuthContext()); QSignalSpy spyWorkflowStarted(model, &WorkflowModel::fireWorkflowStarted); @@ -43,14 +45,14 @@ class test_AuthModel QCOMPARE(spyStateEntered.count(), 0); QCOMPARE(spyTransactionInfoChanged.count(), 0); - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_htmlTransactionInfo.xml"_L1); QSharedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); context->setDidAuthenticateEac1(eac1); - QCOMPARE(model->getTransactionInfo(), QString("this is a test for TransactionInfo")); + QCOMPARE(model->getTransactionInfo(), "this is a <a>test</a> for TransactionInfo"_L1); model->resetAuthContext(context); QVERIFY(model->getTransactionInfo().isEmpty()); Q_EMIT context->fireDidAuthenticateEac1Changed(); - QCOMPARE(model->getTransactionInfo(), QString("this is a test for TransactionInfo")); + QCOMPARE(model->getTransactionInfo(), "this is a <a>test</a> for TransactionInfo"_L1); QCOMPARE(spyWorkflowStarted.count(), 2); QCOMPARE(spyCurrentStateChanged.count(), 2); QCOMPARE(spyStateEntered.count(), 0); @@ -58,6 +60,254 @@ class test_AuthModel } + void test_progressValue() + { + auto* const model = Env::getSingleton(); + + model->resetAuthContext(nullptr); + QCOMPARE(model->getProgressValue(), 0); + + const QSharedPointer context(new AuthContext()); + context->setProgress(50, QString()); + model->resetAuthContext(context); + QCOMPARE(model->getProgressValue(), 50); + } + + + void test_progressMessage() + { + auto* const model = Env::getSingleton(); + + model->resetAuthContext(nullptr); + QCOMPARE(model->getProgressMessage(), QString()); + + const QSharedPointer context(new AuthContext()); + context->setProgress(0, QStringLiteral("TEST")); + model->resetAuthContext(context); + QCOMPARE(model->getProgressMessage(), QStringLiteral("TEST")); + } + + + void test_showChangePinView() + { + auto* const model = Env::getSingleton(); + + model->resetAuthContext(nullptr); + QCOMPARE(model->getShowChangePinView(), false); + + const QSharedPointer context(new AuthContext()); + context->requestChangePinView(); + model->resetAuthContext(context); + QCOMPARE(model->getShowChangePinView(), true); + } + + + void test_resultHeader_data() + { + QTest::addColumn>("context"); + QTest::addColumn("statusCode"); + QTest::addColumn("resultHeader"); + + QTest::addRow("No context") << QSharedPointer() << GlobalStatus::Code::No_Error << ""; + QTest::addRow("Any error") << QSharedPointer::create() << GlobalStatus::Code::Card_Communication_Error << "Authentication failed"; + QTest::addRow("No error") << QSharedPointer::create() << GlobalStatus::Code::No_Error << "Authentication successful"; + QTest::addRow("Browser_Transmission_Error") << QSharedPointer::create() << GlobalStatus::Code::Workflow_Browser_Transmission_Error << "Redirect failed"; + } + + + void test_resultHeader() + { + QFETCH(QSharedPointer, context); + QFETCH(GlobalStatus::Code, statusCode); + QFETCH(QString, resultHeader); + + auto* const model = Env::getSingleton(); + if (context) + { + context->setStatus(GlobalStatus(statusCode)); + } + model->resetAuthContext(context); + + QCOMPARE(model->getResultHeader(), resultHeader); + } + + + void test_getErrorHeader() + { + auto* const model = Env::getSingleton(); + + model->resetAuthContext(nullptr); + QCOMPARE(model->getErrorHeader(), QString()); + + const QSharedPointer context(new AuthContext()); + model->resetAuthContext(context); + QCOMPARE(model->getErrorHeader(), QString()); + + context->setTcTokenUrl(QUrl("https://www.governikus.de/tcToken"_L1)); + QCOMPARE(model->getErrorHeader(), QStringLiteral("https://www.governikus.de")); + } + + + void test_getErrorText_data() + { + QTest::addColumn>("context"); + QTest::addColumn("status"); + QTest::addColumn("result"); + + const GlobalStatus::ExternalInfoMap infoMap { + {GlobalStatus::ExternalInformation::LAST_URL, "https://www.governikus.de"_L1} + }; + + QTest::addRow("No context") << QSharedPointer(nullptr) << GlobalStatus(GlobalStatus::Code::No_Error) << ""; + QTest::addRow("No error") << QSharedPointer::create() << GlobalStatus(GlobalStatus::Code::No_Error) << "No error occurred."; + + QTest::addRow("Any error - No info - No reason") << QSharedPointer::create() << GlobalStatus(GlobalStatus::Code::Card_Communication_Error) << "An error occurred while communicating with the ID card. Please make sure that your ID card is placed correctly on the card reader and try again."; + QTest::addRow("Any error - Info - No reason") << QSharedPointer::create() << GlobalStatus(GlobalStatus::Code::Card_Communication_Error, infoMap) << "An error occurred while communicating with the ID card. Please make sure that your ID card is placed correctly on the card reader and try again.
      (https://www.governikus.de)"; + + const auto context = QSharedPointer::create(); + context->setFailureCode(FailureCode::Reason::Card_Removed); + QTest::addRow("Any error - No info - Reason") << context << GlobalStatus(GlobalStatus::Code::Card_Communication_Error) << "An error occurred while communicating with the ID card. Please make sure that your ID card is placed correctly on the card reader and try again.

      Reason:
      Card_Removed"; + QTest::addRow("Any error - Info - Reason") << context << GlobalStatus(GlobalStatus::Code::Card_Communication_Error, infoMap) << "An error occurred while communicating with the ID card. Please make sure that your ID card is placed correctly on the card reader and try again.
      (https://www.governikus.de)

      Reason:
      Card_Removed"; + } + + + void test_getErrorText() + { + QFETCH(QSharedPointer, context); + QFETCH(GlobalStatus, status); + QFETCH(QString, result); + + auto* const model = Env::getSingleton(); + if (context) + { + context->setStatus(status); + } + model->resetAuthContext(context); + + QCOMPARE(model->getErrorText(), result); + } + + + void test_getStatusCodeString_data() + { + QTest::addColumn>("context"); + QTest::addColumn("statusCode"); + QTest::addColumn("result"); + + QTest::addRow("No context") << QSharedPointer(nullptr) << GlobalStatus::Code::No_Error << "Unknown_Error"; + QTest::addRow("Any error") << QSharedPointer::create() << GlobalStatus::Code::Card_Communication_Error << "Card_Communication_Error"; + QTest::addRow("No error") << QSharedPointer::create() << GlobalStatus::Code::No_Error << "No_Error"; + } + + + void test_getStatusCodeString() + { + QFETCH(QSharedPointer, context); + QFETCH(GlobalStatus::Code, statusCode); + QFETCH(QString, result); + + auto* const model = Env::getSingleton(); + if (context) + { + context->setStatus(GlobalStatus(statusCode)); + } + model->resetAuthContext(context); + + QCOMPARE(model->getStatusCodeString(), result); + } + + + void test_resultViewButtonIcon_data() + { + QTest::addColumn>("context"); + QTest::addColumn("statusCode"); + QTest::addColumn("buttonIcon"); + + QTest::addRow("No context") << QSharedPointer(nullptr) << GlobalStatus::Code::No_Error << ""; + QTest::addRow("Any error") << QSharedPointer::create() << GlobalStatus::Code::Card_Communication_Error << ""; + QTest::addRow("No error") << QSharedPointer::create() << GlobalStatus::Code::No_Error << ""; + QTest::addRow("Browser_Transmission_Error") << QSharedPointer::create() << GlobalStatus::Code::Workflow_Browser_Transmission_Error << "qrc:///images/open_website.svg"; + } + + + void test_resultViewButtonIcon() + { + QFETCH(QSharedPointer, context); + QFETCH(GlobalStatus::Code, statusCode); + QFETCH(QString, buttonIcon); + + auto* const model = Env::getSingleton(); + if (context) + { + context->setStatus(GlobalStatus(statusCode)); + } + model->resetAuthContext(context); + + QCOMPARE(model->getResultViewButtonIcon(), buttonIcon); + } + + + void test_resultViewButtonText_data() + { + QTest::addColumn>("context"); + QTest::addColumn("buttonText"); + + QTest::addRow("No context") << QSharedPointer(nullptr) << ""; + QTest::addRow("Auth") << QSharedPointer(new AuthContext()) << "Return to provider"; + QTest::addRow("SelfAuth") << QSharedPointer(new SelfAuthContext()) << "Back to start page"; + } + + + void test_resultViewButtonText() + { + QFETCH(QSharedPointer, context); + QFETCH(QString, buttonText); + + auto* const model = Env::getSingleton(); + model->resetAuthContext(context); + + QCOMPARE(model->getResultViewButtonText(), buttonText); + } + + + void test_resultViewButtonLink_data() + { + QTest::addColumn>("context"); + QTest::addColumn("statusCode"); + QTest::addColumn("receivedBrowserSendFail"); + QTest::addColumn("refreshUrl"); + QTest::addColumn("buttonLink"); + + const auto& refreshUrl = QUrl("https://dummy.url"_L1); + + QTest::addRow("No context") << QSharedPointer(nullptr) << GlobalStatus::Code::No_Error << false << refreshUrl << QUrl(); + QTest::addRow("Any error") << QSharedPointer::create() << GlobalStatus::Code::Card_Communication_Error << false << refreshUrl << QUrl(); + QTest::addRow("No error") << QSharedPointer::create() << GlobalStatus::Code::No_Error << false << refreshUrl << QUrl(); + QTest::addRow("Browser_Send_Failed") << QSharedPointer::create() << GlobalStatus::Code::No_Error << true << refreshUrl << refreshUrl; + } + + + void test_resultViewButtonLink() + { + QFETCH(QSharedPointer, context); + QFETCH(GlobalStatus::Code, statusCode); + QFETCH(bool, receivedBrowserSendFail); + QFETCH(QUrl, refreshUrl); + QFETCH(QUrl, buttonLink); + + auto* const model = Env::getSingleton(); + if (context) + { + context->setReceivedBrowserSendFailed(receivedBrowserSendFail); + context->setStatus(GlobalStatus(statusCode)); + context->setRefreshUrl(refreshUrl); + } + model->resetAuthContext(context); + + QCOMPARE(model->getResultViewButtonLink(), buttonLink); + } + + }; QTEST_MAIN(test_AuthModel) diff --git a/test/qt/ui/qml/test_CardPositionModel.cpp b/test/qt/ui/qml/test_CardPositionModel.cpp index 9dbb86c1b..68df9fdba 100644 --- a/test/qt/ui/qml/test_CardPositionModel.cpp +++ b/test/qt/ui/qml/test_CardPositionModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ui/qml/test_CertificateDescriptionModel.cpp b/test/qt/ui/qml/test_CertificateDescriptionModel.cpp index 61fe4298d..0a02fa5d3 100644 --- a/test/qt/ui/qml/test_CertificateDescriptionModel.cpp +++ b/test/qt/ui/qml/test_CertificateDescriptionModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,13 +10,12 @@ #include "MockIfdServer.h" #include "TestAuthContext.h" -#include "TestFileHelper.h" #include "context/IfdServiceContext.h" #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -45,7 +44,7 @@ class test_CertificateDescriptionModel private Q_SLOTS: void init() { - mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mModel = Env::getSingleton(); } @@ -64,13 +63,13 @@ class test_CertificateDescriptionModel QCOMPARE(mModel->rowCount(), 4); const QString termsOfUsage = QStringLiteral("Name, Anschrift und E-Mail-Adresse des Diensteanbieters:\nGovernikus GmbH & Co. KG\nHochschulring 4\n28359 Bremen\nE-Mail: kontakt@governikus.de "); - QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::LABEL), QString("Provider")); + QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::LABEL), "Provider"_L1); QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::TEXT), QStringLiteral("Governikus GmbH & Co. KG\nhttps://test.governikus-eid.de")); - QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::LABEL), QString("Certificate issuer")); + QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::LABEL), "Certificate issuer"_L1); QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::TEXT), QStringLiteral("Governikus Test DVCA\nhttp://www.governikus.de")); - QCOMPARE(mModel->data(mModel->index(2), CertificateDescriptionModel::UserRoles::LABEL), QString("Provider information")); + QCOMPARE(mModel->data(mModel->index(2), CertificateDescriptionModel::UserRoles::LABEL), "Provider information"_L1); QCOMPARE(mModel->data(mModel->index(2), CertificateDescriptionModel::UserRoles::TEXT), termsOfUsage); - QCOMPARE(mModel->data(mModel->index(3), CertificateDescriptionModel::UserRoles::LABEL), QString("Validity")); + QCOMPARE(mModel->data(mModel->index(3), CertificateDescriptionModel::UserRoles::LABEL), "Validity"_L1); QCOMPARE(spy.count(), 1); } @@ -86,22 +85,22 @@ class test_CertificateDescriptionModel const auto& validModel = mModel->index(1, 0); - QCOMPARE(mModel->data(validModel, CertificateDescriptionModel::UserRoles::LABEL), QString("Certificate issuer")); + QCOMPARE(mModel->data(validModel, CertificateDescriptionModel::UserRoles::LABEL), "Certificate issuer"_L1); QCOMPARE(mModel->data(validModel, CertificateDescriptionModel::UserRoles::TEXT), QStringLiteral("Governikus Test DVCA\nhttp://www.governikus.de")); QCOMPARE(mModel->data(validModel, 0), QVariant()); - QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::LABEL), QString("Validity")); - QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::TEXT), QString("5/21/20 - 6/20/20")); + QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::LABEL), "Validity"_L1); + QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::TEXT), "5/21/20 - 6/20/20"_L1); } void test_Validity() { - mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_ordered_certificates.xml")); + mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_ordered_certificates.xml"_L1)); mContext->initAccessRightManager(mContext->getDidAuthenticateEac1()->getCvCertificates().last()); mModel->resetContext(mContext); - QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::LABEL), QString("Validity")); - QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::TEXT), QString("5/21/20 - 6/20/20")); + QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::LABEL), "Validity"_L1); + QCOMPARE(mModel->data(mModel->index(3, 0), CertificateDescriptionModel::UserRoles::TEXT), "5/21/20 - 6/20/20"_L1); } @@ -120,11 +119,11 @@ class test_CertificateDescriptionModel const auto& establishPaceChannel = createDataToParse(PacePasswordId::PACE_PIN); ifdContext->setEstablishPaceChannel(QSharedPointer::create(QString(), establishPaceChannel, 6)); - QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::LABEL), QString("Provider")); - QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::TEXT), QString("Gesamtverband der deutschen Versicherungswirtschaft e.V.\n")); - QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::LABEL), QString("Certificate issuer")); - QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::TEXT), QString("D-Trust GmbH\n")); - QCOMPARE(mModel->data(mModel->index(2), CertificateDescriptionModel::UserRoles::LABEL), QString("Provider information")); + QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::LABEL), "Provider"_L1); + QCOMPARE(mModel->data(mModel->index(0), CertificateDescriptionModel::UserRoles::TEXT), "Gesamtverband der deutschen Versicherungswirtschaft e.V.\n"_L1); + QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::LABEL), "Certificate issuer"_L1); + QCOMPARE(mModel->data(mModel->index(1), CertificateDescriptionModel::UserRoles::TEXT), "D-Trust GmbH\n"_L1); + QCOMPARE(mModel->data(mModel->index(2), CertificateDescriptionModel::UserRoles::LABEL), "Provider information"_L1); } diff --git a/test/qt/ui/qml/test_ChangePinModel.cpp b/test/qt/ui/qml/test_ChangePinModel.cpp index 183e68105..762a8c23c 100644 --- a/test/qt/ui/qml/test_ChangePinModel.cpp +++ b/test/qt/ui/qml/test_ChangePinModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -55,20 +55,20 @@ class test_ChangePinModel } - void test_supportedPlugInTypes() + void test_supportedPluginTypes() { const auto& model = Env::getSingleton(); QSharedPointer context(new ChangePinContext()); model->resetChangePinContext(context); #if __has_include("context/PersonalizationContext.h") - QVERIFY(model->getSupportedReaderPlugInTypes().contains(ReaderManagerPlugInType::SMART)); + QVERIFY(model->getSupportedReaderPluginTypes().contains(ReaderManagerPluginType::SMART)); #else - QVERIFY(!model->getSupportedReaderPlugInTypes().contains(ReaderManagerPlugInType::SMART)); + QVERIFY(!model->getSupportedReaderPluginTypes().contains(ReaderManagerPluginType::SMART)); #endif QSharedPointer contextTransportPin(new ChangePinContext(true)); model->resetChangePinContext(contextTransportPin); - QVERIFY(!model->getSupportedReaderPlugInTypes().contains(ReaderManagerPlugInType::SMART)); + QVERIFY(!model->getSupportedReaderPluginTypes().contains(ReaderManagerPluginType::SMART)); } diff --git a/test/qt/ui/qml/test_ChatModel.cpp b/test/qt/ui/qml/test_ChatModel.cpp index 8bceabbf5..18dea9765 100644 --- a/test/qt/ui/qml/test_ChatModel.cpp +++ b/test/qt/ui/qml/test_ChatModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -19,6 +19,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -182,7 +183,7 @@ class test_ChatModel QVERIFY(mModel->mSelectedRights.contains(AccessRight::READ_DG16)); QCOMPARE(spy.count(), 1); auto arguments = spy.takeFirst(); - auto role = arguments.at(2).value>(); + auto role = arguments.at(2).value>(); QCOMPARE(arguments.at(0), index); QCOMPARE(arguments.at(1), index); QCOMPARE(role.at(0), ChatModel::ChatRoles::SELECTED_ROLE); @@ -192,7 +193,7 @@ class test_ChatModel void test_DataNameRole() { mModel->resetContext(mAuthContext); - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"_L1); QSharedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); mAuthContext->setDidAuthenticateEac1(eac1); mAuthContext->initAccessRightManager(eac1->getCvCertificates().at(0)); @@ -203,7 +204,7 @@ class test_ChatModel QVERIFY(!requiredAge.isEmpty()); qDebug() << mModel->data(index, ChatModel::ChatRoles::NAME_ROLE); - QCOMPARE(mModel->data(index, ChatModel::ChatRoles::NAME_ROLE), "Age verification (" + requiredAge + ")"); + QCOMPARE(mModel->data(index, ChatModel::ChatRoles::NAME_ROLE), "Age verification ("_L1 + requiredAge + ")"_L1); } diff --git a/test/qt/ui/qml/test_ConnectivityManager.cpp b/test/qt/ui/qml/test_ConnectivityManager.cpp index 2ede50bb3..14e9a95ce 100644 --- a/test/qt/ui/qml/test_ConnectivityManager.cpp +++ b/test/qt/ui/qml/test_ConnectivityManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,7 +13,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -32,7 +32,6 @@ class test_ConnectivityManager void test_Active() { ConnectivityManager manager; - const QString name = QStringLiteral("name"); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); QSignalSpy signalSpy(&manager, &ConnectivityManager::fireNetworkInterfaceActiveChanged); @@ -40,7 +39,7 @@ class test_ConnectivityManager manager.setActive(true); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("A network interface is now available")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("A network interface is now available"_L1)); QCOMPARE(signalSpy.count(), 1); QVERIFY(manager.isNetworkInterfaceActive()); @@ -51,7 +50,7 @@ class test_ConnectivityManager manager.setActive(false); QCOMPARE(logSpy.count(), 1); - QVERIFY(logSpy.takeFirst().at(0).toString().contains("An active network interface is no longer available")); + QVERIFY(logSpy.takeFirst().at(0).toString().contains("An active network interface is no longer available"_L1)); QCOMPARE(signalSpy.count(), 2); QVERIFY(!manager.isNetworkInterfaceActive()); diff --git a/test/qt/ui/qml/test_Email.cpp b/test/qt/ui/qml/test_Email.cpp new file mode 100644 index 000000000..5ca6c836b --- /dev/null +++ b/test/qt/ui/qml/test_Email.cpp @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "Email.h" + +#include +#include +#include + + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +class test_Email + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase() + { + QCoreApplication::setOrganizationName("orgaName"_L1); + QCoreApplication::setOrganizationDomain("orgaDomain"_L1); + QCoreApplication::setApplicationVersion("appVersion"_L1); + } + + + void test_generateMailBody_data() + { + QTest::addColumn("serviceUrl"); + QTest::addColumn("percentEncoding"); + QTest::addColumn("result"); + + const auto& resultWithService = uR"(Please describe the error that occurs. Our support is available to you in German and English. + + +Application: Test_ui_qml_Email +Application%20Version: appVersion +Organization: orgaName +Organization%20Domain: orgaDomain +System: .+ +Kernel: .+ +Architecture: .+ +Device: .+ +Qt%20Version: .+ +OpenSSL%20Version: .+ + +Error code: +Card_Communication_Error + +Service URL: +https://www.foo.bar + +Parameter of occurred error: +https://www.test.de)"_s; + QTest::newRow("service - percent") << QStringLiteral("https://www.foo.bar") << true << resultWithService; + QTest::newRow("service - no percent") << QStringLiteral("https://www.foo.bar") << false << QString(resultWithService).replace("%20"_L1, " "_L1); + + const auto resultWithoutService = QString(resultWithService).remove(346, 34); + QTest::newRow("no service - percent") << QString() << true << resultWithoutService; + QTest::newRow("no service - no percent") << QString() << false << QString(resultWithoutService).replace("%20"_L1, " "_L1); + } + + + void test_generateMailBody() + { + QFETCH(QString, serviceUrl); + QFETCH(bool, percentEncoding); + QFETCH(QString, result); + + const GlobalStatus::ExternalInfoMap infoMap { + {GlobalStatus::ExternalInformation::LAST_URL, "https://www.test.de"_L1} + }; + const GlobalStatus globalStatus(GlobalStatus::Code::Card_Communication_Error, infoMap); + const auto& mailBody = generateMailBody(globalStatus, serviceUrl, percentEncoding); + + const QRegularExpression re(result); + QVERIFY(re.match(mailBody).hasMatch()); + } + + +}; + +QTEST_GUILESS_MAIN(test_Email) +#include "test_Email.moc" diff --git a/test/qt/ui/qml/test_FormattedTextModel.cpp b/test/qt/ui/qml/test_FormattedTextModel.cpp index 8bc5453c4..17f7ab0eb 100644 --- a/test/qt/ui/qml/test_FormattedTextModel.cpp +++ b/test/qt/ui/qml/test_FormattedTextModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -127,26 +127,26 @@ class test_FormattedTextModel QTest::addColumn("modelContent"); PairList fileContent; - fileContent << qMakePair(QStringLiteral("This is a header"), FormattedTextModel::HEADER); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("First section"), FormattedTextModel::SECTION); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("Subsection one"), FormattedTextModel::SUBSECTION); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("This multiline text will be concatenated to one text."), FormattedTextModel::REGULARTEXT); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("Subsection two"), FormattedTextModel::SUBSECTION); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("Some list items:"), FormattedTextModel::REGULARTEXT); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("First"), FormattedTextModel::LISTITEM); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("Second"), FormattedTextModel::LISTITEM); - fileContent << qMakePair(QString(), FormattedTextModel::EMPTY); - fileContent << qMakePair(QStringLiteral("Third"), FormattedTextModel::LISTITEM); + fileContent << qMakePair(QStringLiteral("This is a header"), FormattedTextModel::LineType::HEADER); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("First section"), FormattedTextModel::LineType::SECTION); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("Subsection one"), FormattedTextModel::LineType::SUBSECTION); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("This multiline text will be concatenated to one text."), FormattedTextModel::LineType::REGULARTEXT); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("Subsection two"), FormattedTextModel::LineType::SUBSECTION); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("Some list items:"), FormattedTextModel::LineType::REGULARTEXT); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("First"), FormattedTextModel::LineType::LISTITEM); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("Second"), FormattedTextModel::LineType::LISTITEM); + fileContent << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); + fileContent << qMakePair(QStringLiteral("Third"), FormattedTextModel::LineType::LISTITEM); PairList fileSeparator; - fileSeparator << qMakePair(QString(), FormattedTextModel::EMPTY); + fileSeparator << qMakePair(QString(), FormattedTextModel::LineType::EMPTY); QTest::addRow("formattedText.txt") << ":/qml/formattedText.txt" << 35 << fileContent + fileSeparator + fileContent; } @@ -166,7 +166,7 @@ class test_FormattedTextModel { const auto modelIndex = textModel.index(i); QCOMPARE(textModel.data(modelIndex, FormattedTextModel::ContentRole), modelContent.at(i).first); - QCOMPARE(textModel.data(modelIndex, FormattedTextModel::LineTypeRole), modelContent.at(i).second); + QCOMPARE(textModel.data(modelIndex, FormattedTextModel::LineTypeRole).value(), modelContent.at(i).second); } } diff --git a/test/qt/ui/qml/test_LogFilterModel.cpp b/test/qt/ui/qml/test_LogFilterModel.cpp index ba9abaf44..72ad6aa02 100644 --- a/test/qt/ui/qml/test_LogFilterModel.cpp +++ b/test/qt/ui/qml/test_LogFilterModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "LogFilterModel.h" @@ -9,7 +9,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -22,9 +22,6 @@ class test_LogFilterModel { Q_OBJECT - private: - QScopedPointer mModel; - private Q_SLOTS: void initTestCase() { @@ -32,70 +29,66 @@ class test_LogFilterModel } - void init() + void filtering() { - mModel.reset(new LogFilterModel()); + LogFilterModel model; qCDebug(card) << "test"; qCWarning(card) << "test"; - } + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList()); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList()); + QCOMPARE(model.rowCount(), 3); - void filtering() - { - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W")})); - QCOMPARE(mModel->getSelectedLevels(), QSet()); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card")})); - QCOMPARE(mModel->getSelectedCategories(), QSet()); - QCOMPARE(mModel->rowCount(), 3); - - QSignalSpy spyLevel(mModel.data(), &LogFilterModel::fireLevelsChanged); - QSignalSpy spyCategories(mModel.data(), &LogFilterModel::fireCategoriesChanged); + QSignalSpy spyLevel(&model, &LogFilterModel::fireLevelsChanged); + QSignalSpy spyCategories(&model, &LogFilterModel::fireCategoriesChanged); qCDebug(gui) << "test"; QCOMPARE(spyLevel.count(), 0); - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W")})); - QCOMPARE(mModel->getSelectedLevels(), QSet()); + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList()); QCOMPARE(spyCategories.count(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card"), QString("gui")})); - QCOMPARE(mModel->getSelectedCategories(), QSet()); - QCOMPARE(mModel->rowCount(), 4); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1, "gui"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList()); + QCOMPARE(model.rowCount(), 4); qCInfo(gui) << "test"; QCOMPARE(spyLevel.count(), 1); - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W"), QString("I")})); - QCOMPARE(mModel->getSelectedLevels(), QSet()); + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "I"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList()); QCOMPARE(spyCategories.count(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card"), QString("gui")})); - QCOMPARE(mModel->getSelectedCategories(), QSet()); - QCOMPARE(mModel->rowCount(), 5); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1, "gui"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList()); + QCOMPARE(model.rowCount(), 5); - mModel->configureLevel(QString("D"), true); + model.configureLevel("D"_L1, true); QCOMPARE(spyLevel.count(), 2); - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W"), QString("I")})); - QCOMPARE(mModel->getSelectedLevels(), QSet({QString("D")})); + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "I"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList({"D"_L1})); QCOMPARE(spyCategories.count(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card"), QString("gui")})); - QCOMPARE(mModel->getSelectedCategories(), QSet()); - QCOMPARE(mModel->rowCount(), 3); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1, "gui"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList()); + QCOMPARE(model.rowCount(), 3); - mModel->configureCategory(QString("card"), true); + model.configureCategory("card"_L1, true); QCOMPARE(spyLevel.count(), 2); - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W"), QString("I")})); - QCOMPARE(mModel->getSelectedLevels(), QSet({QString("D")})); + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "I"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList({"D"_L1})); QCOMPARE(spyCategories.count(), 2); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card"), QString("gui")})); - QCOMPARE(mModel->getSelectedCategories(), QSet({QString("card")})); - QCOMPARE(mModel->rowCount(), 1); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1, "gui"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList({"card"_L1})); + QCOMPARE(model.rowCount(), 1); - mModel->configureLevel(QString("D"), false); + model.configureLevel("D"_L1, false); QCOMPARE(spyLevel.count(), 3); - QCOMPARE(mModel->getLevels(), QSet({QString("D"), QString("W"), QString("I")})); - QCOMPARE(mModel->getSelectedLevels(), QSet()); + QCOMPARE(model.getLevels(), QStringList({"D"_L1, "I"_L1, "W"_L1})); + QCOMPARE(model.getSelectedLevels(), QStringList()); QCOMPARE(spyCategories.count(), 2); - QCOMPARE(mModel->getCategories(), QSet({QString("default"), QString("card"), QString("gui")})); - QCOMPARE(mModel->getSelectedCategories(), QSet({QString("card")})); - QCOMPARE(mModel->rowCount(), 2); + QCOMPARE(model.getCategories(), QStringList({"card"_L1, "default"_L1, "gui"_L1})); + QCOMPARE(model.getSelectedCategories(), QStringList({"card"_L1})); + QCOMPARE(model.rowCount(), 2); } diff --git a/test/qt/ui/qml/test_LogModel.cpp b/test/qt/ui/qml/test_LogModel.cpp index 1d82d9bed..432181f27 100644 --- a/test/qt/ui/qml/test_LogModel.cpp +++ b/test/qt/ui/qml/test_LogModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,7 +13,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_LogModel @@ -54,39 +54,39 @@ class test_LogModel void test_AddLogEntry_data() { - QTest::addColumn("input"); - QTest::addColumn("origin"); - QTest::addColumn("level"); - QTest::addColumn("category"); - QTest::addColumn("message"); - - QTest::newRow("validEntry") << QString("input : test") << QString("input") << QString("D") << QString("input") << QString("test"); - QTest::newRow("empty") << QString(" : ") << QString() << QString("D") << QString() << QString(); - QTest::newRow("leftEmpty") << QString(" : test") << QString() << QString("D") << QString() << QString("test"); - QTest::newRow("rightEmpty") << QString("input : ") << QString("input") << QString("D") << QString("input") << QString(); - QTest::newRow("NoSpaceRight") << QString("input :test") << QString("input :test") << QString("D") << QString("input") << QString(); - QTest::newRow("NoSpaceLeft") << QString("input: test") << QString("input: test") << QString("D") << QString("input:") << QString(); - QTest::newRow("invalidEntry") << QString("inputTest") << QString("inputTest") << QString("D") << QString("inputTest") << QString(); - QTest::newRow("NoSpaces") << QString("input:test") << QString("input:test") << QString("D") << QString("input:test") << QString(); - QTest::newRow("emptyString") << QString() << QString() << QString("D") << QString() << QString(); - QTest::newRow("::") << QString("::") << QString("::") << QString("D") << QString("::") << QString(); - QTest::newRow("a : b : c") << QString("a : b : c") << QString("a") << QString("D") << QString("a") << QString("b : c"); - QTest::newRow("categorySpacesRight") << QString("cat abc : test") << QString("cat abc") << QString("D") << QString("cat") << QString("test"); - QTest::newRow("categorySpaceLeft") << QString(" cat abc : test") << QString("cat abc") << QString("D") << QString("") << QString("test"); - QTest::newRow("levelW") << QString("cat 123 W abc : test") << QString("cat 123 W abc") << QString("W") << QString("cat") << QString("test"); - QTest::newRow("levelA") << QString("cat 123 A abc : test") << QString("cat 123 A abc") << QString("A") << QString("cat") << QString("test"); - QTest::newRow("levelLongPid") << QString("cat 12345 W abc : test") << QString("cat 12345 W abc") << QString("W") << QString("cat") << QString("test"); - QTest::newRow("levelWrongFormat") << QString("cat 123W abc : test") << QString("cat 123W abc") << QString("D") << QString("cat") << QString("test"); + QTest::addColumn("input"); + QTest::addColumn("origin"); + QTest::addColumn("level"); + QTest::addColumn("category"); + QTest::addColumn("message"); + + QTest::newRow("validEntry") << QLatin1String("input : test") << QLatin1String("input") << QLatin1String("D") << QLatin1String("input") << QLatin1String("test"); + QTest::newRow("empty") << QLatin1String(" : ") << QLatin1String() << QLatin1String("D") << QLatin1String() << QLatin1String(); + QTest::newRow("leftEmpty") << QLatin1String(" : test") << QLatin1String() << QLatin1String("D") << QLatin1String() << QLatin1String("test"); + QTest::newRow("rightEmpty") << QLatin1String("input : ") << QLatin1String("input") << QLatin1String("D") << QLatin1String("input") << QLatin1String(); + QTest::newRow("NoSpaceRight") << QLatin1String("input :test") << QLatin1String("input :test") << QLatin1String("D") << QLatin1String("input") << QLatin1String(); + QTest::newRow("NoSpaceLeft") << QLatin1String("input: test") << QLatin1String("input: test") << QLatin1String("D") << QLatin1String("input:") << QLatin1String(); + QTest::newRow("invalidEntry") << QLatin1String("inputTest") << QLatin1String("inputTest") << QLatin1String("D") << QLatin1String("inputTest") << QLatin1String(); + QTest::newRow("NoSpaces") << QLatin1String("input:test") << QLatin1String("input:test") << QLatin1String("D") << QLatin1String("input:test") << QLatin1String(); + QTest::newRow("emptyString") << QLatin1String() << QLatin1String() << QLatin1String("D") << QLatin1String() << QLatin1String(); + QTest::newRow("::") << QLatin1String("::") << QLatin1String("::") << QLatin1String("D") << QLatin1String("::") << QLatin1String(); + QTest::newRow("a : b : c") << QLatin1String("a : b : c") << QLatin1String("a") << QLatin1String("D") << QLatin1String("a") << QLatin1String("b : c"); + QTest::newRow("categorySpacesRight") << QLatin1String("cat abc : test") << QLatin1String("cat abc") << QLatin1String("D") << QLatin1String("cat") << QLatin1String("test"); + QTest::newRow("categorySpaceLeft") << QLatin1String(" cat abc : test") << QLatin1String("cat abc") << QLatin1String("D") << QLatin1String("") << QLatin1String("test"); + QTest::newRow("levelW") << QLatin1String("cat 123 W abc : test") << QLatin1String("cat 123 W abc") << QLatin1String("W") << QLatin1String("cat") << QLatin1String("test"); + QTest::newRow("levelA") << QLatin1String("cat 123 A abc : test") << QLatin1String("cat 123 A abc") << QLatin1String("A") << QLatin1String("cat") << QLatin1String("test"); + QTest::newRow("levelLongPid") << QLatin1String("cat 12345 W abc : test") << QLatin1String("cat 12345 W abc") << QLatin1String("W") << QLatin1String("cat") << QLatin1String("test"); + QTest::newRow("levelWrongFormat") << QLatin1String("cat 123W abc : test") << QLatin1String("cat 123W abc") << QLatin1String("D") << QLatin1String("cat") << QLatin1String("test"); } void test_AddLogEntry() { - QFETCH(QString, input); - QFETCH(QString, origin); - QFETCH(QString, level); - QFETCH(QString, category); - QFETCH(QString, message); + QFETCH(QLatin1String, input); + QFETCH(QLatin1String, origin); + QFETCH(QLatin1String, level); + QFETCH(QLatin1String, category); + QFETCH(QLatin1String, message); QSignalSpy spyLevel(mModel, &LogModel::fireLevelsChanged); QSignalSpy spyCategorie(mModel, &LogModel::fireCategoriesChanged); @@ -115,70 +115,70 @@ class test_LogModel QSignalSpy spyLevel(mModel, &LogModel::fireLevelsChanged); QSignalSpy spyCategorie(mModel, &LogModel::fireCategoriesChanged); - mModel->addLogEntry(QString("cat 0000.00.00 00:00:00.000 000 W test : test")); + mModel->addLogEntry("cat 0000.00.00 00:00:00.000 000 W test : test"_L1); QCOMPARE(spyLevel.size(), 1); - QCOMPARE(mModel->getLevels(), QSet({QString("W")})); + QCOMPARE(mModel->getLevels(), QSet({"W"_L1})); QCOMPARE(spyCategorie.size(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("cat")})); + QCOMPARE(mModel->getCategories(), QSet({"cat"_L1})); - mModel->addLogEntry(QString("cat 0000.00.00 00:00:00.000 000 W test : test")); + mModel->addLogEntry("cat 0000.00.00 00:00:00.000 000 W test : test"_L1); QCOMPARE(spyLevel.size(), 1); - QCOMPARE(mModel->getLevels(), QSet({QString("W")})); + QCOMPARE(mModel->getLevels(), QSet({"W"_L1})); QCOMPARE(spyCategorie.size(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("cat")})); + QCOMPARE(mModel->getCategories(), QSet({"cat"_L1})); - mModel->addLogEntry(QString("cat 0000.00.00 00:00:00.000 000 I test : test")); + mModel->addLogEntry("cat 0000.00.00 00:00:00.000 000 I test : test"_L1); QCOMPARE(spyLevel.size(), 2); - QCOMPARE(mModel->getLevels(), QSet({QString("W"), QString("I")})); + QCOMPARE(mModel->getLevels(), QSet({"W"_L1, "I"_L1})); QCOMPARE(spyCategorie.size(), 1); - QCOMPARE(mModel->getCategories(), QSet({QString("cat")})); + QCOMPARE(mModel->getCategories(), QSet({"cat"_L1})); - mModel->addLogEntry(QString("dog 0000.00.00 00:00:00.000 000 I test : test")); + mModel->addLogEntry("dog 0000.00.00 00:00:00.000 000 I test : test"_L1); QCOMPARE(spyLevel.size(), 2); - QCOMPARE(mModel->getLevels(), QSet({QString("W"), QString("I")})); + QCOMPARE(mModel->getLevels(), QSet({"W"_L1, "I"_L1})); QCOMPARE(spyCategorie.size(), 2); - QCOMPARE(mModel->getCategories(), QSet({QString("cat"), QString("dog")})); + QCOMPARE(mModel->getCategories(), QSet({"cat"_L1, "dog"_L1})); - mModel->addLogEntry(QString("dog 0000.00.00 00:00:00.000 000 I test : test")); + mModel->addLogEntry("dog 0000.00.00 00:00:00.000 000 I test : test"_L1); QCOMPARE(spyLevel.size(), 2); - QCOMPARE(mModel->getLevels(), QSet({QString("W"), QString("I")})); + QCOMPARE(mModel->getLevels(), QSet({"W"_L1, "I"_L1})); QCOMPARE(spyCategorie.size(), 2); - QCOMPARE(mModel->getCategories(), QSet({QString("cat"), QString("dog")})); + QCOMPARE(mModel->getCategories(), QSet({"cat"_L1, "dog"_L1})); } void test_AddMultilineLogEntry() { - mModel->addLogEntry(QString("FooBar")); + mModel->addLogEntry(QLatin1String("FooBar")); QCOMPARE(mModel->mLogEntries.size(), 1); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar")); - mModel->addLogEntry(QString("FooBar")); + mModel->addLogEntry(QLatin1String("FooBar")); QCOMPARE(mModel->mLogEntries.size(), 1); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar\nFooBar")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar\nFooBar")); - mModel->addLogEntry(QString("cat 0000.00.00 00:00:00.000 000 test")); + mModel->addLogEntry(QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); QCOMPARE(mModel->mLogEntries.size(), 2); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar\nFooBar")); - QCOMPARE(mModel->mLogEntries.at(1), QString("cat 0000.00.00 00:00:00.000 000 test")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar\nFooBar")); + QCOMPARE(mModel->mLogEntries.at(1), QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); - mModel->addLogEntry(QString("cat 0001.02.03 04:05:06.007 0000008 test")); + mModel->addLogEntry(QLatin1String("cat 0001.02.03 04:05:06.007 0000008 test")); QCOMPARE(mModel->mLogEntries.size(), 3); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar\nFooBar")); - QCOMPARE(mModel->mLogEntries.at(1), QString("cat 0000.00.00 00:00:00.000 000 test")); - QCOMPARE(mModel->mLogEntries.at(2), QString("cat 0001.02.03 04:05:06.007 0000008 test")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar\nFooBar")); + QCOMPARE(mModel->mLogEntries.at(1), QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); + QCOMPARE(mModel->mLogEntries.at(2), QLatin1String("cat 0001.02.03 04:05:06.007 0000008 test")); - mModel->addLogEntry(QString("BarFoo")); + mModel->addLogEntry(QLatin1String("BarFoo")); QCOMPARE(mModel->mLogEntries.size(), 3); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar\nFooBar")); - QCOMPARE(mModel->mLogEntries.at(1), QString("cat 0000.00.00 00:00:00.000 000 test")); - QCOMPARE(mModel->mLogEntries.at(2), QString("cat 0001.02.03 04:05:06.007 0000008 test\nBarFoo")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar\nFooBar")); + QCOMPARE(mModel->mLogEntries.at(1), QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); + QCOMPARE(mModel->mLogEntries.at(2), QLatin1String("cat 0001.02.03 04:05:06.007 0000008 test\nBarFoo")); - mModel->addLogEntry(QString("cat 0000.00.00 00:00:00.000 000 test")); + mModel->addLogEntry(QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); QCOMPARE(mModel->mLogEntries.size(), 3); - QCOMPARE(mModel->mLogEntries.at(0), QString("FooBar\nFooBar")); - QCOMPARE(mModel->mLogEntries.at(1), QString("cat 0000.00.00 00:00:00.000 000 test")); - QCOMPARE(mModel->mLogEntries.at(2), QString("cat 0001.02.03 04:05:06.007 0000008 test\nBarFoo\ncat 0000.00.00 00:00:00.000 000 test")); + QCOMPARE(mModel->mLogEntries.at(0), QLatin1String("FooBar\nFooBar")); + QCOMPARE(mModel->mLogEntries.at(1), QLatin1String("cat 0000.00.00 00:00:00.000 000 test")); + QCOMPARE(mModel->mLogEntries.at(2), QLatin1String("cat 0001.02.03 04:05:06.007 0000008 test\nBarFoo\ncat 0000.00.00 00:00:00.000 000 test")); } @@ -194,21 +194,21 @@ class test_LogModel void test_SetLogEntries_data() { - QTest::addColumn("fileName"); + QTest::addColumn("fileName"); QTest::addColumn("logEntriesSize"); QTest::addColumn("logLevelSize"); QTest::addColumn("logCategoriesSize"); - QTest::newRow("empty") << QString(":/logfiles/empty.txt") << 0 << 0 << 0; - QTest::newRow("size1") << QString(":/logfiles/size1.txt") << 1 << 1 << 1; - QTest::newRow("size42") << QString(":/logfiles/size42.txt") << 42 << 1 << 1; - QTest::newRow("auth") << QString(":/logfiles/auth.txt") << 1223 << 4 << 19; + QTest::newRow("empty") << QLatin1String(":/logfiles/empty.txt") << 0 << 0 << 0; + QTest::newRow("size1") << QLatin1String(":/logfiles/size1.txt") << 1 << 1 << 1; + QTest::newRow("size42") << QLatin1String(":/logfiles/size42.txt") << 42 << 1 << 1; + QTest::newRow("auth") << QLatin1String(":/logfiles/auth.txt") << 1223 << 4 << 19; } void test_SetLogEntries() { - QFETCH(QString, fileName); + QFETCH(QLatin1String, fileName); QFETCH(int, logEntriesSize); QFETCH(int, logLevelSize); QFETCH(int, logCategoriesSize); @@ -233,24 +233,24 @@ class test_LogModel void test_OnNewLogMsg_data() { - QTest::addColumn("msg"); - QTest::addColumn("fileName"); + QTest::addColumn("msg"); + QTest::addColumn("fileName"); QTest::addColumn("selectedFile"); QTest::addColumn("newLogMsgCounter"); QTest::addColumn("logEntriesSizeChange"); - QTest::newRow("emptyFile_MsgAdded") << QString("test : input") << QString(":/logfiles/empty.txt") << 0 << 1 << 1; - QTest::newRow("emptyFile_MsgNotAdded") << QString(" : ") << QString(":/logfiles/empty.txt") << 1 << 0 << 0; + QTest::newRow("emptyFile_MsgAdded") << QLatin1String("test : input") << QLatin1String(":/logfiles/empty.txt") << 0 << 1 << 1; + QTest::newRow("emptyFile_MsgNotAdded") << QLatin1String(" : ") << QLatin1String(":/logfiles/empty.txt") << 1 << 0 << 0; - QTest::newRow("size1_MsgAdded") << QString("test : input") << QString(":/logfiles/size1.txt") << 0 << 1 << 1; - QTest::newRow("size1_MsgNotAdded") << QString(" : ") << QString(":/logfiles/size1.txt") << 1 << 0 << 0; + QTest::newRow("size1_MsgAdded") << QLatin1String("test : input") << QLatin1String(":/logfiles/size1.txt") << 0 << 1 << 1; + QTest::newRow("size1_MsgNotAdded") << QLatin1String(" : ") << QLatin1String(":/logfiles/size1.txt") << 1 << 0 << 0; } void test_OnNewLogMsg() { - QFETCH(QString, msg); - QFETCH(QString, fileName); + QFETCH(QLatin1String, msg); + QFETCH(QLatin1String, fileName); QFETCH(int, selectedFile); QFETCH(int, newLogMsgCounter); QFETCH(int, logEntriesSizeChange); @@ -283,10 +283,7 @@ class test_LogModel resetModel(new LogModel()); QCOMPARE(mModel->getLogFileNames().size(), 2); - mModel->removeCurrentLogFile(); - QCOMPARE(mModel->getLogFileNames().size(), 2); - mModel->setLogFile(1); - mModel->removeCurrentLogFile(); + mModel->removeOtherLogFiles(); QCOMPARE(mModel->getLogFileNames().size(), 1); } diff --git a/test/qt/ui/qml/test_NotificationModel.cpp b/test/qt/ui/qml/test_NotificationModel.cpp index 418c2c7c0..1889c2113 100644 --- a/test/qt/ui/qml/test_NotificationModel.cpp +++ b/test/qt/ui/qml/test_NotificationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_NotificationModel @@ -48,7 +49,7 @@ class test_NotificationModel { QSignalSpy spy(mModel, &NotificationModel::fireLastTypeChanged); - const QString msg("message"); + const QLatin1String msg("message"); const QLoggingCategory develMode("developermode"); for (int i = 0; i < 20; i++) @@ -59,7 +60,7 @@ class test_NotificationModel QCOMPARE(mModel->mNotificationEntries.at(i).mType, QLatin1String(develMode.categoryName())); } - const QString newMsg("new message"); + const QLatin1String newMsg("new message"); const QLoggingCategory feedback("feedback"); qCDebug(feedback).noquote() << newMsg; @@ -81,8 +82,8 @@ class test_NotificationModel QTest::newRow("entriesEmpty") << 0 << 0 << 0 << QVariant(); QTest::newRow("RowNumberEqualsSize") << 2 << 2 << type << QVariant(); - QTest::newRow("entriesFirstIndex0Type") << 4 << 5 << type << QVariant(QString("developermode")); - QTest::newRow("entriesFirstIndex2Text") << 3 << 22 << 5 << QVariant(QString("message")); + QTest::newRow("entriesFirstIndex0Type") << 4 << 5 << type << QVariant("developermode"_L1); + QTest::newRow("entriesFirstIndex2Text") << 3 << 22 << 5 << QVariant("message"_L1); QTest::newRow("indexOutOfRange") << 10 << 5 << time << QVariant(); } @@ -97,7 +98,7 @@ class test_NotificationModel QSignalSpy spy(mModel, &NotificationModel::fireLastTypeChanged); QModelIndex index = mModel->createIndex(row, 0); - const QString msg("message"); + const QLatin1String msg("message"); const QLoggingCategory category("developermode"); for (int i = 0; i < size; i++) { diff --git a/test/qt/ui/qml/test_NumberModel.cpp b/test/qt/ui/qml/test_NumberModel.cpp index fa3333d25..e96401454 100644 --- a/test/qt/ui/qml/test_NumberModel.cpp +++ b/test/qt/ui/qml/test_NumberModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -241,7 +241,7 @@ class test_NumberModel const QString readerName = QStringLiteral("name"); const QString test = QStringLiteral("test"); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); Q_EMIT readerManager->fireReaderPropertiesUpdated(ReaderInfo()); QCOMPARE(spyReaderNameChanged.count(), 0); @@ -283,6 +283,9 @@ class test_NumberModel mModel->resetContext(context); QCOMPARE(mModel->getInputError(), QString()); + context->setLastPaceResult(CardReturnCode::OK_PUK); + QCOMPARE(mModel->getInputError(), QString()); + context->setLastPaceResult(CardReturnCode::CANCELLATION_BY_USER); QCOMPARE(mModel->getInputError(), QString()); @@ -292,22 +295,23 @@ class test_NumberModel context->setCardConnection(connection); context->setLastPaceResult(CardReturnCode::INVALID_PIN); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, six-digit ID card PIN. You have two further attempts to enter the correct ID card PIN.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 6-digit ID card PIN.

      You have 2 further attempts to enter the correct ID card PIN.")); context->setLastPaceResult(CardReturnCode::INVALID_PIN_2); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, six-digit ID card PIN twice. " - "For a third attempt, the six-digit Card Access Number (CAN) must be entered first. " - "You can find your CAN in the bottom right on the front of your ID card.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 6-digit ID card PIN 2 times.

      " + "For a 3rd attempt, the 6-digit Card Access Number (CAN) must be entered first. " + "You can find your CAN in the bottom right on the front of your ID card.")); context->setLastPaceResult(CardReturnCode::INVALID_PIN_3); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, six-digit ID card PIN thrice, your ID card PIN is now blocked. " - "To remove the block, the ten-digit PUK must be entered first.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 6-digit ID card PIN 3 times. Your ID card PIN is now blocked.

      " + "To remove the block, the 10-digit PUK must be entered first. " + "You can find the PUK in the bottom right next to the Transport PIN in the authority's letter.")); context->setLastPaceResult(CardReturnCode::INVALID_CAN); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, six-digit Card Access Number (CAN). Please try again.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect Card Access Number (CAN). Please try again. You can find your CAN in the bottom right on the front of your ID card.")); context->setLastPaceResult(CardReturnCode::INVALID_PUK); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, ten-digit PUK. Please try again.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 10-digit PUK. Please try again.")); context->setLastPaceResult(CardReturnCode::UNKNOWN); QCOMPARE(mModel->getInputError(), tr("An unexpected error has occurred during processing.")); @@ -322,15 +326,16 @@ class test_NumberModel mModel->resetContext(context); context->setCardConnection(connection); context->setLastPaceResult(CardReturnCode::INVALID_PIN); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, five-digit Transport PIN. " - "You have two further attempts to enter the correct Transport PIN.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 5-digit Transport PIN.

      " + "You have 2 further attempts to enter the correct Transport PIN. " + "The 5-digit Transport PIN may be found on the bottom left of your PIN letter.")); context->setLastPaceResult(CardReturnCode::INVALID_PIN_2); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, five-digit Transport PIN twice. " - "For a third attempt, the six-digit Card Access Number (CAN) must be entered first. " - "You can find your CAN in the bottom right on the front of your ID card.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 5-digit Transport PIN 2 times.

      " + "For a 3rd attempt, the 6-digit Card Access Number (CAN) must be entered first. " + "You can find your CAN in the bottom right on the front of your ID card.")); context->setLastPaceResult(CardReturnCode::INVALID_PIN_3); - QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, five-digit Transport PIN thrice, your Transport PIN is now blocked. " - "To remove the block, the ten-digit PUK must be entered first.")); + QCOMPARE(mModel->getInputError(), tr("You have entered an incorrect, 5-digit Transport PIN 3 times, your Transport PIN is now blocked. " + "To remove the block, the 10-digit PUK must be entered first.")); connectionThread.quit(); connectionThread.wait(); @@ -350,7 +355,7 @@ class test_NumberModel QCOMPARE(mModel->getRetryCounter(), -1); const QString name = QStringLiteral("name"); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, true, false); MockReader reader(name); reader.setInfoCardInfo(cardInfo); @@ -368,53 +373,53 @@ class test_NumberModel void test_RequestTransportPin_data() { QTest::addColumn>("context"); - QTest::addColumn("passwordType"); + QTest::addColumn("passwordType"); - QTest::newRow("WorkflowContext") << QSharedPointer(new TestWorkflowContext()) << PasswordType::PIN; - QTest::newRow("ChangePinContext") << QSharedPointer(new ChangePinContext()) << PasswordType::PIN; - QTest::newRow("ChangePinContext-false") << QSharedPointer(new ChangePinContext(false)) << PasswordType::PIN; - QTest::newRow("ChangePinContext-true") << QSharedPointer(new ChangePinContext(true)) << PasswordType::TRANSPORT_PIN; + QTest::newRow("WorkflowContext") << QSharedPointer(new TestWorkflowContext()) << NumberModel::PasswordType::PIN; + QTest::newRow("ChangePinContext") << QSharedPointer(new ChangePinContext()) << NumberModel::PasswordType::PIN; + QTest::newRow("ChangePinContext-false") << QSharedPointer(new ChangePinContext(false)) << NumberModel::PasswordType::PIN; + QTest::newRow("ChangePinContext-true") << QSharedPointer(new ChangePinContext(true)) << NumberModel::PasswordType::TRANSPORT_PIN; } void test_RequestTransportPin() { QFETCH(QSharedPointer, context); - QFETCH(PasswordType, passwordType); + QFETCH(NumberModel::PasswordType, passwordType); - QCOMPARE(mModel->getPasswordType(), PasswordType::PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::PIN); mModel->resetContext(context); QCOMPARE(mModel->getPasswordType(), passwordType); mModel->resetContext(); - QCOMPARE(mModel->getPasswordType(), PasswordType::PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::PIN); } void test_GetPasswordType_ContextIsNullptr() { - QCOMPARE(mModel->getPasswordType(), PasswordType::PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::PIN); } void test_GetPasswordType_data() { QTest::addColumn("passwordId"); - QTest::addColumn("passwordType"); + QTest::addColumn("passwordType"); - QTest::newRow("unknown") << PacePasswordId::UNKNOWN << PasswordType::PIN; - QTest::newRow("mrz") << PacePasswordId::PACE_MRZ << PasswordType::PIN; - QTest::newRow("pin") << PacePasswordId::PACE_PIN << PasswordType::PIN; - QTest::newRow("can") << PacePasswordId::PACE_CAN << PasswordType::CAN; - QTest::newRow("puk") << PacePasswordId::PACE_PUK << PasswordType::PUK; + QTest::newRow("unknown") << PacePasswordId::UNKNOWN << NumberModel::PasswordType::PIN; + QTest::newRow("mrz") << PacePasswordId::PACE_MRZ << NumberModel::PasswordType::PIN; + QTest::newRow("pin") << PacePasswordId::PACE_PIN << NumberModel::PasswordType::PIN; + QTest::newRow("can") << PacePasswordId::PACE_CAN << NumberModel::PasswordType::CAN; + QTest::newRow("puk") << PacePasswordId::PACE_PUK << NumberModel::PasswordType::PUK; } void test_GetPasswordType() { QFETCH(PacePasswordId, passwordId); - QFETCH(PasswordType, passwordType); + QFETCH(NumberModel::PasswordType, passwordType); const QSharedPointer context(new TestWorkflowContext()); @@ -433,16 +438,16 @@ class test_NumberModel mModel->resetContext(context); context->setEstablishPaceChannelType(PacePasswordId::PACE_PIN); - QCOMPARE(mModel->getPasswordType(), PasswordType::PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::PIN); context->setPin(pin); - QCOMPARE(mModel->getPasswordType(), PasswordType::NEW_PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::NEW_PIN); mModel->setNewPin(pin); - QCOMPARE(mModel->getPasswordType(), PasswordType::NEW_PIN_CONFIRMATION); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::NEW_PIN_CONFIRMATION); mModel->setNewPinConfirmation(pin); - QCOMPARE(mModel->getPasswordType(), PasswordType::NEW_PIN_CONFIRMATION); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::NEW_PIN_CONFIRMATION); } @@ -451,14 +456,14 @@ class test_NumberModel #if __has_include("context/PersonalizationContext.h") const QSharedPointer context(new PersonalizationContext(QString())); mModel->resetContext(context); - QCOMPARE(mModel->getPasswordType(), PasswordType::PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::PIN); auto personalizationContext = context.objectCast(); QVERIFY(personalizationContext); personalizationContext->setSessionIdentifier(QUuid::createUuid()); - QCOMPARE(mModel->getPasswordType(), PasswordType::NEW_SMART_PIN); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::NEW_SMART_PIN); mModel->setNewPin(QStringLiteral("123456")); - QCOMPARE(mModel->getPasswordType(), PasswordType::NEW_SMART_PIN_CONFIRMATION); + QCOMPARE(mModel->getPasswordType(), NumberModel::PasswordType::NEW_SMART_PIN_CONFIRMATION); #endif } @@ -490,43 +495,43 @@ class test_NumberModel { QTest::addColumn("inputData"); QTest::addColumn("pinLength"); - QTest::addColumn("passwordType"); + QTest::addColumn("passwordType"); - QTest::newRow("default - 0") << EstablishPaceChannel() << 0 << PasswordType::PIN; - QTest::newRow("default - 5") << EstablishPaceChannel() << 5 << PasswordType::TRANSPORT_PIN; - QTest::newRow("default - 6") << EstablishPaceChannel() << 6 << PasswordType::PIN; + QTest::newRow("default - 0") << EstablishPaceChannel() << 0 << NumberModel::PasswordType::PIN; + QTest::newRow("default - 5") << EstablishPaceChannel() << 5 << NumberModel::PasswordType::TRANSPORT_PIN; + QTest::newRow("default - 6") << EstablishPaceChannel() << 6 << NumberModel::PasswordType::PIN; - QTest::newRow("pin - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 0 << PasswordType::PIN; - QTest::newRow("pin - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 5 << PasswordType::TRANSPORT_PIN; - QTest::newRow("pin - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 6 << PasswordType::PIN; + QTest::newRow("pin - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 0 << NumberModel::PasswordType::PIN; + QTest::newRow("pin - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 5 << NumberModel::PasswordType::TRANSPORT_PIN; + QTest::newRow("pin - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_PIN) << 6 << NumberModel::PasswordType::PIN; - QTest::newRow("can - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 0 << PasswordType::CAN; - QTest::newRow("can - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 5 << PasswordType::CAN; - QTest::newRow("can - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 6 << PasswordType::CAN; + QTest::newRow("can - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 0 << NumberModel::PasswordType::CAN; + QTest::newRow("can - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 5 << NumberModel::PasswordType::CAN; + QTest::newRow("can - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_CAN) << 6 << NumberModel::PasswordType::CAN; - QTest::newRow("puk - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 0 << PasswordType::PUK; - QTest::newRow("puk - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 5 << PasswordType::PUK; - QTest::newRow("puk - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 6 << PasswordType::PUK; + QTest::newRow("puk - no cert - 0") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 0 << NumberModel::PasswordType::PUK; + QTest::newRow("puk - no cert - 5") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 5 << NumberModel::PasswordType::PUK; + QTest::newRow("puk - no cert - 6") << EstablishPaceChannel(PacePasswordId::PACE_PUK) << 6 << NumberModel::PasswordType::PUK; - QTest::newRow("unknown - no cert - 0") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 0 << PasswordType::PIN; - QTest::newRow("unknown - no cert - 5") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 5 << PasswordType::TRANSPORT_PIN; - QTest::newRow("unknown - no cert - 6") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 6 << PasswordType::PIN; + QTest::newRow("unknown - no cert - 0") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 0 << NumberModel::PasswordType::PIN; + QTest::newRow("unknown - no cert - 5") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 5 << NumberModel::PasswordType::TRANSPORT_PIN; + QTest::newRow("unknown - no cert - 6") << EstablishPaceChannel(PacePasswordId::UNKNOWN) << 6 << NumberModel::PasswordType::PIN; - QTest::newRow("pin - cert - 0") << createDataToParse(PacePasswordId::PACE_PIN) << 0 << PasswordType::PIN; - QTest::newRow("pin - cert - 5") << createDataToParse(PacePasswordId::PACE_PIN) << 5 << PasswordType::TRANSPORT_PIN; - QTest::newRow("pin - cert - 6") << createDataToParse(PacePasswordId::PACE_PIN) << 6 << PasswordType::PIN; + QTest::newRow("pin - cert - 0") << createDataToParse(PacePasswordId::PACE_PIN) << 0 << NumberModel::PasswordType::PIN; + QTest::newRow("pin - cert - 5") << createDataToParse(PacePasswordId::PACE_PIN) << 5 << NumberModel::PasswordType::TRANSPORT_PIN; + QTest::newRow("pin - cert - 6") << createDataToParse(PacePasswordId::PACE_PIN) << 6 << NumberModel::PasswordType::PIN; - QTest::newRow("can - cert - 0") << createDataToParse(PacePasswordId::PACE_CAN) << 0 << PasswordType::CAN; - QTest::newRow("can - cert - 5") << createDataToParse(PacePasswordId::PACE_CAN) << 5 << PasswordType::CAN; - QTest::newRow("can - cert - 6") << createDataToParse(PacePasswordId::PACE_CAN) << 6 << PasswordType::CAN; + QTest::newRow("can - cert - 0") << createDataToParse(PacePasswordId::PACE_CAN) << 0 << NumberModel::PasswordType::CAN; + QTest::newRow("can - cert - 5") << createDataToParse(PacePasswordId::PACE_CAN) << 5 << NumberModel::PasswordType::CAN; + QTest::newRow("can - cert - 6") << createDataToParse(PacePasswordId::PACE_CAN) << 6 << NumberModel::PasswordType::CAN; - QTest::newRow("puk - cert - 0") << createDataToParse(PacePasswordId::PACE_PUK) << 0 << PasswordType::PUK; - QTest::newRow("puk - cert - 5") << createDataToParse(PacePasswordId::PACE_PUK) << 5 << PasswordType::PUK; - QTest::newRow("puk - cert - 6") << createDataToParse(PacePasswordId::PACE_PUK) << 6 << PasswordType::PUK; + QTest::newRow("puk - cert - 0") << createDataToParse(PacePasswordId::PACE_PUK) << 0 << NumberModel::PasswordType::PUK; + QTest::newRow("puk - cert - 5") << createDataToParse(PacePasswordId::PACE_PUK) << 5 << NumberModel::PasswordType::PUK; + QTest::newRow("puk - cert - 6") << createDataToParse(PacePasswordId::PACE_PUK) << 6 << NumberModel::PasswordType::PUK; - QTest::newRow("unknown - cert - 0") << createDataToParse(PacePasswordId::UNKNOWN) << 0 << PasswordType::PIN; - QTest::newRow("unknown - cert - 5") << createDataToParse(PacePasswordId::UNKNOWN) << 5 << PasswordType::TRANSPORT_PIN; - QTest::newRow("unknown - cert - 6") << createDataToParse(PacePasswordId::UNKNOWN) << 6 << PasswordType::PIN; + QTest::newRow("unknown - cert - 0") << createDataToParse(PacePasswordId::UNKNOWN) << 0 << NumberModel::PasswordType::PIN; + QTest::newRow("unknown - cert - 5") << createDataToParse(PacePasswordId::UNKNOWN) << 5 << NumberModel::PasswordType::TRANSPORT_PIN; + QTest::newRow("unknown - cert - 6") << createDataToParse(PacePasswordId::UNKNOWN) << 6 << NumberModel::PasswordType::PIN; } @@ -534,7 +539,7 @@ class test_NumberModel { QFETCH(EstablishPaceChannel, inputData); QFETCH(int, pinLength); - QFETCH(PasswordType, passwordType); + QFETCH(NumberModel::PasswordType, passwordType); const QSharedPointer context(new IfdServiceContext(QSharedPointer(new RemoteIfdServer()))); mModel->resetContext(context); @@ -546,6 +551,57 @@ class test_NumberModel } + void test_resetInputError() + { + QThread connectionThread; + connectionThread.start(); + QSharedPointer context(new TestWorkflowContext()); + const QSharedPointer worker(new MockCardConnectionWorker()); + worker->moveToThread(&connectionThread); + const QSharedPointer connection(new CardConnection(worker)); + context->setCardConnection(connection); + + mModel->resetContext(context); + context->setLastPaceResult(CardReturnCode::OK); + QVERIFY(mModel->getInputError().isEmpty()); + + context->setPin(QStringLiteral("000000")); + context->setLastPaceResult(CardReturnCode::INVALID_PIN); + QVERIFY(!mModel->getPin().isEmpty()); + QVERIFY(!mModel->getInputError().isEmpty()); + + mModel->resetInputError(); + QVERIFY(!mModel->getPin().isEmpty()); + QVERIFY(mModel->getInputError().isEmpty()); + + connectionThread.quit(); + connectionThread.wait(); + } + + + void test_setInitialInputErrorShown() + { + QSharedPointer context(new TestWorkflowContext()); + + mModel->resetContext(context); + context->setLastPaceResult(CardReturnCode::OK); + context->setEstablishPaceChannelType(PacePasswordId::PACE_PIN); + QVERIFY(mModel->getInitialInputError().isEmpty()); + context->setEstablishPaceChannelType(PacePasswordId::PACE_CAN); + QVERIFY(!mModel->getInitialInputError().isEmpty()); + context->setEstablishPaceChannelType(PacePasswordId::PACE_PUK); + QVERIFY(!mModel->getInitialInputError().isEmpty()); + + context->setInitialInputErrorShown(); + context->setEstablishPaceChannelType(PacePasswordId::PACE_PIN); + QVERIFY(mModel->getInitialInputError().isEmpty()); + context->setEstablishPaceChannelType(PacePasswordId::PACE_CAN); + QVERIFY(mModel->getInitialInputError().isEmpty()); + context->setEstablishPaceChannelType(PacePasswordId::PACE_PUK); + QVERIFY(mModel->getInitialInputError().isEmpty()); + } + + }; QTEST_MAIN(test_NumberModel) diff --git a/test/qt/ui/qml/test_PinResetInformationModel.cpp b/test/qt/ui/qml/test_PinResetInformationModel.cpp index 573ab1753..3865157cc 100644 --- a/test/qt/ui/qml/test_PinResetInformationModel.cpp +++ b/test/qt/ui/qml/test_PinResetInformationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/ui/qml/test_ProxyCredentials.cpp b/test/qt/ui/qml/test_ProxyCredentials.cpp index dd13561d3..be7766cfc 100644 --- a/test/qt/ui/qml/test_ProxyCredentials.cpp +++ b/test/qt/ui/qml/test_ProxyCredentials.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,12 +8,11 @@ #include "ProxyCredentials.h" - #include #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -45,7 +44,7 @@ class test_ProxyCredentials QFETCH(QNetworkProxy::ProxyType, type); QFETCH(QString, url); - QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com", 1337, "Test"); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com"_L1, 1337, "Test"_L1); proxy.setType(type); QAuthenticator authenticator; @@ -56,19 +55,19 @@ class test_ProxyCredentials void test_Credentials() { - QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com", 1337, "Test"); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com"_L1, 1337, "Test"_L1); QAuthenticator authenticator; ProxyCredentials proxyCredentials(proxy, &authenticator); - QCOMPARE(proxyCredentials.getProposedUser(), "Test"); + QCOMPARE(proxyCredentials.getProposedUser(), "Test"_L1); - QCOMPARE(proxyCredentials.getUser(), ""); - proxyCredentials.setUser("TestUser"); - QCOMPARE(proxyCredentials.getUser(), "TestUser"); + QCOMPARE(proxyCredentials.getUser(), ""_L1); + proxyCredentials.setUser("TestUser"_L1); + QCOMPARE(proxyCredentials.getUser(), "TestUser"_L1); - QCOMPARE(proxyCredentials.getPassword(), ""); - proxyCredentials.setPassword("TestPassword"); - QCOMPARE(proxyCredentials.getPassword(), "TestPassword"); + QCOMPARE(proxyCredentials.getPassword(), ""_L1); + proxyCredentials.setPassword("TestPassword"_L1); + QCOMPARE(proxyCredentials.getPassword(), "TestPassword"_L1); } @@ -77,7 +76,7 @@ class test_ProxyCredentials const int waitFor = 500; const int tolerance = 10; - QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com", 1337, "Test"); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "proxy.example.com"_L1, 1337, "Test"_L1); QAuthenticator authenticator; ProxyCredentials proxyCredentials(proxy, &authenticator); diff --git a/test/qt/ui/qml/test_QmlFileStructure.cpp b/test/qt/ui/qml/test_QmlFileStructure.cpp index ea39fd3ec..44e8642b8 100644 --- a/test/qt/ui/qml/test_QmlFileStructure.cpp +++ b/test/qt/ui/qml/test_QmlFileStructure.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "ResourceLoader.h" @@ -8,6 +8,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_QmlFileStructure @@ -26,11 +27,7 @@ class test_QmlFileStructure QDirIterator iterator(QStringLiteral(":"), {QStringLiteral("*.qml")}, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (iterator.hasNext()) { - const auto& file = iterator.next(); - if (!file.endsWith(QStringLiteral("main.qml"))) - { - mQmlFiles += file; - } + mQmlFiles << iterator.next(); } } @@ -52,7 +49,7 @@ class test_QmlFileStructure QFETCH(QFileInfo, qmlFile); QDir dir = qmlFile.dir(); - while (dir.dirName().startsWith(QLatin1Char('+'))) + while (dir.dirName().startsWith('+'_L1)) { dir.cdUp(); const QString fileInParentFolder = dir.path() + QDir::separator() + qmlFile.fileName(); diff --git a/test/qt/ui/qml/test_ReaderModel.cpp b/test/qt/ui/qml/test_ReaderModel.cpp index ffa514e3f..d683cbd70 100644 --- a/test/qt/ui/qml/test_ReaderModel.cpp +++ b/test/qt/ui/qml/test_ReaderModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2017-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderModel.h" @@ -12,7 +12,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -22,27 +22,46 @@ class MockReaderManager Q_OBJECT private: - const QVector& mReaderInfos; + const QList& mReaderInfos; + bool mIsScanRunning; public: - MockReaderManager(const QVector& pReaderInfos); - QVector getReaderInfos(const ReaderFilter& pFilter = ReaderFilter()) const override; + MockReaderManager(const QList& pReaderInfos); + ReaderManagerPluginInfo getPluginInfo(ReaderManagerPluginType pType) const override; + QList getReaderInfos(const ReaderFilter& pFilter = ReaderFilter()) const override; + + void setIsScanRunning(bool pRunning); }; -MockReaderManager::MockReaderManager(const QVector& pReaderInfos) : - mReaderInfos(pReaderInfos) +MockReaderManager::MockReaderManager(const QList& pReaderInfos) + : mReaderInfos(pReaderInfos) + , mIsScanRunning(false) +{ +} + + +ReaderManagerPluginInfo MockReaderManager::getPluginInfo(ReaderManagerPluginType pType) const { + ReaderManagerPluginInfo info(pType); + info.setScanRunning(mIsScanRunning); + return info; } -QVector MockReaderManager::getReaderInfos(const ReaderFilter& pFilter) const +QList MockReaderManager::getReaderInfos(const ReaderFilter& pFilter) const { Q_UNUSED(pFilter) return mReaderInfos; } +void MockReaderManager::setIsScanRunning(bool pRunning) +{ + mIsScanRunning = pRunning; +} + + class test_ReaderModel : public QObject { @@ -63,10 +82,10 @@ class test_ReaderModel private: QScopedPointer mMockReaderConfiguration; - QVector mUsbIds; + QList mUsbIds; MockReaderDetector mMockReaderDetector; - QVector mReaderInfos; + QList mReaderInfos; MockReaderManager mMockReaderManager; private Q_SLOTS: @@ -101,14 +120,14 @@ class test_ReaderModel } - void test_01_settings() + void test_settings() { ReaderModel readerModel; QCOMPARE(readerModel.rowCount(), 0); } - void test_02_usbId() + void test_usbId() { #if defined(Q_OS_FREEBSD) QSKIP("No driver available for UsbId(0x0C4B, 0x0501) on FreeBSD"); @@ -124,7 +143,7 @@ class test_ReaderModel } - void test_03_usbId_unknown() + void test_usbId_unknown() { mUsbIds += UsbId(0x1, 0x2); // Unknown @@ -133,29 +152,36 @@ class test_ReaderModel } - void test_04_usbId_readerManager_equal() + void test_usbId_readerManager_different_scan_not_running() { #if defined(Q_OS_FREEBSD) QSKIP("No driver available for UsbId(0x04E6, 0x5790) on FreeBSD"); #endif + mUsbIds += UsbId(0x0C4B, 0x0501); // REINER SCT cyberJack RFID komfort mUsbIds += UsbId(0x04E6, 0x5790); // Identiv Cloud 3700 F - mReaderInfos += ReaderInfo("Identiv CLOUD 3700 F Contactless Reader 0", ReaderManagerPlugInType::PCSC); + mReaderInfos += ReaderInfo("Identiv CLOUD 3700 F Contactless Reader 0"_L1, ReaderManagerPluginType::PCSC); + QModelIndex index; ReaderModel readerModel; - QCOMPARE(readerModel.rowCount(), 1); - const auto& index = readerModel.index(0, 0, QModelIndex()); - QCOMPARE(readerModel.data(index, ReaderModel::UserRoles::READER_HTML_DESCRIPTION).toString(), tr("Driver installed")); + QCOMPARE(readerModel.rowCount(), 2); + index = readerModel.index(0, 0, QModelIndex()); + QCOMPARE(readerModel.data(index, ReaderModel::UserRoles::READER_HTML_DESCRIPTION).toString(), tr("The smartcard service of your system is not reachable.")); + index = readerModel.index(1, 0, QModelIndex()); + const auto& htmlDescription = readerModel.data(index, ReaderModel::UserRoles::READER_HTML_DESCRIPTION).toString(); + QVERIFY(htmlDescription.startsWith(tr("The smartcard service of your system is not reachable."))); } - void test_05_usbId_readerManager_different() + void test_usbId_readerManager_different_scan_running() { #if defined(Q_OS_FREEBSD) QSKIP("No driver available for UsbId(0x04E6, 0x5790) on FreeBSD"); #endif mUsbIds += UsbId(0x0C4B, 0x0501); // REINER SCT cyberJack RFID komfort mUsbIds += UsbId(0x04E6, 0x5790); // Identiv Cloud 3700 F - mReaderInfos += ReaderInfo("Identiv CLOUD 3700 F Contactless Reader 0", ReaderManagerPlugInType::PCSC); + mReaderInfos += ReaderInfo("Identiv CLOUD 3700 F Contactless Reader 0"_L1, ReaderManagerPluginType::PCSC); + + mMockReaderManager.setIsScanRunning(true); QModelIndex index; ReaderModel readerModel; @@ -164,20 +190,21 @@ class test_ReaderModel QCOMPARE(readerModel.data(index, ReaderModel::UserRoles::READER_HTML_DESCRIPTION).toString(), tr("Driver installed")); index = readerModel.index(1, 0, QModelIndex()); const auto& htmlDescription = readerModel.data(index, ReaderModel::UserRoles::READER_HTML_DESCRIPTION).toString(); - QVERIFY(htmlDescription.startsWith(tr("The smartcard service of your system is not reachable."))); + QVERIFY(htmlDescription.startsWith(tr("No driver installed"))); + } - void test_06_settings_readerManager_unknown() + void test_settings_readerManager_unknown() { - mReaderInfos += ReaderInfo("Governikus Special Reader", ReaderManagerPlugInType::PCSC); + mReaderInfos += ReaderInfo("Governikus Special Reader"_L1, ReaderManagerPluginType::PCSC); ReaderModel readerModel; QCOMPARE(readerModel.rowCount(), 1); } - void test_07_translation() + void test_translation() { ReaderModel readerModel; QSignalSpy spy(&readerModel, &ReaderModel::fireModelChanged); diff --git a/test/qt/ui/qml/test_ReaderScanEnabler.cpp b/test/qt/ui/qml/test_ReaderScanEnabler.cpp index 01ee1a08e..fbf578301 100644 --- a/test/qt/ui/qml/test_ReaderScanEnabler.cpp +++ b/test/qt/ui/qml/test_ReaderScanEnabler.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "ReaderScanEnabler.h" #include "ApplicationModel.h" #include "Env.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "context/ChangePinContext.h" @@ -14,7 +14,7 @@ #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) using namespace governikus; @@ -31,17 +31,17 @@ class test_ReaderScanEnabler private Q_SLOTS: void init() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations mParent.reset(new QQuickItem()); - auto& mockPlugin = MockReaderManagerPlugIn::getInstance(); + auto& mockPlugin = MockReaderManagerPlugin::getInstance(); mockPlugin.addReader(); mEnabler = new ReaderScanEnabler(mParent.data()); - mEnabler->setPlugInType(mockPlugin.getInfo().getPlugInType()); + mEnabler->setPluginType(mockPlugin.getInfo().getPluginType()); mEnabler->setVisible(false); QCoreApplication::processEvents(); // Make sure to process things from itemChange } @@ -56,24 +56,24 @@ class test_ReaderScanEnabler void test_enableScan() { QSignalSpy scanRunningChanged(mEnabler.data(), &ReaderScanEnabler::fireScanRunningChanged); - const auto& pluginType = mEnabler->getPlugInType(); + const auto& pluginType = mEnabler->getPluginType(); const auto* readerManager = Env::getSingleton(); - QCOMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), false); + QCOMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), false); mEnabler->enableScan(true); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), true); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), true); QTRY_COMPARE(scanRunningChanged.size(), 1); mEnabler->enableScan(true); // Call a second time to ensure the state does not change - QCOMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), true); + QCOMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), true); QTRY_COMPARE(scanRunningChanged.size(), 1); mEnabler->enableScan(false); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), false); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), false); QTRY_COMPARE(scanRunningChanged.size(), 2); mEnabler->enableScan(false); // Call a second time to ensure the state does not change - QCOMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), false); + QCOMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), false); QTRY_COMPARE(scanRunningChanged.size(), 2); } @@ -90,7 +90,7 @@ class test_ReaderScanEnabler void test_visibilityChange() { - const auto& pluginType = mEnabler->getPlugInType(); + const auto& pluginType = mEnabler->getPluginType(); auto* readerManager = Env::getSingleton(); QFETCH(bool, initialScanState); @@ -99,13 +99,13 @@ class test_ReaderScanEnabler initialScanState ? readerManager->startScan(pluginType) : readerManager->stopScan(pluginType); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), initialScanState); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), initialScanState); mEnabler->setVisible(true); QVERIFY(mEnabler->isVisible()); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), true); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), true); mEnabler->setVisible(false); QVERIFY(!mEnabler->isVisible()); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), finalScanState); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), finalScanState); } @@ -121,20 +121,20 @@ class test_ReaderScanEnabler void test_restartScan() { - const auto& pluginType = mEnabler->getPlugInType(); + const auto& pluginType = mEnabler->getPluginType(); const auto* readerManager = Env::getSingleton(); QFETCH(QSharedPointer, workflowContext); QFETCH(bool, finalScanState); Env::getSingleton()->resetContext(workflowContext); - QCOMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), false); + QCOMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), false); mEnabler->setVisible(true); QVERIFY(mEnabler->isVisible()); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), true); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), true); mEnabler->setVisible(false); QVERIFY(!mEnabler->isVisible()); - QTRY_COMPARE(readerManager->getPlugInInfo(pluginType).isScanRunning(), finalScanState); + QTRY_COMPARE(readerManager->getPluginInfo(pluginType).isScanRunning(), finalScanState); } diff --git a/test/qt/ui/qml/test_ReleaseInformationModel.cpp b/test/qt/ui/qml/test_ReleaseInformationModel.cpp index 789706932..646d9f6f8 100644 --- a/test/qt/ui/qml/test_ReleaseInformationModel.cpp +++ b/test/qt/ui/qml/test_ReleaseInformationModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2020-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,6 +15,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_ReleaseInformationModel @@ -31,7 +32,7 @@ class test_ReleaseInformationModel void initTestCase() { Env::setCreator(std::function([] { - return new MockReleaseInformation(VersionNumber("1.2.3"), false); + return new MockReleaseInformation(VersionNumber("1.2.3"_L1), false); })); Env::setCreator(std::function([](const VersionNumber& pVersion, bool pConsiderOnlyThisVersion){ return new MockReleaseInformation(pVersion, pConsiderOnlyThisVersion); @@ -92,7 +93,7 @@ class test_ReleaseInformationModel { QCOMPARE(mModel->getUpdateRelease()->rowCount(), 1); - mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4")); + mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4"_L1)); QCOMPARE(mSpyUpdateInformationChanged->count(), 1); QCOMPARE(mModel->getUpdateRelease()->rowCount(), 11); @@ -105,7 +106,7 @@ class test_ReleaseInformationModel QCOMPARE(mSpyCurrentInformationChanged->count(), 1); - mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4")); + mReleaseInfoConfig->setUpdateVersion(VersionNumber("1.2.4"_L1)); QCOMPARE(mSpyUpdateInformationChanged->count(), 1); diff --git a/test/qt/ui/qml/test_RemoteDeviceFilterModel.cpp b/test/qt/ui/qml/test_RemoteDeviceFilterModel.cpp index 4d505f3e5..87e8fab79 100644 --- a/test/qt/ui/qml/test_RemoteDeviceFilterModel.cpp +++ b/test/qt/ui/qml/test_RemoteDeviceFilterModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,7 +12,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -29,9 +29,9 @@ class test_RemoteDeviceFilterModel QSharedPointer filterModelUnavail = QSharedPointer::create(sourceModel.data(), RemoteDeviceFilterModel::showUnavailableAndPaired); QSharedPointer filterModelAvailPair = QSharedPointer::create(sourceModel.data(), RemoteDeviceFilterModel::showActivePairingMode); - const RemoteDeviceModelEntry availableEntry(QString("reader 1"), QString("test id"), true, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); - const RemoteDeviceModelEntry unavailableEntry(QString("reader 2"), QString("test id"), false, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); - const RemoteDeviceModelEntry availablePairingEntry(QString("reader 2"), QString("test id"), true, false, true, true, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); + const RemoteDeviceModelEntry availableEntry("reader 1"_L1, "test id"_L1, true, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); + const RemoteDeviceModelEntry unavailableEntry("reader 2"_L1, "test id"_L1, false, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); + const RemoteDeviceModelEntry availablePairingEntry("reader 2"_L1, "test id"_L1, true, false, true, true, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), nullptr); sourceModel->mAllRemoteReaders.insert(0, availableEntry); sourceModel->mAllRemoteReaders.insert(1, unavailableEntry); diff --git a/test/qt/ui/qml/test_RemoteDeviceModel.cpp b/test/qt/ui/qml/test_RemoteDeviceModel.cpp index 0c806363b..58e7bf07e 100644 --- a/test/qt/ui/qml/test_RemoteDeviceModel.cpp +++ b/test/qt/ui/qml/test_RemoteDeviceModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "AppSettings.h" @@ -8,10 +8,31 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(RemoteDeviceModel::SettingsRemoteRoles) +class MockRemoteDeviceModel + : public RemoteDeviceModel +{ + [[nodiscard]] QList presentReaders() const override; +}; + +QList MockRemoteDeviceModel::presentReaders() const +{ + const auto dName = QStringLiteral("new_name"); + const auto dId = QStringLiteral("myDeviceId"); + const auto disco = Discovery(dName, dId, 12345, {IfdVersion::Version::latest}, false); + const auto ifdDesc = IfdDescriptor(disco, QHostAddress(QStringLiteral("127.0.0.1"))); + const QSharedPointer remoteDeviceListEntry(new IfdListEntry(ifdDesc)); + remoteDeviceListEntry->setIfdDescriptor(ifdDesc); + return QList { + RemoteDeviceModelEntry {remoteDeviceListEntry} + }; +} + + class test_RemoteDeviceModel : public QObject { @@ -157,28 +178,28 @@ class test_RemoteDeviceModel { RemoteDeviceModelEntry entry; - QCOMPARE(mModel->getStatus(entry), QString("Not connected")); + QCOMPARE(mModel->getStatus(entry), "Not connected"_L1); mModel->mAllRemoteReaders.insert(0, entry); - QCOMPARE(mModel->getStatus(entry), QString("Unsupported")); + QCOMPARE(mModel->getStatus(entry), "Unsupported"_L1); entry.mSupported = true; - QCOMPARE(mModel->getStatus(entry), QString("Not paired")); + QCOMPARE(mModel->getStatus(entry), "Not paired"_L1); entry.setPaired(true); - QCOMPARE(mModel->getStatus(entry), QString("Unavailable")); + QCOMPARE(mModel->getStatus(entry), "Unavailable"_L1); entry.setNetworkVisible(true); - QCOMPARE(mModel->getStatus(entry), QString("Available")); + QCOMPARE(mModel->getStatus(entry), "Available"_L1); entry.mSupported = false; - QCOMPARE(mModel->getStatus(entry), QString("Paired, but unsupported")); + QCOMPARE(mModel->getStatus(entry), "Paired, but unsupported"_L1); entry.setNetworkVisible(true); entry.mSupported = true; entry.mIsPairing = true; - QCOMPARE(mModel->getStatus(entry), QString("Click to pair")); + QCOMPARE(mModel->getStatus(entry), "Click to pair"_L1); } @@ -186,14 +207,14 @@ class test_RemoteDeviceModel { RemoteDeviceModelEntry entry1; RemoteDeviceModelEntry entry2; - entry1.setId(QString("id")); + entry1.setId("id"_L1); - QCOMPARE(mModel->getRemoteDeviceListEntry(QString("id")), QSharedPointer()); + QCOMPARE(mModel->getRemoteDeviceListEntry("id"_L1), QSharedPointer()); mModel->mAllRemoteReaders.insert(0, entry1); mModel->mAllRemoteReaders.insert(1, entry2); - QCOMPARE(mModel->getRemoteDeviceListEntry(QString("id")), nullptr); + QCOMPARE(mModel->getRemoteDeviceListEntry("id"_L1), nullptr); } @@ -204,7 +225,7 @@ class test_RemoteDeviceModel QSharedPointer listEntry(new IfdListEntry(descriptor)); RemoteDeviceModelEntry entry1(listEntry); - RemoteDeviceModelEntry entry2(QString("entry 2")); + RemoteDeviceModelEntry entry2("entry 2"_L1); mModel->mAllRemoteReaders << entry1 << entry2; const auto& index1 = mModel->createIndex(0, 0); @@ -222,10 +243,10 @@ class test_RemoteDeviceModel QTest::addColumn("column"); QTest::addColumn("output"); - QTest::newRow("device name") << RemoteDeviceModel::SettingsRemoteRoles::REMOTE_DEVICE_NAME << 0 << 0 << QVariant(QString("reader 1")); - QTest::newRow("device status") << RemoteDeviceModel::SettingsRemoteRoles::REMOTE_DEVICE_STATUS << 1 << 0 << QVariant(QString("Unsupported")); - QTest::newRow("last connected") << RemoteDeviceModel::SettingsRemoteRoles::LAST_CONNECTED << 0 << 0 << QVariant(QString("14.05.2019 12:00 AM")); - QTest::newRow("device id") << RemoteDeviceModel::SettingsRemoteRoles::DEVICE_ID << 0 << 0 << QVariant(QString("test id")); + QTest::newRow("device name") << RemoteDeviceModel::SettingsRemoteRoles::REMOTE_DEVICE_NAME << 0 << 0 << QVariant("reader 1"_L1); + QTest::newRow("device status") << RemoteDeviceModel::SettingsRemoteRoles::REMOTE_DEVICE_STATUS << 1 << 0 << QVariant("Unsupported"_L1); + QTest::newRow("last connected") << RemoteDeviceModel::SettingsRemoteRoles::LAST_CONNECTED << 0 << 0 << QVariant("14.05.2019 12:00 AM"_L1); + QTest::newRow("device id") << RemoteDeviceModel::SettingsRemoteRoles::DEVICE_ID << 0 << 0 << QVariant("test id"_L1); QTest::newRow("network visible") << RemoteDeviceModel::SettingsRemoteRoles::IS_NETWORK_VISIBLE << 1 << 0 << QVariant(bool(false)); QTest::newRow("supported") << RemoteDeviceModel::SettingsRemoteRoles::IS_SUPPORTED << 0 << 0 << QVariant(bool(true)); QTest::newRow("paired") << RemoteDeviceModel::SettingsRemoteRoles::IS_PAIRED << 0 << 0 << QVariant(bool(true)); @@ -242,10 +263,10 @@ class test_RemoteDeviceModel QFETCH(int, column); QFETCH(QVariant, output); - QVector readers; + QList readers; QSharedPointer listEntry(new IfdListEntry(IfdDescriptor())); - const RemoteDeviceModelEntry entry1(QString("reader 1"), QString("test id"), true, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), listEntry); - const RemoteDeviceModelEntry entry2(QString("reader 2")); + const RemoteDeviceModelEntry entry1("reader 1"_L1, "test id"_L1, true, false, true, false, QDateTime(QDate(2019, 5, 14), QTime(0, 0)), listEntry); + const RemoteDeviceModelEntry entry2("reader 2"_L1); readers << entry1 << entry2; mModel->mAllRemoteReaders = readers; const auto& index = mModel->createIndex(row, column); @@ -275,6 +296,32 @@ class test_RemoteDeviceModel } + void test_ChangedName() + { + MockRemoteDeviceModel model; + + RemoteServiceSettings& settings = Env::getSingleton()->getRemoteServiceSettings(); + settings.addTrustedCertificate(QSslCertificate()); + + const auto dName = QStringLiteral("old_name"); + const auto dId = QStringLiteral("myDeviceId"); + const auto disco = Discovery(dName, dId, 12345, {IfdVersion::Version::latest}, false); + const auto ifdDesc = IfdDescriptor(disco, QHostAddress(QStringLiteral("127.0.0.1"))); + const QSharedPointer remoteDeviceListEntry(new IfdListEntry(ifdDesc)); + + model.mAllRemoteReaders.clear(); + model.addOrUpdateReader(RemoteDeviceModelEntry(remoteDeviceListEntry)); + + const auto newName = QStringLiteral("new_name"); + const auto newDisco = Discovery(newName, dId, 12345, {IfdVersion::Version::latest}, false); + const auto newIfdDesc = IfdDescriptor(newDisco, QHostAddress(QStringLiteral("127.0.0.1"))); + remoteDeviceListEntry->setIfdDescriptor(newIfdDesc); + + const auto name = model.data(mModel->index(0), RemoteDeviceModel::SettingsRemoteRoles::REMOTE_DEVICE_NAME).toString(); + QCOMPARE(name, QStringLiteral("new_name (was old_name)")); + } + + }; QTEST_MAIN(test_RemoteDeviceModel) diff --git a/test/qt/ui/qml/test_RemoteServiceModel.cpp b/test/qt/ui/qml/test_RemoteServiceModel.cpp index f06ab49b2..a85968787 100644 --- a/test/qt/ui/qml/test_RemoteServiceModel.cpp +++ b/test/qt/ui/qml/test_RemoteServiceModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,7 +15,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(EstablishPaceChannel) @@ -49,31 +49,31 @@ class test_RemoteServiceModel } - void test_ReaderPlugInType() + void test_ReaderPluginType() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations - const ReaderManagerPlugInType input1 = ReaderManagerPlugInType::NFC; - const ReaderManagerPlugInType input2 = ReaderManagerPlugInType::UNKNOWN; + const ReaderManagerPluginType input1 = ReaderManagerPluginType::NFC; + const ReaderManagerPluginType input2 = ReaderManagerPluginType::UNKNOWN; - mModel->setReaderPlugInType(input1); - QCOMPARE(mModel->getReaderPlugInType(), ReaderManagerPlugInType::UNKNOWN); + mModel->setReaderPluginType(input1); + QCOMPARE(mModel->getReaderPluginType(), ReaderManagerPluginType::UNKNOWN); mModel->resetRemoteServiceContext(mContext); - mModel->setReaderPlugInType(input1); - QCOMPARE(mModel->getReaderPlugInType(), input1); + mModel->setReaderPluginType(input1); + QCOMPARE(mModel->getReaderPluginType(), input1); - mModel->setReaderPlugInType(input2); - QCOMPARE(mModel->getReaderPlugInType(), ReaderManagerPlugInType::UNKNOWN); + mModel->setReaderPluginType(input2); + QCOMPARE(mModel->getReaderPluginType(), ReaderManagerPluginType::UNKNOWN); } void test_CancelPasswordRequest() { - QSignalSpy spy(mContext.data(), &IfdServiceContext::fireCancelPasswordRequest); + QSignalSpy spy(mContext.data(), &IfdServiceContext::fireUserError); mModel->cancelPasswordRequest(); QCOMPARE(spy.count(), 0); @@ -81,6 +81,21 @@ class test_RemoteServiceModel mModel->resetRemoteServiceContext(mContext); mModel->cancelPasswordRequest(); QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).value(), StatusCode::INPUT_CANCELLED); + } + + + void test_PasswordsDiffer() + { + QSignalSpy spy(mContext.data(), &IfdServiceContext::fireUserError); + + mModel->passwordsDiffer(); + QCOMPARE(spy.count(), 0); + + mModel->resetRemoteServiceContext(mContext); + mModel->passwordsDiffer(); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).value(), StatusCode::PASSWORDS_DIFFER); } @@ -152,13 +167,13 @@ class test_RemoteServiceModel } - void test_getSupportedReaderPlugInTypes() + void test_getSupportedReaderPluginTypes() { - QVector supportedPlugIns {ReaderManagerPlugInType::NFC}; + QList supportedPlugins {ReaderManagerPluginType::NFC}; #if __has_include("SmartManager.h") - supportedPlugIns << ReaderManagerPlugInType::SMART; + supportedPlugins << ReaderManagerPluginType::SMART; #endif - QCOMPARE(mModel->getSupportedReaderPlugInTypes(), supportedPlugIns); + QCOMPARE(mModel->getSupportedReaderPluginTypes(), supportedPlugins); } @@ -208,8 +223,9 @@ class test_RemoteServiceModel QSignalSpy spyDisplayTextChanged(mModel, &RemoteServiceModel::fireDisplayTextChanged); mModel->resetRemoteServiceContext(mContext); - mContext->setDisplayText(inputText); QCOMPARE(spyDisplayTextChanged.count(), 1); + mContext->setDisplayText(inputText); + QCOMPARE(spyDisplayTextChanged.count(), 2); QCOMPARE(mModel->getDisplayText(), outputText); QCOMPARE(mModel->getPercentage(), expectedPercentage); } @@ -219,15 +235,15 @@ class test_RemoteServiceModel { QSignalSpy spyDisplayTextChanged(mModel, &RemoteServiceModel::fireDisplayTextChanged); - QCOMPARE(mModel->getDisplayText(), ""); + QCOMPARE(mModel->getDisplayText(), ""_L1); QCOMPARE(mModel->getPercentage(), 0); mModel->resetRemoteServiceContext(mContext); - QCOMPARE(spyDisplayTextChanged.count(), 0); - mContext->setDisplayText("Dummy"); - QCOMPARE(spyDisplayTextChanged.count(), 1); - mContext->setDisplayText("Dummy"); QCOMPARE(spyDisplayTextChanged.count(), 1); + mContext->setDisplayText("Dummy"_L1); + QCOMPARE(spyDisplayTextChanged.count(), 2); + mContext->setDisplayText("Dummy"_L1); + QCOMPARE(spyDisplayTextChanged.count(), 2); } diff --git a/test/qt/ui/qml/test_SelfAuthModel.cpp b/test/qt/ui/qml/test_SelfAuthModel.cpp index fb00dc3a6..8bddccca9 100644 --- a/test/qt/ui/qml/test_SelfAuthModel.cpp +++ b/test/qt/ui/qml/test_SelfAuthModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_SelfAuthModel @@ -103,7 +104,7 @@ class test_SelfAuthModel void test_OnSelfAuthenticationDataChanged() { - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoAddress.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoAddress.json"_L1); SelfAuthenticationData selfAuthenticationData(data); mContext->setSelfAuthenticationData(selfAuthenticationData); mModel->resetContext(mContext); diff --git a/test/qt/ui/qml/test_SettingsModel.cpp b/test/qt/ui/qml/test_SettingsModel.cpp new file mode 100644 index 000000000..2a6285242 --- /dev/null +++ b/test/qt/ui/qml/test_SettingsModel.cpp @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + + +#include "SettingsModel.h" + +#include "AppSettings.h" + +#include +#include + + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +class test_SettingsModel + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void testAutoRedirect() + { + auto* model = Env::getSingleton(); + QSignalSpy spy(model, &SettingsModel::fireAutoRedirectAfterAuthenticationChanged); + + QCOMPARE(spy.count(), 0); + QCOMPARE(model->isAutoRedirectAfterAuthentication(), true); + + model->setAutoRedirectAfterAuthentication(false); + QCOMPARE(spy.count(), 1); + QCOMPARE(model->isAutoRedirectAfterAuthentication(), false); + + model->setAutoRedirectAfterAuthentication(false); + QCOMPARE(spy.count(), 1); + QCOMPARE(model->isAutoRedirectAfterAuthentication(), false); + + model->setAutoRedirectAfterAuthentication(true); + QCOMPARE(spy.count(), 2); + QCOMPARE(model->isAutoRedirectAfterAuthentication(), true); + + model->setAutoRedirectAfterAuthentication(true); + QCOMPARE(spy.count(), 2); + QCOMPARE(model->isAutoRedirectAfterAuthentication(), true); + } + + + void testAnimations() + { + const auto* model = Env::getSingleton(); + QSignalSpy animationsSpy(model, &SettingsModel::fireUseAnimationsChanged); + + QCOMPARE(animationsSpy.count(), 0); + QCOMPARE(model->isUseAnimations(), true); + + model->setUseAnimations(false); + QCOMPARE(animationsSpy.count(), 1); + QCOMPARE(model->isUseAnimations(), false); + + model->setUseAnimations(false); + QCOMPARE(animationsSpy.count(), 1); + QCOMPARE(model->isUseAnimations(), false); + + model->setUseAnimations(true); + QCOMPARE(animationsSpy.count(), 2); + QCOMPARE(model->isUseAnimations(), true); + + model->setUseAnimations(true); + QCOMPARE(animationsSpy.count(), 2); + QCOMPARE(model->isUseAnimations(), true); + } + + + void testModeOption() + { + const auto& settings = Env::getSingleton()->getGeneralSettings(); + auto* model = Env::getSingleton(); + QCOMPARE(model->getDarkMode(), SettingsModel::ModeOption::OFF); + + model->setDarkMode(SettingsModel::ModeOption::AUTO); + QCOMPARE(settings.getDarkMode(), "AUTO"_L1); + QCOMPARE(model->getDarkMode(), SettingsModel::ModeOption::AUTO); + + model->setDarkMode(SettingsModel::ModeOption::ON); + QCOMPARE(settings.getDarkMode(), "ON"_L1); + QCOMPARE(model->getDarkMode(), SettingsModel::ModeOption::ON); + } + + +}; + +QTEST_GUILESS_MAIN(test_SettingsModel) +#include "test_SettingsModel.moc" diff --git a/test/qt/ui/qml/test_SortedReaderModel.cpp b/test/qt/ui/qml/test_SortedReaderModel.cpp index 84cd915b5..fc92a107d 100644 --- a/test/qt/ui/qml/test_SortedReaderModel.cpp +++ b/test/qt/ui/qml/test_SortedReaderModel.cpp @@ -1,11 +1,12 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include #include "ReaderModel.h" +using namespace Qt::Literals::StringLiterals; using namespace governikus; struct FakeReaderInfo @@ -22,10 +23,10 @@ class MockReaderModel Q_OBJECT private: - QVector mReaders; + QList mReaders; public: - explicit MockReaderModel(const QVector& readers); + explicit MockReaderModel(const QList& readers); int rowCount(const QModelIndex& parent) const override; @@ -37,7 +38,7 @@ class MockReaderModel QVariant data(const QModelIndex& index, int role) const override; }; -MockReaderModel::MockReaderModel(const QVector& readers) +MockReaderModel::MockReaderModel(const QList& readers) : mReaders(readers) { } @@ -89,11 +90,11 @@ class test_SortedReaderModel private Q_SLOTS: void test_order() { - QVector readers = { - {"3", false, false}, - {"0", true, true}, - {"1", false, true}, - {"2", true, false} + QList readers = { + {"3"_L1, false, false}, + {"0"_L1, true, true}, + {"1"_L1, false, true}, + {"2"_L1, true, false} }; MockReaderModel sourceModel(readers); SortedReaderModel sortedModel; @@ -102,10 +103,10 @@ class test_SortedReaderModel sortedModel.onDataChanged(); QVERIFY(sortedModel.rowCount() == 4); - QCOMPARE(sortedModel.data(sortedModel.index(0, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "0"); - QCOMPARE(sortedModel.data(sortedModel.index(1, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "1"); - QCOMPARE(sortedModel.data(sortedModel.index(2, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "2"); - QCOMPARE(sortedModel.data(sortedModel.index(3, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "3"); + QCOMPARE(sortedModel.data(sortedModel.index(0, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "0"_L1); + QCOMPARE(sortedModel.data(sortedModel.index(1, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "1"_L1); + QCOMPARE(sortedModel.data(sortedModel.index(2, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "2"_L1); + QCOMPARE(sortedModel.data(sortedModel.index(3, 0, QModelIndex()), ReaderModel::UserRoles::READER_NAME), "3"_L1); } diff --git a/test/qt/ui/qml/test_UILoader.cpp b/test/qt/ui/qml/test_UiLoader.cpp similarity index 55% rename from test/qt/ui/qml/test_UILoader.cpp rename to test/qt/ui/qml/test_UiLoader.cpp index 66e2f98da..1f54606d9 100644 --- a/test/qt/ui/qml/test_UILoader.cpp +++ b/test/qt/ui/qml/test_UiLoader.cpp @@ -1,24 +1,24 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UILoader + * \brief Unit tests for \ref UiLoader */ -#include "UILoader.h" +#include "UiLoader.h" -#include "UIPlugInJson.h" -#include "UIPlugInWebSocket.h" +#include "UiPluginJson.h" +#include "UiPluginWebSocket.h" #include #include using namespace governikus; -Q_IMPORT_PLUGIN(UIPlugInWebSocket) +Q_IMPORT_PLUGIN(UiPluginWebSocket) -class test_UILoader +class test_UiLoader : public QObject { Q_OBJECT @@ -26,67 +26,67 @@ class test_UILoader private Q_SLOTS: void isNotLoaded() { - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QVERIFY(loader.initialize()); QVERIFY(!loader.isLoaded()); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); QTest::ignoreMessage(QtCriticalMsg, R"(Cannot find UI plugin: "json")"); - QVERIFY(!loader.load()); + QVERIFY(!loader.load()); QVERIFY(!loader.isLoaded()); - QVERIFY(!loader.getLoaded()); + QVERIFY(!loader.getLoaded()); QCOMPARE(spyLoaded.count(), 0); - QTest::ignoreMessage(QtDebugMsg, "Shutdown UILoader: QList()"); + QTest::ignoreMessage(QtDebugMsg, "Shutdown UiLoader: QList()"); loader.shutdown(); } void checkNonEmptyDefault() { - QCOMPARE(UILoader::getDefault(), QStringLiteral("websocket")); + QCOMPARE(UiLoader::getDefault(), QStringLiteral("websocket")); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "websocket")"); QTest::ignoreMessage(QtDebugMsg, R"(Try to load UI plugin: "json")"); QTest::ignoreMessage(QtCriticalMsg, R"(Cannot find UI plugin: "json")"); QTest::ignoreMessage(QtWarningMsg, "Cannot start WebSocket because JSON-API is missing"); - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QVERIFY(loader.load()); QVERIFY(loader.isLoaded()); QVERIFY(!loader.initialize()); - QVERIFY(loader.getLoaded()); + QVERIFY(loader.getLoaded()); QCOMPARE(spyLoaded.count(), 1); QVERIFY(loader.requiresReaderManager()); - const auto* ui = loader.getLoaded(); + const auto* ui = loader.getLoaded(); QCOMPARE(ui->property("default"), QVariant(true)); QCOMPARE(ui->property("passive"), QVariant()); QCOMPARE(ui->property("readerManager"), QVariant()); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("websocket"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("websocket"))"); } void userRequestReset() // reset to initial default { - UILoader::setUserRequest({QStringLiteral("json")}); - UILoader::setUserRequest({}); - UILoader loader; - QSignalSpy spyLoaded(&loader, &UILoader::fireLoadedPlugin); + UiLoader::setUserRequest({QStringLiteral("json")}); + UiLoader::setUserRequest({}); + UiLoader loader; + QSignalSpy spyLoaded(&loader, &UiLoader::fireLoadedPlugin); QVERIFY(loader.load()); QVERIFY(loader.isLoaded()); QVERIFY(!loader.initialize()); - QVERIFY(loader.getLoaded()); + QVERIFY(loader.getLoaded()); QCOMPARE(spyLoaded.count(), 1); - QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UILoader: QList("websocket"))"); + QTest::ignoreMessage(QtDebugMsg, R"(Shutdown UiLoader: QList("websocket"))"); } }; -QTEST_GUILESS_MAIN(test_UILoader) -#include "test_UILoader.moc" +QTEST_GUILESS_MAIN(test_UiLoader) +#include "test_UiLoader.moc" diff --git a/test/qt/ui/qml/test_UIPlugInQml.cpp b/test/qt/ui/qml/test_UiPluginQml.cpp similarity index 80% rename from test/qt/ui/qml/test_UIPlugInQml.cpp rename to test/qt/ui/qml/test_UiPluginQml.cpp index 8f5aaa603..638e5da4a 100644 --- a/test/qt/ui/qml/test_UIPlugInQml.cpp +++ b/test/qt/ui/qml/test_UiPluginQml.cpp @@ -1,8 +1,8 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2023-2024 Governikus GmbH & Co. KG, Germany */ -#include "UIPlugInQml.h" +#include "UiPluginQml.h" #include "context/AuthContext.h" #include "context/ChangePinContext.h" @@ -30,17 +30,23 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QSharedPointer) -class test_UIPlugInQml +class test_UiPluginQml : public QObject { Q_OBJECT private Q_SLOTS: + void init() + { + qunsetenv("OVERRIDE_PLATFORM"); + } + + void test_onWorkflowChanged_data() { QTest::addColumn>("request"); @@ -83,7 +89,7 @@ class test_UIPlugInQml QVERIFY(!Env::getSingleton()->mContext); QVERIFY(!Env::getSingleton()->mContext); - UIPlugInQml plugin; + UiPluginQml plugin; plugin.onWorkflowStarted(request); QCOMPARE(Env::getSingleton()->getDelay(), 1000); QVERIFY(Env::getSingleton()->mContext); @@ -117,7 +123,7 @@ class test_UIPlugInQml void test_useSystemFontChanged() { ResourceLoader::getInstance().init(); - UIPlugInQml plugin; + UiPluginQml plugin; auto& generalSettings = Env::getSingleton()->getGeneralSettings(); QVERIFY(!generalSettings.isUseSystemFont()); @@ -133,8 +139,8 @@ class test_UIPlugInQml void test_setFontScaleFactor() { - UIPlugInQml plugin; - QSignalSpy spy(&plugin, &UIPlugInQml::fireFontScaleFactorChanged); + UiPluginQml plugin; + QSignalSpy spy(&plugin, &UiPluginQml::fireFontScaleFactorChanged); const auto initialValue = plugin.getFontScaleFactor(); @@ -150,8 +156,8 @@ class test_UIPlugInQml void test_setDarkMode() { - UIPlugInQml plugin; - QSignalSpy spy(&plugin, &UIPlugInQml::fireOsDarkModeChanged); + UiPluginQml plugin; + QSignalSpy spy(&plugin, &UiPluginQml::fireOsDarkModeChanged); const auto initialValue = plugin.isOsDarkModeEnabled(); @@ -165,7 +171,34 @@ class test_UIPlugInQml } + void test_overridePlattform() + { + QCOMPARE(UiPluginQml::getOverridePlatform(), QString()); + qputenv("OVERRIDE_PLATFORM", "dummy"_ba); + QCOMPARE(UiPluginQml::getOverridePlatform(), QStringLiteral("dummy")); + } + + + void test_adjustQmlImportPath() + { + const auto& primaryPrefix = QStringLiteral("qrc:/qt/qml"); + QCOMPARE(UiPluginQml::adjustQmlImportPath(nullptr), primaryPrefix); + + QQmlEngine engine; + QCOMPARE(UiPluginQml::adjustQmlImportPath(&engine), primaryPrefix); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) + QVERIFY(engine.importPathList().contains(primaryPrefix)); +#endif + + qputenv("OVERRIDE_PLATFORM", "platform"_ba); + QTest::ignoreMessage(QtDebugMsg, "Override platform: \"platform\""); + QCOMPARE(UiPluginQml::adjustQmlImportPath(&engine), "qrc:/platform"_L1); + QVERIFY(!engine.importPathList().contains(primaryPrefix)); + QVERIFY(engine.importPathList().contains("qrc:/platform"_L1)); + } + + }; -QTEST_MAIN(test_UIPlugInQml) -#include "test_UIPlugInQml.moc" +QTEST_MAIN(test_UiPluginQml) +#include "test_UiPluginQml.moc" diff --git a/test/qt/ui/qml/test_WorkflowModel.cpp b/test/qt/ui/qml/test_WorkflowModel.cpp index 7e78fa693..663c96c12 100644 --- a/test/qt/ui/qml/test_WorkflowModel.cpp +++ b/test/qt/ui/qml/test_WorkflowModel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,7 +10,7 @@ #include "Env.h" #include "MockCardConnectionWorker.h" -#include "MockReaderManagerPlugIn.h" +#include "MockReaderManagerPlugin.h" #include "ReaderManager.h" #include "ResourceLoader.h" #include "TestWorkflowContext.h" @@ -20,8 +20,9 @@ #include -Q_IMPORT_PLUGIN(MockReaderManagerPlugIn) +Q_IMPORT_PLUGIN(MockReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -33,7 +34,7 @@ class test_WorkflowModel private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -57,7 +58,7 @@ class test_WorkflowModel QSignalSpy spyCurrentStateChanged(&model, &WorkflowModel::fireCurrentStateChanged); QSignalSpy spyStateEntered(&model, &WorkflowModel::fireStateEntered); QSignalSpy spyResultChanged(&model, &WorkflowModel::fireResultChanged); - QSignalSpy spyReaderPlugInTypeChanged(&model, &WorkflowModel::fireReaderPlugInTypeChanged); + QSignalSpy spyReaderPluginTypeChanged(&model, &WorkflowModel::fireReaderPluginTypeChanged); QSignalSpy spySelectedReaderChanged(&model, &WorkflowModel::fireSelectedReaderChanged); QSignalSpy spyWorkflowFinished(&model, &WorkflowModel::fireWorkflowFinished); @@ -75,15 +76,15 @@ class test_WorkflowModel QCOMPARE(spyResultChanged.count(), 2); QCOMPARE(spyWorkflowFinished.count(), 1); - Q_EMIT context->fireStateChanged(QString("state")); + Q_EMIT context->fireStateChanged("state"_L1); QCOMPARE(spyCurrentStateChanged.count(), 3); QCOMPARE(spyStateEntered.count(), 1); Q_EMIT context->fireResultChanged(); QCOMPARE(spyResultChanged.count(), 3); - Q_EMIT context->fireReaderPlugInTypesChanged(); - QCOMPARE(spyReaderPlugInTypeChanged.count(), 1); + Q_EMIT context->fireReaderPluginTypesChanged(); + QCOMPARE(spyReaderPluginTypeChanged.count(), 1); Q_EMIT context->fireCardConnectionChanged(); QCOMPARE(spySelectedReaderChanged.count(), 1); @@ -117,23 +118,23 @@ class test_WorkflowModel } - void test_ReaderPlugInType() + void test_ReaderPluginType() { WorkflowModel model; QSharedPointer context(new TestWorkflowContext()); - QCOMPARE(model.getReaderPlugInType(), ReaderManagerPlugInType::UNKNOWN); + QCOMPARE(model.getReaderPluginType(), ReaderManagerPluginType::UNKNOWN); model.mContext = context; - QCOMPARE(model.getReaderPlugInType(), ReaderManagerPlugInType::UNKNOWN); + QCOMPARE(model.getReaderPluginType(), ReaderManagerPluginType::UNKNOWN); - model.setReaderPlugInType(ReaderManagerPlugInType::UNKNOWN); - QVERIFY(context->getReaderPlugInTypes().contains(ReaderManagerPlugInType::UNKNOWN)); - QCOMPARE(model.getReaderPlugInType(), ReaderManagerPlugInType::UNKNOWN); + model.setReaderPluginType(ReaderManagerPluginType::UNKNOWN); + QVERIFY(context->getReaderPluginTypes().contains(ReaderManagerPluginType::UNKNOWN)); + QCOMPARE(model.getReaderPluginType(), ReaderManagerPluginType::UNKNOWN); - model.setReaderPlugInType(ReaderManagerPlugInType::NFC); - QVERIFY(context->getReaderPlugInTypes().contains(ReaderManagerPlugInType::NFC)); - QCOMPARE(model.getReaderPlugInType(), ReaderManagerPlugInType::NFC); + model.setReaderPluginType(ReaderManagerPluginType::NFC); + QVERIFY(context->getReaderPluginTypes().contains(ReaderManagerPluginType::NFC)); + QCOMPARE(model.getReaderPluginType(), ReaderManagerPluginType::NFC); } @@ -147,7 +148,7 @@ class test_WorkflowModel void test_startScanExplicitly() { QSharedPointer context(new TestWorkflowContext()); - QSignalSpy spy(context.data(), &WorkflowContext::fireReaderPlugInTypesChanged); + QSignalSpy spy(context.data(), &WorkflowContext::fireReaderPluginTypesChanged); WorkflowModel model; model.resetWorkflowContext(context); @@ -167,11 +168,11 @@ class test_WorkflowModel model.resetWorkflowContext(context); QCOMPARE(model.hasCard(), false); - auto mockReader = MockReaderManagerPlugIn::getInstance().addReader("SomeReaderWithCard"); + auto mockReader = MockReaderManagerPlugin::getInstance().addReader("SomeReaderWithCard"_L1); auto info = mockReader->getReaderInfo(); - info.setCardInfo(CardInfo(CardType::EID_CARD, QSharedPointer(), 3, false, false, false)); + info.setCardInfo(CardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, false, false, false)); mockReader->setReaderInfo(info); - model.setReaderPlugInType(ReaderManagerPlugInType::MOCK); + model.setReaderPluginType(ReaderManagerPluginType::MOCK); QCOMPARE(model.hasCard(), true); } @@ -192,7 +193,7 @@ class test_WorkflowModel void test_statusCodeImage() { QSharedPointer context(new TestWorkflowContext()); - QSignalSpy spy(context.data(), &WorkflowContext::fireReaderPlugInTypesChanged); + QSignalSpy spy(context.data(), &WorkflowContext::fireReaderPluginTypesChanged); QFETCH(GlobalStatus::Code, statusCode); context->setStatus(statusCode); @@ -201,13 +202,13 @@ class test_WorkflowModel model.resetWorkflowContext(context); auto image = model.getStatusCodeImage(); - image = image.replace("qrc://", ":"); + image = image.replace("qrc://"_L1, ":"_L1); if (image.isEmpty()) { return; } - if (image.contains("%1")) + if (image.contains("%1"_L1)) { QStringList themes; themes << QStringLiteral("darkmode") << QStringLiteral("lightmode") << QStringLiteral("highcontrast"); @@ -215,14 +216,27 @@ class test_WorkflowModel for (const auto& theme : themes) { const auto fileName = image.arg(theme); - QVERIFY2(QFile(fileName).exists(), qPrintable(QString("%1 not found").arg(fileName))); + QVERIFY2(QFile(fileName).exists(), qPrintable("%1 not found"_L1.arg(fileName))); } } else { QVERIFY(QFile::exists(image)); } + } + + + void test_getLastReturnCode() + { + WorkflowModel model; + QCOMPARE(model.getLastReturnCode(), CardReturnCode::UNDEFINED); + + QSharedPointer context(new TestWorkflowContext()); + model.resetWorkflowContext(context); + QCOMPARE(model.getLastReturnCode(), CardReturnCode::OK); + context->setLastPaceResult(CardReturnCode::CANCELLATION_BY_USER); + QCOMPARE(model.getLastReturnCode(), CardReturnCode::CANCELLATION_BY_USER); } diff --git a/test/qt/ui/scheme/test_UIPlugInScheme.cpp b/test/qt/ui/scheme/test_UiPluginScheme.cpp similarity index 56% rename from test/qt/ui/scheme/test_UIPlugInScheme.cpp rename to test/qt/ui/scheme/test_UiPluginScheme.cpp index 0e3551c97..5def735ce 100644 --- a/test/qt/ui/scheme/test_UIPlugInScheme.cpp +++ b/test/qt/ui/scheme/test_UiPluginScheme.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! - * \brief Unit tests for \ref UIPlugInScheme + * \brief Unit tests for \ref UiPluginScheme */ -#include "UIPlugInScheme.h" +#include "UiPluginScheme.h" #include "WorkflowRequest.h" #include "context/AuthContext.h" @@ -14,11 +14,12 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QSharedPointer) -class test_UIPlugInScheme +class test_UiPluginScheme : public QObject { Q_OBJECT @@ -31,18 +32,18 @@ class test_UIPlugInScheme { QTest::addColumn("url"); - QTest::newRow(" 1") << QUrl("eid://127.0.0.1:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 2") << QUrl("eid://localhost:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 3") << QUrl("eid://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"); - QTest::newRow(" 4") << QUrl("eid://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 5") << QUrl("http://127.0.0.1:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 6") << QUrl("http://localhost:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 7") << QUrl("http://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"); - QTest::newRow(" 8") << QUrl("http://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"); - QTest::newRow(" 9") << QUrl("https://127.0.0.1:24727/eID-Client?tctokenURL=bla"); - QTest::newRow("10") << QUrl("https://localhost:24727/eID-Client?tctokenURL=bla"); - QTest::newRow("11") << QUrl("https://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"); - QTest::newRow("12") << QUrl("https://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"); + QTest::newRow(" 1") << QUrl("eid://127.0.0.1:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 2") << QUrl("eid://localhost:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 3") << QUrl("eid://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 4") << QUrl("eid://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 5") << QUrl("http://127.0.0.1:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 6") << QUrl("http://localhost:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 7") << QUrl("http://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 8") << QUrl("http://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 9") << QUrl("https://127.0.0.1:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow("10") << QUrl("https://localhost:24727/eID-Client?tctokenURL=bla"_L1); + QTest::newRow("11") << QUrl("https://www.ausweisapp.bund.de/eID-Client?tctokenURL=bla"_L1); + QTest::newRow("12") << QUrl("https://www.ausweisapp.bund.de:24727/eID-Client?tctokenURL=bla"_L1); } @@ -50,8 +51,8 @@ class test_UIPlugInScheme { QFETCH(QUrl, url); - UIPlugInScheme ui; - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); + UiPluginScheme ui; + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); QDesktopServices::openUrl(url); QCOMPARE(spy.count(), 1); @@ -64,23 +65,23 @@ class test_UIPlugInScheme void showui_data() { QTest::addColumn("module"); - QTest::addColumn("urlTemplate"); + QTest::addColumn("urlTemplate"); const auto& uiModules = Enum::getList(); for (const auto& module : uiModules) { - QTest::newRow(QString("%1 - eid - ip").arg(getEnumName(module)).toUtf8().constData()) << module << QString("eid://127.0.0.1:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - eid - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << QString("eid://localhost:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - eid - url").arg(getEnumName(module)).toUtf8().constData()) << module << QString("eid://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - eid - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << QString("eid://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - http - ip").arg(getEnumName(module)).toUtf8().constData()) << module << QString("http://127.0.0.1:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - http - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << QString("http://localhost:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - http - url").arg(getEnumName(module)).toUtf8().constData()) << module << QString("http://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - http - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << QString("http://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - https - ip").arg(getEnumName(module)).toUtf8().constData()) << module << QString("https://127.0.0.1:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - https - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << QString("https://localhost:24727/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - https - url").arg(getEnumName(module)).toUtf8().constData()) << module << QString("https://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"); - QTest::newRow(QString("%1 - https - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << QString("https://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"); + QTest::newRow(QStringLiteral("%1 - eid - ip").arg(getEnumName(module)).toUtf8().constData()) << module << "eid://127.0.0.1:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - eid - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << "eid://localhost:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - eid - url").arg(getEnumName(module)).toUtf8().constData()) << module << "eid://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - eid - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << "eid://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - http - ip").arg(getEnumName(module)).toUtf8().constData()) << module << "http://127.0.0.1:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - http - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << "http://localhost:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - http - url").arg(getEnumName(module)).toUtf8().constData()) << module << "http://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - http - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << "http://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - https - ip").arg(getEnumName(module)).toUtf8().constData()) << module << "https://127.0.0.1:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - https - localhost").arg(getEnumName(module)).toUtf8().constData()) << module << "https://localhost:24727/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - https - url").arg(getEnumName(module)).toUtf8().constData()) << module << "https://www.ausweisapp.bund.de/eID-Client?ShowUI=%1"_L1; + QTest::newRow(QStringLiteral("%1 - https - url - port").arg(getEnumName(module)).toUtf8().constData()) << module << "https://www.ausweisapp.bund.de:24727/eID-Client?ShowUI=%1"_L1; } } @@ -88,10 +89,10 @@ class test_UIPlugInScheme void showui() { QFETCH(UiModule, module); - QFETCH(QString, urlTemplate); + QFETCH(QLatin1String, urlTemplate); - UIPlugInScheme ui; - QSignalSpy spy(&ui, &UIPlugIn::fireShowUiRequested); + UiPluginScheme ui; + QSignalSpy spy(&ui, &UiPlugin::fireShowUiRequested); const QLatin1String moduleName = Enum::getName(module); @@ -109,11 +110,11 @@ class test_UIPlugInScheme { QTest::addColumn("url"); - QTest::newRow("1") << QUrl("https://127.0.0.1/eID-Client?tctokenURL=bla"); - QTest::newRow("2") << QUrl("https://localhost/eID-Client?tctokenURL=bla"); - QTest::newRow("3") << QUrl("https://localhost:24727/eID?tctokenURL=bla"); - QTest::newRow("4") << QUrl("https://www.ausweisapp.bund.de/de/aa2/a11y"); - QTest::newRow("5") << QUrl("https://www.ausweisapp.bund.de/en/aa2/a11y"); + QTest::newRow("1") << QUrl("https://127.0.0.1/eID-Client?tctokenURL=bla"_L1); + QTest::newRow("2") << QUrl("https://localhost/eID-Client?tctokenURL=bla"_L1); + QTest::newRow("3") << QUrl("https://localhost:24727/eID?tctokenURL=bla"_L1); + QTest::newRow("4") << QUrl("https://www.ausweisapp.bund.de/de/aa2/a11y"_L1); + QTest::newRow("5") << QUrl("https://www.ausweisapp.bund.de/en/aa2/a11y"_L1); } @@ -121,8 +122,8 @@ class test_UIPlugInScheme { QFETCH(QUrl, url); - UIPlugInScheme ui; - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); + UiPluginScheme ui; + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); QTest::ignoreMessage(QtDebugMsg, "Not our business. Using the appropriate mechanism for the user's desktop environment."); QDesktopServices::openUrl(url); @@ -134,11 +135,11 @@ class test_UIPlugInScheme { QTest::addColumn("url"); - QTest::newRow(" 1") << QUrl("eid://127.0.0.1/eID-Client?tctokenURL=bla"); - QTest::newRow(" 2") << QUrl("eid://localhost/eID-Client?tctokenURL=bla"); - QTest::newRow(" 3") << QUrl("eid://localhost:24727/eID?tctokenURL=bla"); - QTest::newRow(" 4") << QUrl("eid://www.ausweisapp.bund.de/de/aa2/a11y"); - QTest::newRow(" 5") << QUrl("eid://www.ausweisapp.bund.de/en/aa2/a11y"); + QTest::newRow(" 1") << QUrl("eid://127.0.0.1/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 2") << QUrl("eid://localhost/eID-Client?tctokenURL=bla"_L1); + QTest::newRow(" 3") << QUrl("eid://localhost:24727/eID?tctokenURL=bla"_L1); + QTest::newRow(" 4") << QUrl("eid://www.ausweisapp.bund.de/de/aa2/a11y"_L1); + QTest::newRow(" 5") << QUrl("eid://www.ausweisapp.bund.de/en/aa2/a11y"_L1); } @@ -146,8 +147,8 @@ class test_UIPlugInScheme { QFETCH(QUrl, url); - UIPlugInScheme ui; - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); + UiPluginScheme ui; + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); QTest::ignoreMessage(QtWarningMsg, "Request type: unknown"); QDesktopServices::openUrl(url); @@ -157,12 +158,12 @@ class test_UIPlugInScheme void unknownQuery() { - UIPlugInScheme ui; - QSignalSpy spyUi(&ui, &UIPlugIn::fireShowUiRequested); - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); + UiPluginScheme ui; + QSignalSpy spyUi(&ui, &UiPlugin::fireShowUiRequested); + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); QTest::ignoreMessage(QtWarningMsg, "Unknown query type: QUrl(\"eid://127.0.0.1:24727/eID-Client?foo=bar\")"); - QDesktopServices::openUrl(QUrl("eid://127.0.0.1:24727/eID-Client?foo=bar")); + QDesktopServices::openUrl(QUrl("eid://127.0.0.1:24727/eID-Client?foo=bar"_L1)); QCOMPARE(spyUi.count(), 0); QCOMPARE(spy.count(), 0); } @@ -170,31 +171,31 @@ class test_UIPlugInScheme void onCustomUrl() { - UIPlugInScheme ui; + UiPluginScheme ui; QUrl url; - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); - connect(&ui, &UIPlugIn::fireWorkflowRequested, this, [&url](const QSharedPointer& pRequest){ + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); + connect(&ui, &UiPlugin::fireWorkflowRequested, this, [&url](const QSharedPointer& pRequest){ url = pRequest->getContext().objectCast()->getActivationUrl(); }); QTest::ignoreMessage(QtDebugMsg, "Got new request"); QTest::ignoreMessage(QtDebugMsg, "Request URL: QUrl(\"http://crap\")"); QTest::ignoreMessage(QtDebugMsg, "Not our business. Using the appropriate mechanism for the user's desktop environment."); - ui.onCustomUrl(QUrl("http://crap")); + ui.onCustomUrl(QUrl("http://crap"_L1)); QCOMPARE(spy.count(), 0); - const QUrl testUrl("http://localhost:24727/eID-Client?tcTokenURL=http://bla"); + const QUrl testUrl("http://localhost:24727/eID-Client?tcTokenURL=http://bla"_L1); QTest::ignoreMessage(QtDebugMsg, "Got new request"); QTest::ignoreMessage(QtDebugMsg, "Request type: authentication"); ui.onCustomUrl(testUrl); QCOMPARE(spy.count(), 1); QCOMPARE(url, testUrl); - QSignalSpy spyShowUi(&ui, &UIPlugIn::fireShowUiRequested); + QSignalSpy spyShowUi(&ui, &UiPlugin::fireShowUiRequested); QTest::ignoreMessage(QtDebugMsg, "Got new request"); QTest::ignoreMessage(QtDebugMsg, "Request type: showui"); - ui.onCustomUrl(QUrl("http://localhost:24727/eID-Client?showUi")); + ui.onCustomUrl(QUrl("http://localhost:24727/eID-Client?showUi"_L1)); QCOMPARE(spy.count(), 1); QCOMPARE(spyShowUi.count(), 1); } @@ -208,35 +209,35 @@ class test_UIPlugInScheme void sendRedirect() { - UIPlugInScheme ui; + UiPluginScheme ui; QSharedPointer request; - QSignalSpy spy(&ui, &UIPlugIn::fireWorkflowRequested); - connect(&ui, &UIPlugIn::fireWorkflowRequested, this, [&request](const QSharedPointer& pRequest){ + QSignalSpy spy(&ui, &UiPlugin::fireWorkflowRequested); + connect(&ui, &UiPlugin::fireWorkflowRequested, this, [&request](const QSharedPointer& pRequest){ request = pRequest; }); QTest::ignoreMessage(QtDebugMsg, "Got new request"); QTest::ignoreMessage(QtDebugMsg, "Request type: authentication"); - ui.onCustomUrl(QUrl("http://localhost:24727/eID-Client?tcTokenURL=https://bla")); + ui.onCustomUrl(QUrl("http://localhost:24727/eID-Client?tcTokenURL=https://bla"_L1)); QVERIFY(request); - QVERIFY(request->getData().value()); + QCOMPARE(request->getData().metaType(), QMetaType::fromType()); auto authContext = request->getContext().objectCast(); QVERIFY(authContext); - authContext->setRefreshUrl(QUrl("https://www.example.com")); + authContext->setRefreshUrl(QUrl("https://www.example.com?ResultMajor=ok"_L1)); authContext->setStatus(GlobalStatus::Code::No_Error); QDesktopServices::setUrlHandler(QStringLiteral("https"), this, "sendRedirectOnCustomUrl"); - QTest::ignoreMessage(QtDebugMsg, "Determined redirect URL QUrl(\"https://www.example.com?ResultMajor=ok\")"); + QTest::ignoreMessage(QtDebugMsg, "Perform redirect to URL QUrl(\"https://www.example.com?ResultMajor=ok\")"); ui.onWorkflowFinished(request); - QTRY_COMPARE(mReceivedUrl, QUrl("https://www.example.com?ResultMajor=ok")); // clazy:exclude=qstring-allocations + QTRY_COMPARE(mReceivedUrl, QUrl("https://www.example.com?ResultMajor=ok"_L1)); // clazy:exclude=qstring-allocations QDesktopServices::unsetUrlHandler(QStringLiteral("https")); } }; -QTEST_GUILESS_MAIN(test_UIPlugInScheme) -#include "test_UIPlugInScheme.moc" +QTEST_GUILESS_MAIN(test_UiPluginScheme) +#include "test_UiPluginScheme.moc" diff --git a/test/qt/ui/webservice/test_UIPlugInWebServiceBrowserHandler.cpp b/test/qt/ui/webservice/test_UIPlugInWebServiceBrowserHandler.cpp deleted file mode 100644 index 065eb5270..000000000 --- a/test/qt/ui/webservice/test_UIPlugInWebServiceBrowserHandler.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "UIPlugInWebService.h" - -#include "MockSocket.h" -#include "ResourceLoader.h" -#include "WorkflowRequest.h" -#include "context/AuthContext.h" - -#include -#include - -using namespace governikus; - -class test_UIPlugInWebServiceBrowserHandler - : public QObject -{ - Q_OBJECT - QPointer mSocket; - QSharedPointer mRequest; - QSharedPointer mAuthContext; - - QByteArray split(const QByteArray& pData) - { - return pData.split('\r').at(0); - } - - private Q_SLOTS: - void initTestCase() - { - //QCoreApplication::setApplicationVersion("1.0.0"); - HttpServer::cPort = 0; - } - - - void init() - { - mSocket = new MockSocket(); - mSocket->setSocketState(QAbstractSocket::ConnectedState); - mRequest.reset(new HttpRequest(mSocket)); - mAuthContext.reset(new AuthContext(true, QUrl("http://activationUrl"))); - - ResourceLoader::getInstance().init(); // html templates - } - - - void getActivationUrl() - { - mSocket->mReadBuffer = QByteArray("GET /testUrl HTTP/1.1\r\n" - "\r\n\r\n"); - Q_EMIT mSocket->readyRead(); - QCOMPARE(mRequest->getUrl().toEncoded(), QByteArray("/testUrl")); - - UIPlugInWebService ui; - - QUrl url; - connect(&ui, &UIPlugIn::fireWorkflowRequested, this, [&url](const QSharedPointer& pRequest){ - url = pRequest->getContext().objectCast()->getActivationUrl(); - }); - - ui.handleWorkflowRequest(mRequest); - QCOMPARE(url.toEncoded(), QByteArray("/testUrl")); - } - - - void connectionLost() - { - mSocket->setSocketState(QAbstractSocket::UnconnectedState); - UIPlugInWebService ui; - - // lost for error page - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QLatin1String("The browser connection was lost.")); - - // lost for correct redirect - mAuthContext->setTcTokenNotFound(false); - mAuthContext->setRefreshUrl(QUrl("http://dummy")); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QLatin1String("The connection to the browser was lost. No forwarding was executed. Please try to call the URL again manually: dummy")); - } - - - void tcTokenNotFound() - { - UIPlugInWebService ui; - mAuthContext->setTcTokenNotFound(true); - - QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 404"); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 404 Not Found"); - } - - - void internalErrorBeforeTcToken() - { - UIPlugInWebService ui; - mAuthContext->setStatus(GlobalStatus::Code::Workflow_InternalError_BeforeTcToken); - - QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 500"); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 500 Internal Server Error"); - } - - - void emptyRefreshUrlNoTcToken() - { - UIPlugInWebService ui; - mAuthContext->setTcTokenNotFound(false); - - QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 400"); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 400 Bad Request"); - } - - - void emptyRefreshUrlNoCommunicationErrorAddress() - { - const QByteArray tokenData("" - "" - " https://eid-server.example.de/entrypoint" - " 1A2BB129" - " https://service.example.de/loggedin?7eb39f62" - " urn:liberty:paos:2006-08 " - " urn:ietf:rfc:4279 " - " " - " 4BC1A0B5 " - " " - ""); - - UIPlugInWebService ui; - mAuthContext->setTcTokenNotFound(false); - mAuthContext->setTcToken(QSharedPointer::create(tokenData)); - - QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 400"); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 400 Bad Request"); - } - - - void emptyRefreshUrl() - { - const QByteArray tokenData("" - "" - " https://eid-server.example.de/entrypoint" - " 1A2BB129" - " https://service.example.de/loggedin?7eb39f62" - " https://flupp" - " urn:liberty:paos:2006-08 " - " urn:ietf:rfc:4279 " - " " - " 4BC1A0B5 " - " " - ""); - - UIPlugInWebService ui; - mAuthContext->setTcTokenNotFound(false); - mAuthContext->setTcToken(QSharedPointer::create(tokenData)); - - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 303 See Other"); - QVERIFY(mSocket->mWriteBuffer.contains("Location: https://flupp")); - } - - - void sendRefreshUrl() - { - UIPlugInWebService ui; - mAuthContext->setTcTokenNotFound(false); - mAuthContext->setRefreshUrl(QUrl("http://dummy")); - - QTest::ignoreMessage(QtDebugMsg, "Redirect URL: QUrl(\"http://dummy?ResultMajor=ok\")"); - QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); - QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 303 See Other"); - QVERIFY(mSocket->mWriteBuffer.contains("Location: http://dummy?ResultMajor=ok")); - } - - -}; - -QTEST_GUILESS_MAIN(test_UIPlugInWebServiceBrowserHandler) -#include "test_UIPlugInWebServiceBrowserHandler.moc" diff --git a/test/qt/ui/webservice/test_UIPlugInWebService.cpp b/test/qt/ui/webservice/test_UiPluginWebService.cpp similarity index 53% rename from test/qt/ui/webservice/test_UIPlugInWebService.cpp rename to test/qt/ui/webservice/test_UiPluginWebService.cpp index 733a8b022..c1076fb45 100644 --- a/test/qt/ui/webservice/test_UIPlugInWebService.cpp +++ b/test/qt/ui/webservice/test_UiPluginWebService.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! * \brief Unit tests for \ref WebserviceActivationHandler */ -#include "UIPlugInWebService.h" +#include "UiPluginWebService.h" #include "HttpServerRequestor.h" #include "MockNetworkManager.h" @@ -19,14 +19,15 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; -class test_UIPlugInWebService +class test_UiPluginWebService : public QObject { Q_OBJECT - QSharedPointer mUi; + QSharedPointer mUi; QScopedPointer mShowUiSpy, mShowUserInfoSpy, mAuthenticationSpy; QUrl getUrl(const QString& pUrl) @@ -44,7 +45,7 @@ class test_UIPlugInWebService private Q_SLOTS: void initTestCase() { - QCoreApplication::setApplicationVersion("1.0.0"); + QCoreApplication::setApplicationVersion("1.0.0"_L1); HttpServer::cPort = 0; ResourceLoader::getInstance().init(); } @@ -52,11 +53,11 @@ class test_UIPlugInWebService void init() { - mUi = QSharedPointer::create(); + mUi = QSharedPointer::create(); QVERIFY(mUi->initialize()); - mShowUiSpy.reset(new QSignalSpy(mUi.data(), &UIPlugIn::fireShowUiRequested)); - mShowUserInfoSpy.reset(new QSignalSpy(mUi.data(), &UIPlugIn::fireShowUserInformationRequested)); - mAuthenticationSpy.reset(new QSignalSpy(mUi.data(), &UIPlugIn::fireWorkflowRequested)); + mShowUiSpy.reset(new QSignalSpy(mUi.data(), &UiPlugin::fireShowUiRequested)); + mShowUserInfoSpy.reset(new QSignalSpy(mUi.data(), &UiPlugin::fireShowUserInformationRequested)); + mAuthenticationSpy.reset(new QSignalSpy(mUi.data(), &UiPlugin::fireWorkflowRequested)); } @@ -69,27 +70,27 @@ class test_UIPlugInWebService void showUI_data() { - QTest::addColumn("url"); + QTest::addColumn("url"); QTest::addColumn("module"); - QTest::newRow("noModule") << QString("/eID-Client?ShowUI") << UiModule::DEFAULT; - QTest::newRow("current") << QString("/eID-Client?ShowUI=current") << UiModule::CURRENT; - QTest::newRow("PINManagement") << QString("/eID-Client?ShowUI=PINManagement") << UiModule::PINMANAGEMENT; - QTest::newRow("PINManagement caseInsensitive") << QString("/eID-Client?ShowUI=PINManagement") << UiModule::PINMANAGEMENT; - QTest::newRow("Settings") << QString("/eID-Client?ShowUI=SETTINGS") << UiModule::SETTINGS; + QTest::newRow("noModule") << QLatin1String("/eID-Client?ShowUI") << UiModule::DEFAULT; + QTest::newRow("current") << QLatin1String("/eID-Client?ShowUI=current") << UiModule::CURRENT; + QTest::newRow("PINManagement") << QLatin1String("/eID-Client?ShowUI=PINManagement") << UiModule::PINMANAGEMENT; + QTest::newRow("PINManagement caseInsensitive") << QLatin1String("/eID-Client?ShowUI=PINManagement") << UiModule::PINMANAGEMENT; + QTest::newRow("Settings") << QLatin1String("/eID-Client?ShowUI=SETTINGS") << UiModule::SETTINGS; - QTest::newRow("Tutorial") << QString("/eID-Client?ShowUI=TUTORIAL") << UiModule::TUTORIAL; - QTest::newRow("Help") << QString("/eID-Client?ShowUI=HELP") << UiModule::HELP; - QTest::newRow("Self AUth") << QString("/eID-Client?ShowUI=SELF_AUTHENTICATION") << UiModule::SELF_AUTHENTICATION; + QTest::newRow("Tutorial") << QLatin1String("/eID-Client?ShowUI=TUTORIAL") << UiModule::TUTORIAL; + QTest::newRow("Help") << QLatin1String("/eID-Client?ShowUI=HELP") << UiModule::HELP; + QTest::newRow("Self AUth") << QLatin1String("/eID-Client?ShowUI=SELF_AUTHENTICATION") << UiModule::SELF_AUTHENTICATION; - QTest::newRow("SMART_EID") << QString("/eID-Client?ShowUI=SMART_EID") << UiModule::SMART_EID; - QTest::newRow("Smart-eID") << QString("/eID-Client?ShowUI=Smart-eID") << UiModule::SMART_EID; + QTest::newRow("SMART_EID") << QLatin1String("/eID-Client?ShowUI=SMART_EID") << UiModule::SMART_EID; + QTest::newRow("Smart-eID") << QLatin1String("/eID-Client?ShowUI=Smart-eID") << UiModule::SMART_EID; } void showUI() { - QFETCH(QString, url); + QFETCH(QLatin1String, url); QFETCH(UiModule, module); QTest::ignoreMessage(QtDebugMsg, "Request type: showui"); @@ -108,22 +109,22 @@ class test_UIPlugInWebService void status_data() { - QTest::addColumn("url"); - QTest::addColumn("header"); - QTest::addColumn("name"); - - QTest::newRow("default") << QString("/eID-Client?status") << QString("text/plain; charset=utf-8") << QString("PLAIN"); - QTest::newRow("plain") << QString("/eID-Client?status=plain") << QString("text/plain; charset=utf-8") << QString("PLAIN"); - QTest::newRow("json") << QString("/eID-Client?status=json") << QString("application/json") << QString("JSON"); - QTest::newRow("json caseInsensitive") << QString("/eID-Client?status=JsoN") << QString("application/json") << QString("JSON"); + QTest::addColumn("url"); + QTest::addColumn("header"); + QTest::addColumn("name"); + + QTest::newRow("default") << QLatin1String("/eID-Client?status") << QLatin1String("text/plain; charset=utf-8") << QLatin1String("PLAIN"); + QTest::newRow("plain") << QLatin1String("/eID-Client?status=plain") << QLatin1String("text/plain; charset=utf-8") << QLatin1String("PLAIN"); + QTest::newRow("json") << QLatin1String("/eID-Client?status=json") << QLatin1String("application/json") << QLatin1String("JSON"); + QTest::newRow("json caseInsensitive") << QLatin1String("/eID-Client?status=JsoN") << QLatin1String("application/json") << QLatin1String("JSON"); } void status() { - QFETCH(QString, url); - QFETCH(QString, header); - QFETCH(QString, name); + QFETCH(QLatin1String, url); + QFETCH(QLatin1String, header); + QFETCH(QLatin1String, name); QTest::ignoreMessage(QtDebugMsg, "Request type: status"); QTest::ignoreMessage(QtDebugMsg, QRegularExpression(QStringLiteral("Create response with status format: ") + name)); @@ -143,21 +144,21 @@ class test_UIPlugInWebService void imageRequest_data() { - QTest::addColumn("url"); - QTest::addColumn("header"); + QTest::addColumn("url"); + QTest::addColumn("header"); QTest::addColumn("size"); QTest::addColumn("error"); - QTest::newRow("favicon") << QString("/favicon.ico") << QString("image/x-icon") << 94921 << QNetworkReply::NoError; - QTest::newRow("smallicon") << QString("/images/html_templates/icon_attention.svg") << QString("image/svg+xml") << 957 << QNetworkReply::NoError; - QTest::newRow("nothing") << QString("/images/html_templates/nothing.gif") << QString() << 0 << QNetworkReply::ContentNotFoundError; + QTest::newRow("favicon") << QLatin1String("/favicon.ico") << QLatin1String("image/x-icon") << 94921 << QNetworkReply::NoError; + QTest::newRow("smallicon") << QLatin1String("/images/html_templates/icon_attention.svg") << QLatin1String("image/svg+xml") << 957 << QNetworkReply::NoError; + QTest::newRow("nothing") << QLatin1String("/images/html_templates/nothing.gif") << QLatin1String() << 0 << QNetworkReply::ContentNotFoundError; } void imageRequest() { - QFETCH(QString, url); - QFETCH(QString, header); + QFETCH(QLatin1String, url); + QFETCH(QLatin1String, header); QFETCH(int, size); QFETCH(QNetworkReply::NetworkError, error); @@ -174,11 +175,11 @@ class test_UIPlugInWebService void authentication() { - connect(mUi.data(), &UIPlugIn::fireWorkflowRequested, mUi.data(), &UIPlugIn::onWorkflowStarted); // fake AppController + connect(mUi.data(), &UiPlugin::fireWorkflowRequested, mUi.data(), &UiPlugin::onWorkflowStarted); // fake AppController QTest::ignoreMessage(QtDebugMsg, "Request type: authentication"); HttpServerRequestor requestor; - QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla")); + QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla"_L1)); QVERIFY(reply); QCOMPARE(reply->error(), QNetworkReply::NoError); @@ -192,7 +193,7 @@ class test_UIPlugInWebService { QTest::ignoreMessage(QtDebugMsg, "Request type: authentication"); - connect(mUi.data(), &UIPlugIn::fireWorkflowRequested, this, [this](const QSharedPointer& pRequest) + connect(mUi.data(), &UiPlugin::fireWorkflowRequested, this, [this](const QSharedPointer& pRequest) { const auto request = pRequest->getData().value>(); request->send(HTTP_STATUS_NO_CONTENT); // send something to avoid retry of Qt @@ -204,7 +205,7 @@ class test_UIPlugInWebService QTest::ignoreMessage(QtCriticalMsg, "Cannot send 'Processing' to caller as connection is lost"); HttpServerRequestor requestor; - QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla")); + QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla"_L1)); QVERIFY(reply); QCOMPARE(reply->error(), QNetworkReply::NoError); @@ -216,11 +217,11 @@ class test_UIPlugInWebService void authenticationAlreadyActive() { - connect(mUi.data(), &UIPlugIn::fireWorkflowRequested, mUi.data(), &UIPlugIn::onWorkflowUnhandled); + connect(mUi.data(), &UiPlugin::fireWorkflowRequested, mUi.data(), &UiPlugin::onWorkflowUnhandled); QTest::ignoreMessage(QtDebugMsg, "Request type: authentication"); HttpServerRequestor requestor; - QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla")); + QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?tctokenURL=bla"_L1)); QVERIFY(reply); QCOMPARE(reply->error(), QNetworkReply::ContentConflictError); @@ -230,10 +231,42 @@ class test_UIPlugInWebService } + void corsResponseOptions() + { + HttpServerRequestor requestor; + QSharedPointer reply = requestor.optionsRequest(getUrl("/eID-Client?tctokenURL=bla"_L1)); + QVERIFY(reply); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->readAll().size(), 0); + QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Origin")); + QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Private-Network")); + + QCOMPARE(mShowUiSpy->count(), 0); + QCOMPARE(mShowUserInfoSpy->count(), 0); + QCOMPARE(mAuthenticationSpy->count(), 0); + } + + + void corsResponseHead() + { + HttpServerRequestor requestor; + QSharedPointer reply = requestor.headRequest(getUrl("/eID-Client?tctokenURL=bla"_L1)); + QVERIFY(reply); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->readAll().size(), 0); + QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Origin")); + QVERIFY(reply->rawHeaderList().contains("Access-Control-Allow-Private-Network")); + + QCOMPARE(mShowUiSpy->count(), 0); + QCOMPARE(mShowUserInfoSpy->count(), 0); + QCOMPARE(mAuthenticationSpy->count(), 0); + } + + void unknownRequest() { HttpServerRequestor requestor; - QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?unknownRequest")); + QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?unknownRequest"_L1)); QVERIFY(reply); QCOMPARE(reply->error(), QNetworkReply::ContentNotFoundError); } @@ -242,7 +275,7 @@ class test_UIPlugInWebService void sameUserAgentVersion() { HttpServerRequestor requestor; - QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?ShowUI")); + QSharedPointer reply = requestor.getRequest(getUrl("/eID-Client?ShowUI"_L1)); QVERIFY(reply); QCOMPARE(reply->error(), QNetworkReply::NoError); @@ -259,8 +292,8 @@ class test_UIPlugInWebService { QTest::ignoreMessage(QtWarningMsg, "Current version is higher than caller version"); - QNetworkRequest request(getUrl("/eID-Client?ShowUI")); - request.setHeader(QNetworkRequest::UserAgentHeader, getUserAgentVersion("0.0.0")); + QNetworkRequest request(getUrl("/eID-Client?ShowUI"_L1)); + request.setHeader(QNetworkRequest::UserAgentHeader, getUserAgentVersion("0.0.0"_L1)); HttpServerRequestor requestor; QSharedPointer reply = requestor.getRequest(request); @@ -270,7 +303,7 @@ class test_UIPlugInWebService QCOMPARE(mAuthenticationSpy->count(), 0); QCOMPARE(mShowUiSpy->count(), 0); QCOMPARE(mShowUserInfoSpy->count(), 1); - QVERIFY(mShowUserInfoSpy->takeFirst().at(0).toString().contains("You tried to start an older version")); + QVERIFY(mShowUserInfoSpy->takeFirst().at(0).toString().contains("You tried to start an older version"_L1)); } @@ -278,8 +311,8 @@ class test_UIPlugInWebService { QTest::ignoreMessage(QtWarningMsg, "Current version is lower than caller version"); - QNetworkRequest request(getUrl("/eID-Client?ShowUI")); - request.setHeader(QNetworkRequest::UserAgentHeader, getUserAgentVersion("2.0.0")); + QNetworkRequest request(getUrl("/eID-Client?ShowUI"_L1)); + request.setHeader(QNetworkRequest::UserAgentHeader, getUserAgentVersion("2.0.0"_L1)); HttpServerRequestor requestor; QSharedPointer reply = requestor.getRequest(request); @@ -289,7 +322,7 @@ class test_UIPlugInWebService QCOMPARE(mAuthenticationSpy->count(), 0); QCOMPARE(mShowUiSpy->count(), 0); QCOMPARE(mShowUserInfoSpy->count(), 1); - QVERIFY(mShowUserInfoSpy->takeFirst().at(0).toString().contains("You tried to start a newer version")); + QVERIFY(mShowUserInfoSpy->takeFirst().at(0).toString().contains("You tried to start a newer version"_L1)); } @@ -298,10 +331,10 @@ class test_UIPlugInWebService QTest::addColumn("httpStatusCode"); QTest::addColumn("existingAppResult"); - QTest::newRow("timeout") << 0 << static_cast(UIPlugInWebService::ExistingAppResult::SHOWUI_TIMEOUT); - QTest::newRow("no-proxy") << 200 << static_cast(UIPlugInWebService::ExistingAppResult::SHOWUI_SUCCEED); - QTest::newRow("proxy-failed") << 502 << static_cast(UIPlugInWebService::ExistingAppResult::REBIND_FAILED); - QTest::newRow("proxy-succedd") << 502 << static_cast(UIPlugInWebService::ExistingAppResult::REBIND_SUCCEED); + QTest::newRow("timeout") << 0 << static_cast(UiPluginWebService::ExistingAppResult::SHOWUI_TIMEOUT); + QTest::newRow("no-proxy") << 200 << static_cast(UiPluginWebService::ExistingAppResult::SHOWUI_SUCCEED); + QTest::newRow("proxy-failed") << 502 << static_cast(UiPluginWebService::ExistingAppResult::REBIND_FAILED); + QTest::newRow("proxy-succedd") << 502 << static_cast(UiPluginWebService::ExistingAppResult::REBIND_SUCCEED); } @@ -309,7 +342,7 @@ class test_UIPlugInWebService { QFETCH(int, httpStatusCode); QFETCH(int, existingAppResult); - const auto existingAppResultType = static_cast(existingAppResult); + const auto existingAppResultType = static_cast(existingAppResult); const auto testAddress = HttpServer::cAddresses.constFirst(); QScopedValueRollback guard(HttpServer::cAddresses); @@ -317,18 +350,18 @@ class test_UIPlugInWebService MockNetworkManager networkManager; Env::set(NetworkManager::staticMetaObject, &networkManager); - if (existingAppResultType == UIPlugInWebService::ExistingAppResult::SHOWUI_TIMEOUT) + if (existingAppResultType == UiPluginWebService::ExistingAppResult::SHOWUI_TIMEOUT) { QTest::ignoreMessage(QtWarningMsg, "ShowUI request timed out"); } else { - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, httpStatusCode); reply->fireFinished(); networkManager.setNextReply(reply); - if (existingAppResultType == UIPlugInWebService::ExistingAppResult::REBIND_FAILED) + if (existingAppResultType == UiPluginWebService::ExistingAppResult::REBIND_FAILED) { HttpServer::cAddresses.clear(); } @@ -340,26 +373,26 @@ class test_UIPlugInWebService void test_GuessImageContentType_data() { - QTest::addColumn("fileName"); + QTest::addColumn("fileName"); QTest::addColumn("output"); - QTest::newRow("x-icon") << QString("test.ico") << QByteArrayLiteral("image/x-icon"); - QTest::newRow("X-ICON") << QString("test.iCo") << QByteArrayLiteral("image/x-icon"); - QTest::newRow("jpg") << QString("test.jpg") << QByteArrayLiteral("image/jpeg"); - QTest::newRow("JPG") << QString("test.JPG") << QByteArrayLiteral("image/jpeg"); - QTest::newRow("jpeg") << QString("test.jpeg") << QByteArrayLiteral("image/jpeg"); - QTest::newRow("JPEG") << QString("test.Jpeg") << QByteArrayLiteral("image/jpeg"); - QTest::newRow("png") << QString("test.png") << QByteArrayLiteral("image/png"); - QTest::newRow("PNG") << QString("test.pNG") << QByteArrayLiteral("image/png"); - QTest::newRow("svg") << QString("test.svg") << QByteArrayLiteral("image/svg+xml"); - QTest::newRow("SVG") << QString("TEST.SVG") << QByteArrayLiteral("image/svg+xml"); - QTest::newRow("other") << QString("test.test") << QByteArrayLiteral("image"); + QTest::newRow("x-icon") << QLatin1String("test.ico") << QByteArrayLiteral("image/x-icon"); + QTest::newRow("X-ICON") << QLatin1String("test.iCo") << QByteArrayLiteral("image/x-icon"); + QTest::newRow("jpg") << QLatin1String("test.jpg") << QByteArrayLiteral("image/jpeg"); + QTest::newRow("JPG") << QLatin1String("test.JPG") << QByteArrayLiteral("image/jpeg"); + QTest::newRow("jpeg") << QLatin1String("test.jpeg") << QByteArrayLiteral("image/jpeg"); + QTest::newRow("JPEG") << QLatin1String("test.Jpeg") << QByteArrayLiteral("image/jpeg"); + QTest::newRow("png") << QLatin1String("test.png") << QByteArrayLiteral("image/png"); + QTest::newRow("PNG") << QLatin1String("test.pNG") << QByteArrayLiteral("image/png"); + QTest::newRow("svg") << QLatin1String("test.svg") << QByteArrayLiteral("image/svg+xml"); + QTest::newRow("SVG") << QLatin1String("TEST.SVG") << QByteArrayLiteral("image/svg+xml"); + QTest::newRow("other") << QLatin1String("test.test") << QByteArrayLiteral("image"); } void test_GuessImageContentType() { - QFETCH(QString, fileName); + QFETCH(QLatin1String, fileName); QFETCH(QByteArray, output); QCOMPARE(mUi->guessImageContentType(fileName), output); @@ -368,5 +401,5 @@ class test_UIPlugInWebService }; -QTEST_GUILESS_MAIN(test_UIPlugInWebService) -#include "test_UIPlugInWebService.moc" +QTEST_GUILESS_MAIN(test_UiPluginWebService) +#include "test_UiPluginWebService.moc" diff --git a/test/qt/ui/webservice/test_UiPluginWebServiceBrowserHandler.cpp b/test/qt/ui/webservice/test_UiPluginWebServiceBrowserHandler.cpp new file mode 100644 index 000000000..f87f29575 --- /dev/null +++ b/test/qt/ui/webservice/test_UiPluginWebServiceBrowserHandler.cpp @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "UiPluginWebService.h" + +#include "MockSocket.h" +#include "ResourceLoader.h" +#include "WorkflowRequest.h" +#include "context/AuthContext.h" + +#include +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + +class test_UiPluginWebServiceBrowserHandler + : public QObject +{ + Q_OBJECT + QPointer mSocket; + QSharedPointer mRequest; + QSharedPointer mAuthContext; + + QByteArray split(const QByteArray& pData) + { + return pData.split('\r').at(0); + } + + private Q_SLOTS: + void initTestCase() + { + //QCoreApplication::setApplicationVersion("1.0.0"); + HttpServer::cPort = 0; + } + + + void init() + { + mSocket = new MockSocket(); + mSocket->setSocketState(QAbstractSocket::ConnectedState); + mRequest.reset(new HttpRequest(mSocket)); + mAuthContext.reset(new AuthContext(true, QUrl("http://activationUrl"_L1))); + + ResourceLoader::getInstance().init(); // html templates + } + + + void getActivationUrl() + { + mSocket->mReadBuffer = QByteArray("GET /testUrl HTTP/1.1\r\n" + "\r\n\r\n"); + Q_EMIT mSocket->readyRead(); + QCOMPARE(mRequest->getUrl().toEncoded(), QByteArray("/testUrl")); + + UiPluginWebService ui; + + QUrl url; + connect(&ui, &UiPlugin::fireWorkflowRequested, this, [&url](const QSharedPointer& pRequest){ + url = pRequest->getContext().objectCast()->getActivationUrl(); + }); + + ui.handleWorkflowRequest(mRequest); + QCOMPARE(url.toEncoded(), QByteArray("/testUrl")); + } + + + void connectionLost() + { + mSocket->setSocketState(QAbstractSocket::UnconnectedState); + UiPluginWebService ui; + + // lost for error page + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QLatin1String("The browser connection was lost.")); + + // lost for correct redirect + mAuthContext->setTcTokenNotFound(false); + mAuthContext->setRefreshUrl(QUrl("http://dummy?ResultMajor=ok"_L1)); + QTest::ignoreMessage(QtDebugMsg, "Perform redirect to URL: QUrl(\"http://dummy?ResultMajor=ok\")"); + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), "The connection to the browser was lost while redirecting to the provider (dummy). No automatic redirection could be performed."_L1); + } + + + void tcTokenNotFound() + { + UiPluginWebService ui; + mAuthContext->setTcTokenNotFound(true); + + QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 404"); + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); + QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 404 Not Found"); + } + + + void internalErrorBeforeTcToken() + { + UiPluginWebService ui; + mAuthContext->setStatus(GlobalStatus::Code::Workflow_InternalError_BeforeTcToken); + + QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 500"); + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); + QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 500 Internal Server Error"); + } + + + void emptyRefreshUrlNoTcToken() + { + UiPluginWebService ui; + mAuthContext->setTcTokenNotFound(false); + + QTest::ignoreMessage(QtDebugMsg, "Invalid redirect URL: QUrl(\"\")"); + QTest::ignoreMessage(QtDebugMsg, "Send error page to browser, error code 400"); + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); + QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 400 Bad Request"); + } + + + void sendRefreshUrl() + { + UiPluginWebService ui; + mAuthContext->setTcTokenNotFound(false); + mAuthContext->setRefreshUrl(QUrl("http://dummy?ResultMajor=ok"_L1)); + + QTest::ignoreMessage(QtDebugMsg, "Perform redirect to URL: QUrl(\"http://dummy?ResultMajor=ok\")"); + QCOMPARE(ui.sendRedirect(mRequest, mAuthContext), QString()); + QCOMPARE(split(mSocket->mWriteBuffer), "HTTP/1.0 303 See Other"); + QVERIFY(mSocket->mWriteBuffer.contains("Location: http://dummy?ResultMajor=ok")); + } + + +}; + +QTEST_GUILESS_MAIN(test_UiPluginWebServiceBrowserHandler) +#include "test_UiPluginWebServiceBrowserHandler.moc" diff --git a/test/qt/whitelist_client/test_SurveyModel.cpp b/test/qt/whitelist_client/test_SurveyModel.cpp deleted file mode 100644 index 340db1a05..000000000 --- a/test/qt/whitelist_client/test_SurveyModel.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany - */ - -#include "SurveyModel.h" - -#include "AppSettings.h" -#include "DeviceInfo.h" -#include "Env.h" -#include "MockNetworkManager.h" -#include "VolatileSettings.h" - -#include -#include - -using namespace governikus; - -Q_DECLARE_METATYPE(CardInfo::TagType) - -class test_SurveyModel - : public QObject -{ - Q_OBJECT - - private: - QSharedPointer mNetworkManager; - - void setReaderInfo(SurveyModel& model, ReaderManagerPlugInType readerPlugInType, CardInfo::TagType nfcTagType, int maxApduLength, bool hasEid = true) - { - CardInfo cardInfo(hasEid ? CardType::EID_CARD : CardType::NONE); - cardInfo.setTagType(nfcTagType); - ReaderInfo readerInfo("TestReader", readerPlugInType, cardInfo); - readerInfo.setMaxApduLength(maxApduLength); - model.setReaderInfo(readerInfo); - } - - private Q_SLOTS: - void init() - { - mNetworkManager.reset(new MockNetworkManager()); - Env::set(NetworkManager::staticMetaObject, mNetworkManager.data()); - } - - - void cleanup() - { - AbstractSettings::getStore()->clear(); - } - - - void testTransmitSurvey() - { - SurveyModel model; - - model.transmitSurvey(); - mNetworkManager->fireFinished(); - const QByteArray json = mNetworkManager->getLastData(); - auto result = QJsonDocument::fromJson(json); - - QVERIFY(result["Rom"].isObject()); - auto rom = result["Rom"].toObject(); - QVERIFY(rom["BuildNumber"].isString()); - QCOMPARE(rom["BuildNumber"].toString(), DeviceInfo::getOSBuildNumber()); - QVERIFY(rom["OsVersion"].isString()); - QCOMPARE(rom["OsVersion"].toString(), DeviceInfo::getOSVersion()); - QVERIFY(rom["KernelVersion"].isString()); - QCOMPARE(rom["KernelVersion"].toString(), DeviceInfo::getKernelVersion()); - QVERIFY(rom["MaximumNfcPacketLength"].isDouble()); - QCOMPARE(rom["MaximumNfcPacketLength"].toDouble(), 0); - - QVERIFY(result["Vendor"].isString()); - QCOMPARE(result["Vendor"].toString(), DeviceInfo::getVendor()); - QVERIFY(result["ModelNumber"].isString()); - QCOMPARE(result["ModelNumber"].toString(), DeviceInfo::getModelNumber()); - QVERIFY(result["ModelName"].isString()); - QCOMPARE(result["ModelName"].toString(), DeviceInfo::getModelName()); - QVERIFY(result["AusweisAppVersionNumber"].isString()); - QCOMPARE(result["AusweisAppVersionNumber"].toString(), QCoreApplication::applicationVersion()); - QVERIFY(result["NfcTagType"].isString()); - QCOMPARE(result["NfcTagType"].toString(), "U"); - } - - - void testOnCardInserted_data() - { - QTest::addColumn("usedAsSdk"); - QTest::addColumn("hasEid"); - QTest::addColumn("readerPlugInType"); - QTest::addColumn("nfcTagType"); - QTest::addColumn("maxNfcPacketLength"); - QTest::addColumn("authSuccessful"); - - QTest::addColumn("askForDeviceSurvey"); - QTest::addColumn("nfcTagTypeJson"); - QTest::addColumn("maxNfcPacketLengthJson"); - - QTest::addRow("Normal NFC_4A") << false << true << ReaderManagerPlugInType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << true << "A" << 9999.; - QTest::addRow("Normal NFC_4B") << false << true << ReaderManagerPlugInType::NFC << CardInfo::TagType::NFC_4B << 500 << true << true << "B" << 500.; - - QTest::addRow("Unknown NFC") << false << true << ReaderManagerPlugInType::NFC << CardInfo::TagType::UNKNOWN << 125 << true << true << "U" << 125.; - QTest::addRow("SDK") << true << true << ReaderManagerPlugInType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - QTest::addRow("No card") << false << false << ReaderManagerPlugInType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - - QTest::addRow("PCSC") << false << true << ReaderManagerPlugInType::PCSC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - QTest::addRow("REMOTE IFD") << false << true << ReaderManagerPlugInType::REMOTE_IFD << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - QTest::addRow("LOCAL IFD") << false << true << ReaderManagerPlugInType::LOCAL_IFD << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - QTest::addRow("SMART") << false << true << ReaderManagerPlugInType::SMART << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; - - QTest::addRow("Auth Error") << false << true << ReaderManagerPlugInType::NFC << CardInfo::TagType::NFC_4A << 9999 << false << false << "A" << 9999.; - } - - - void testOnCardInserted() - { - QFETCH(bool, usedAsSdk); - QFETCH(bool, hasEid); - QFETCH(ReaderManagerPlugInType, readerPlugInType); - QFETCH(CardInfo::TagType, nfcTagType); - QFETCH(int, maxNfcPacketLength); - QFETCH(bool, authSuccessful); - - QFETCH(bool, askForDeviceSurvey); - QFETCH(QString, nfcTagTypeJson); - QFETCH(double, maxNfcPacketLengthJson); - - SDK_MODE(usedAsSdk); - - SurveyModel model; - - model.transmitSurvey(); - mNetworkManager->fireFinished(); - QByteArray json = mNetworkManager->getLastData(); - auto result = QJsonDocument::fromJson(json); - auto rom = result["Rom"].toObject(); - QCOMPARE(rom["MaximumNfcPacketLength"].toDouble(), 0); - QCOMPARE(result["NfcTagType"].toString(), "U"); - QCOMPARE(model.askForDeviceSurvey(), false); - - setReaderInfo(model, readerPlugInType, nfcTagType, maxNfcPacketLength, hasEid); - model.setAuthWasSuccessful(authSuccessful); - - QCOMPARE(model.askForDeviceSurvey(), askForDeviceSurvey); - - Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(true); - - QCOMPARE(model.askForDeviceSurvey(), false); - - model.transmitSurvey(); - mNetworkManager->fireFinished(); - json = mNetworkManager->getLastData(); - result = QJsonDocument::fromJson(json); - rom = result["Rom"].toObject(); - QCOMPARE(model.isDeviceSurveyPending(), askForDeviceSurvey); - QCOMPARE(rom["MaximumNfcPacketLength"].toDouble(), maxNfcPacketLengthJson); - QCOMPARE(result["NfcTagType"].toString(), nfcTagTypeJson); - } - - - void testResetNfc() - { - Env::getSingleton()->setUsedAsSDK(false); - - SurveyModel model; - - model.setAuthWasSuccessful(true); - setReaderInfo(model, ReaderManagerPlugInType::NFC, CardInfo::TagType::NFC_4A, 9999); - - model.resetNfcData(); - - model.transmitSurvey(); - mNetworkManager->fireFinished(); - QByteArray json = mNetworkManager->getLastData(); - auto result = QJsonDocument::fromJson(json); - auto rom = result["Rom"].toObject(); - QCOMPARE(model.askForDeviceSurvey(), false); - QCOMPARE(rom["MaximumNfcPacketLength"].toDouble(), 0); - QCOMPARE(result["NfcTagType"].toString(), "U"); - } - - - void test_DeclineDeviceSurvey() - { - Env::getSingleton()->setUsedAsSDK(false); - - SurveyModel model; - - setReaderInfo(model, ReaderManagerPlugInType::NFC, CardInfo::TagType::NFC_4A, 9999); - model.setAuthWasSuccessful(true); - - QCOMPARE(model.askForDeviceSurvey(), true); - - Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(false); - - QCOMPARE(model.askForDeviceSurvey(), false); - QCOMPARE(model.isDeviceSurveyPending(), false); - } - - -}; - -QTEST_GUILESS_MAIN(test_SurveyModel) -#include "test_SurveyModel.moc" diff --git a/test/qt/workflows/context/test_AccessRightManager.cpp b/test/qt/workflows/context/test_AccessRightManager.cpp index 1bb132eca..f1dc497c7 100644 --- a/test/qt/workflows/context/test_AccessRightManager.cpp +++ b/test/qt/workflows/context/test_AccessRightManager.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,6 +15,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -66,7 +67,7 @@ class test_AccessRightManager { Env::getSingleton()->setUsedAsSDK(false); - mTestAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_accessRightsEmpty.xml")); + mTestAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_accessRightsEmpty.xml"_L1)); mEac1Changed.reset(new QSignalSpy(mTestAuthContext.data(), &AuthContext::fireDidAuthenticateEac1Changed)); mARMCreated.reset(new QSignalSpy(mTestAuthContext.data(), &AuthContext::fireAccessRightManagerCreated)); } @@ -81,7 +82,7 @@ class test_AccessRightManager void test_AuthContext_00() { - TestAuthContext context(":/paos/DIDAuthenticateEAC1_accessRightsMissing.xml"); + TestAuthContext context(":/paos/DIDAuthenticateEAC1_accessRightsMissing.xml"_L1); QCOMPARE(context.getAccessRightManager()->getRequiredAccessRights().size(), 0); QCOMPARE(context.getAccessRightManager()->getOptionalAccessRights().size(), 16); QCOMPARE(context.getAccessRightManager()->getEffectiveAccessRights().size(), 16); @@ -91,7 +92,7 @@ class test_AccessRightManager void test_AuthContext_01() { // Empty after creation - checkChatSizes("01-01", 0, 0, 0); + checkChatSizes("01-01"_L1, 0, 0, 0); } @@ -99,21 +100,21 @@ class test_AccessRightManager { // Try to set required right that is not in cvc mTestAuthContext->setRequiredAccessRights({AccessRight::READ_DG21}); - checkChatSizes("02-01", 0, 0, 0); - checkAndClearSignals("02-02", 1); + checkChatSizes("02-01"_L1, 0, 0, 0); + checkAndClearSignals("02-02"_L1, 1); // Try to set optional right that is not in cvc mTestAuthContext->setOptionalAccessRights({AccessRight::READ_DG21}); - checkChatSizes("02-03", 0, 0, 0); - checkAndClearSignals("02-04", 1); + checkChatSizes("02-03"_L1, 0, 0, 0); + checkAndClearSignals("02-04"_L1, 1); // Try to set a right in required and optional mTestAuthContext->setOptionalAccessRights({AccessRight::READ_DG05}); - checkChatSizes("02-05", 0, 1, 1); - checkAndClearSignals("02-06", 1); + checkChatSizes("02-05"_L1, 0, 1, 1); + checkAndClearSignals("02-06"_L1, 1); mTestAuthContext->setRequiredAccessRights({AccessRight::READ_DG05}); - checkChatSizes("02-07", 1, 0, 1); - checkAndClearSignals("02-08", 1); + checkChatSizes("02-07"_L1, 1, 0, 1); + checkAndClearSignals("02-08"_L1, 1); } @@ -121,13 +122,13 @@ class test_AccessRightManager { mTestAuthContext->setOptionalAccessRights({AccessRight::READ_DG05}); mTestAuthContext->setRequiredAccessRights({AccessRight::READ_DG06}); - checkChatSizes("03-01", 1, 1, 2); - checkAndClearSignals("03-02", 2); + checkChatSizes("03-01"_L1, 1, 1, 2); + checkAndClearSignals("03-02"_L1, 2); // Clear effective access rights *mTestAuthContext->getAccessRightManager() = {}; - checkChatSizes("03-03", 1, 1, 1); - checkAndClearSignals("03-04", 0); + checkChatSizes("03-03"_L1, 1, 1, 1); + checkAndClearSignals("03-04"_L1, 0); } @@ -135,44 +136,44 @@ class test_AccessRightManager { // Set only one access right as optional, required access rights remain empty mTestAuthContext->setOptionalAccessRights({AccessRight::READ_DG05}); - checkChatSizes("04-01", 0, 1, 1); + checkChatSizes("04-01"_L1, 0, 1, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-02", 1); + checkAndClearSignals("04-02"_L1, 1); // Try to set an optional access right that is already set *mTestAuthContext->getAccessRightManager() += AccessRight::READ_DG05; - checkChatSizes("04-03", 0, 1, 1); + checkChatSizes("04-03"_L1, 0, 1, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-04", 0); + checkAndClearSignals("04-04"_L1, 0); // Try to remove an optional access right *mTestAuthContext->getAccessRightManager() -= AccessRight::READ_DG05; - checkChatSizes("04-05", 0, 1, 0); + checkChatSizes("04-05"_L1, 0, 1, 0); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-06", 0); + checkAndClearSignals("04-06"_L1, 0); // Try to remove an optional access right that is not set *mTestAuthContext->getAccessRightManager() -= AccessRight::READ_DG05; - checkChatSizes("04-07", 0, 1, 0); + checkChatSizes("04-07"_L1, 0, 1, 0); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-08", 0); + checkAndClearSignals("04-08"_L1, 0); // Try to set an optional access right *mTestAuthContext->getAccessRightManager() += AccessRight::READ_DG05; - checkChatSizes("04-09", 0, 1, 1); + checkChatSizes("04-09"_L1, 0, 1, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-10", 0); + checkAndClearSignals("04-10"_L1, 0); // Try to set an access right that is not included in optional or required access rights QTest::ignoreMessage(QtWarningMsg, "Adding AGE_VERIFICATION to effective chat is not allowed"); *mTestAuthContext->getAccessRightManager() += AccessRight::AGE_VERIFICATION; - checkChatSizes("04-11", 0, 1, 1); + checkChatSizes("04-11"_L1, 0, 1, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getOptionalAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("04-12", 0); + checkAndClearSignals("04-12"_L1, 0); } @@ -180,38 +181,38 @@ class test_AccessRightManager { // Set only one access right as required, optional access rights remain empty mTestAuthContext->setRequiredAccessRights({AccessRight::READ_DG05}); - checkChatSizes("05-01", 1, 0, 1); + checkChatSizes("05-01"_L1, 1, 0, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getRequiredAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("05-02", 1); + checkAndClearSignals("05-02"_L1, 1); // Try to set an required access right that is already set *mTestAuthContext->getAccessRightManager() += AccessRight::READ_DG05; - checkChatSizes("05-03", 1, 0, 1); + checkChatSizes("05-03"_L1, 1, 0, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getRequiredAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("05-04", 0); + checkAndClearSignals("05-04"_L1, 0); // Try to remove an required access right QTest::ignoreMessage(QtWarningMsg, "Removing READ_DG05 from effective chat is not allowed"); *mTestAuthContext->getAccessRightManager() -= AccessRight::READ_DG05; - checkChatSizes("05-05", 1, 0, 1); + checkChatSizes("05-05"_L1, 1, 0, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getRequiredAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("05-06", 0); + checkAndClearSignals("05-06"_L1, 0); // Try to remove an access right that is not included in optional or required access rights *mTestAuthContext->getAccessRightManager() -= AccessRight::AGE_VERIFICATION; - checkChatSizes("05-07", 1, 0, 1); + checkChatSizes("05-07"_L1, 1, 0, 1); QVERIFY(mTestAuthContext->getAccessRightManager()->getRequiredAccessRights().contains(AccessRight::READ_DG05)); QVERIFY(mTestAuthContext->getAccessRightManager()->getEffectiveAccessRights().contains(AccessRight::READ_DG05)); - checkAndClearSignals("05-08", 0); + checkAndClearSignals("05-08"_L1, 0); } void test_Testbed_C2_01() { - TestAuthContext context(":/testbed/DIDAuthenticateEAC1_C2_01.xml"); + TestAuthContext context(":/testbed/DIDAuthenticateEAC1_C2_01.xml"_L1); *context.getAccessRightManager() -= AccessRight::CAN_ALLOWED; QVERIFY(context.encodeEffectiveChat().toHex().endsWith("3c0f13ffe4")); } @@ -219,7 +220,7 @@ class test_AccessRightManager void test_Testbed_C2_02() { - TestAuthContext context(":/testbed/DIDAuthenticateEAC1_C2_02.xml"); + TestAuthContext context(":/testbed/DIDAuthenticateEAC1_C2_02.xml"_L1); *context.getAccessRightManager() = {}; QVERIFY(context.encodeEffectiveChat().toHex().endsWith("0000000000")); } diff --git a/test/qt/workflows/context/test_AuthContext.cpp b/test/qt/workflows/context/test_AuthContext.cpp index 4245e262b..0b36a328f 100644 --- a/test/qt/workflows/context/test_AuthContext.cpp +++ b/test/qt/workflows/context/test_AuthContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,12 +10,15 @@ #include "AppSettings.h" #include "TestAuthContext.h" +#include "TestFileHelper.h" #include "VolatileSettings.h" +#include "paos/retrieve/DidAuthenticateEac1Parser.h" #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -25,6 +28,68 @@ class test_AuthContext Q_OBJECT private Q_SLOTS: + void test_ReceivedBrowserSendFailed() + { + AuthContext context; + QSignalSpy spy(&context, &AuthContext::fireResultChanged); + + QCOMPARE(context.isReceivedBrowserSendFailed(), false); + + context.setReceivedBrowserSendFailed(true); + QCOMPARE(spy.size(), 1); + QCOMPARE(context.isReceivedBrowserSendFailed(), true); + + context.setReceivedBrowserSendFailed(true); + QCOMPARE(spy.size(), 1); + QCOMPARE(context.isReceivedBrowserSendFailed(), true); + + context.setReceivedBrowserSendFailed(false); + QCOMPARE(spy.size(), 2); + QCOMPARE(context.isReceivedBrowserSendFailed(), false); + + context.setReceivedBrowserSendFailed(false); + QCOMPARE(spy.size(), 2); + QCOMPARE(context.isReceivedBrowserSendFailed(), false); + } + + + void test_requestChangePinView() + { + AuthContext context; + QSignalSpy spy(&context, &AuthContext::fireShowChangePinViewChanged); + + QCOMPARE(context.isSkipMobileRedirect(), false); + + context.requestChangePinView(); + QCOMPARE(spy.size(), 1); + QCOMPARE(context.isSkipMobileRedirect(), true); + + context.requestChangePinView(); + QCOMPARE(spy.size(), 1); + QCOMPARE(context.isSkipMobileRedirect(), true); + } + + + void test_acceptedEidTypes() + { + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_template.xml"_L1); + content = content.replace(QByteArray(""), QByteArray("SECertified")); + QSharedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); + + AuthContext context; + QCOMPARE(context.getAcceptedEidTypes(), {AcceptedEidType::CARD_CERTIFIED}); + + context.setDidAuthenticateEac1(eac1); + QCOMPARE(context.getAcceptedEidTypes(), {AcceptedEidType::SE_CERTIFIED}); + + context.initAccessRightManager(TestAuthContext::getTerminalCvc(eac1)); + QCOMPARE(context.getAcceptedEidTypes(), {AcceptedEidType::CARD_CERTIFIED}); + + context.setDidAuthenticateEac1(nullptr); + QCOMPARE(context.getAcceptedEidTypes(), {AcceptedEidType::CARD_CERTIFIED}); + } + + void test_CanAllowed_data() { QTest::addColumn("usedAsSdk"); @@ -46,7 +111,7 @@ class test_AuthContext Env::getSingleton()->setUsedAsSDK(usedAsSdk); Env::getSingleton()->getGeneralSettings().setEnableCanAllowed(enabled); - TestAuthContext context(":/paos/DIDAuthenticateEAC1.xml"); + TestAuthContext context(":/paos/DIDAuthenticateEAC1.xml"_L1); Env::getSingleton()->getGeneralSettings().setEnableCanAllowed(false); Env::getSingleton()->setUsedAsSDK(false); QSignalSpy spy(&context, &TestAuthContext::fireCanAllowedModeChanged); @@ -180,9 +245,9 @@ class test_AuthContext AuthContext context; QCOMPARE(context.getCertificateList().size(), 0); - context.addCertificateData(QUrl("https://governikus.de"), QSslCertificate()); + context.addCertificateData(QUrl("https://governikus.de"_L1), QSslCertificate()); QCOMPARE(context.getCertificateList().size(), 1); - context.addCertificateData(QUrl("https://governikus.de"), QSslCertificate()); + context.addCertificateData(QUrl("https://governikus.de"_L1), QSslCertificate()); QCOMPARE(context.getCertificateList().size(), 2); } diff --git a/test/qt/workflows/context/test_ChangePinContext.cpp b/test/qt/workflows/context/test_ChangePinContext.cpp index 1a59ba0a0..d10e4f098 100644 --- a/test/qt/workflows/context/test_ChangePinContext.cpp +++ b/test/qt/workflows/context/test_ChangePinContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/workflows/context/test_WorkflowContext.cpp b/test/qt/workflows/context/test_WorkflowContext.cpp index c442272b3..338e9bea6 100644 --- a/test/qt/workflows/context/test_WorkflowContext.cpp +++ b/test/qt/workflows/context/test_WorkflowContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "context/WorkflowContext.h" @@ -10,7 +10,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -21,13 +21,13 @@ class test_WorkflowContext QSharedPointer mContext; private: - QVector allow_all_types() + QList allow_all_types() { - return QVector({AcceptedEidType::CARD_CERTIFIED, AcceptedEidType::HW_KEYSTORE, AcceptedEidType::SE_CERTIFIED, AcceptedEidType::SE_ENDORSED}); + return QList({AcceptedEidType::CARD_CERTIFIED, AcceptedEidType::HW_KEYSTORE, AcceptedEidType::SE_CERTIFIED, AcceptedEidType::SE_ENDORSED}); } - QVector allow_all_types_but(const AcceptedEidType& pType) + QList allow_all_types_but(const AcceptedEidType& pType) { auto types = allow_all_types(); types.removeOne(pType); @@ -35,15 +35,15 @@ class test_WorkflowContext } - QVector allow_only(std::initializer_list pTypes) + QList allow_only(std::initializer_list pTypes) { - return QVector(pTypes); + return QList(pTypes); } QSharedPointer createCardConnection(CardType pCardType) { - auto readerInfo = ReaderInfo("reader", ReaderManagerPlugInType::UNKNOWN, CardInfo(pCardType)); + auto readerInfo = ReaderInfo("reader"_L1, ReaderManagerPluginType::UNKNOWN, CardInfo(pCardType)); return QSharedPointer(new MockCardConnection(readerInfo)); } @@ -134,16 +134,6 @@ class test_WorkflowContext } - void test_ErrorReportToUser() - { - mContext->setErrorReportedToUser(true); - QVERIFY(mContext->isErrorReportedToUser()); - - mContext->setErrorReportedToUser(false); - QVERIFY(!mContext->isErrorReportedToUser()); - } - - void test_CurrentState() { const QString state1 = QStringLiteral("state1"); @@ -167,19 +157,19 @@ class test_WorkflowContext } - void test_ReaderPlugInTypes() + void test_ReaderPluginTypes() { - QVector vector1({ReaderManagerPlugInType::PCSC}); - QVector vector2({ReaderManagerPlugInType::REMOTE_IFD}); - QSignalSpy spy(mContext.data(), &WorkflowContext::fireReaderPlugInTypesChanged); + QList vector1({ReaderManagerPluginType::PCSC}); + QList vector2({ReaderManagerPluginType::REMOTE_IFD}); + QSignalSpy spy(mContext.data(), &WorkflowContext::fireReaderPluginTypesChanged); - mContext->setReaderPlugInTypes(vector1); - QCOMPARE(mContext->getReaderPlugInTypes(), vector1); + mContext->setReaderPluginTypes(vector1); + QCOMPARE(mContext->getReaderPluginTypes(), vector1); QCOMPARE(spy.count(), 1); spy.clear(); - mContext->setReaderPlugInTypes(vector2); - QCOMPARE(mContext->getReaderPlugInTypes(), vector2); + mContext->setReaderPluginTypes(vector2); + QCOMPARE(mContext->getReaderPluginTypes(), vector2); QCOMPARE(spy.count(), 1); } @@ -229,13 +219,13 @@ class test_WorkflowContext mContext->setCardConnection(QSharedPointer::create(worker)); QVERIFY(!mContext->isPinBlocked()); - const CardInfo cardInfo1(CardType::EID_CARD, QSharedPointer(), 3, false, false); - const ReaderInfo readerInfo1(QString(), ReaderManagerPlugInType::UNKNOWN, cardInfo1); + const CardInfo cardInfo1(CardType::EID_CARD, FileRef(), QSharedPointer(), 3, false, false); + const ReaderInfo readerInfo1(QString(), ReaderManagerPluginType::UNKNOWN, cardInfo1); Q_EMIT worker->fireReaderInfoChanged(readerInfo1); QVERIFY(!mContext->isPinBlocked()); - const CardInfo cardInfo2(CardType::EID_CARD, QSharedPointer(), 0, false, false); - const ReaderInfo readerInfo2(QString(), ReaderManagerPlugInType::UNKNOWN, cardInfo2); + const CardInfo cardInfo2(CardType::EID_CARD, FileRef(), QSharedPointer(), 0, false, false); + const ReaderInfo readerInfo2(QString(), ReaderManagerPluginType::UNKNOWN, cardInfo2); Q_EMIT worker->fireReaderInfoChanged(readerInfo2); QVERIFY(mContext->isPinBlocked()); } @@ -303,13 +293,13 @@ class test_WorkflowContext void test_eidTypeMismatch_data() { QTest::addColumn>("cardConnection"); - QTest::addColumn>("acceptedTypes"); + QTest::addColumn>("acceptedTypes"); QTest::addColumn("result"); - QTest::addRow("No error when no cardconnection 1") << QSharedPointer() << QVector() << false; + QTest::addRow("No error when no cardconnection 1") << QSharedPointer() << QList() << false; QTest::addRow("No error when no cardconnection 2") << QSharedPointer() << allow_all_types() << false; - QTest::addRow("No error when no card") << createCardConnection(CardType::NONE) << QVector() << false; + QTest::addRow("No error when no card") << createCardConnection(CardType::NONE) << QList() << false; QTest::addRow("ID card allowed") << createCardConnection(CardType::EID_CARD) << allow_all_types() << false; QTest::addRow("ID card not allowed") << createCardConnection(CardType::EID_CARD) << allow_all_types_but(AcceptedEidType::CARD_CERTIFIED) << true; @@ -321,7 +311,7 @@ class test_WorkflowContext void test_eidTypeMismatch() { QFETCH(QSharedPointer, cardConnection); - QFETCH(QVector, acceptedTypes); + QFETCH(QList, acceptedTypes); QFETCH(bool, result); mContext->setAcceptedEidTypes(acceptedTypes); @@ -334,7 +324,7 @@ class test_WorkflowContext void test_isMobileEidTypeAllowed_data() { QTest::addColumn("mobileEidType"); - QTest::addColumn>("acceptedTypes"); + QTest::addColumn>("acceptedTypes"); QTest::addColumn("result"); QTest::addRow("UNKNOWN not allowed") << MobileEidType::UNKNOWN << allow_all_types() << false; @@ -357,7 +347,7 @@ class test_WorkflowContext void test_isMobileEidTypeAllowed() { QFETCH(MobileEidType, mobileEidType); - QFETCH(QVector, acceptedTypes); + QFETCH(QList, acceptedTypes); QFETCH(bool, result); mContext->setAcceptedEidTypes(acceptedTypes); @@ -366,6 +356,14 @@ class test_WorkflowContext } + void test_setInitialInputErrorShown() + { + QVERIFY(!mContext->isInitialInputErrorShown()); + mContext->setInitialInputErrorShown(); + QVERIFY(mContext->isInitialInputErrorShown()); + } + + }; QTEST_GUILESS_MAIN(test_WorkflowContext) diff --git a/test/qt/workflows/ifd/test_IfdServiceContext.cpp b/test/qt/workflows/ifd/test_IfdServiceContext.cpp index 398df8514..617de0b0a 100644 --- a/test/qt/workflows/ifd/test_IfdServiceContext.cpp +++ b/test/qt/workflows/ifd/test_IfdServiceContext.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,7 +13,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -65,7 +65,7 @@ class test_IfdServiceContext void test_ModifyPinMessage() { IfdServiceContext context(mIfdServer); - const QSharedPointer message(new IfdModifyPin(QString("message"), QByteArray("message"))); + const QSharedPointer message(new IfdModifyPin("message"_L1, QByteArray("message"))); const QSharedPointer emptyMessage(new IfdModifyPin(QString(), QByteArray())); context.setModifyPinMessage(message); @@ -95,7 +95,7 @@ class test_IfdServiceContext void test_EstablishPaceChannelMessage() { IfdServiceContext context(mIfdServer); - const QSharedPointer message(new IfdEstablishPaceChannel(QString("SlotHandle"), EstablishPaceChannel(), 6)); + const QSharedPointer message(new IfdEstablishPaceChannel("SlotHandle"_L1, EstablishPaceChannel(), 6)); context.setEstablishPaceChannel(message); QVERIFY(!context.getSlotHandle().isEmpty()); @@ -169,6 +169,17 @@ class test_IfdServiceContext } + void test_UserError() + { + IfdServiceContext context(mIfdServer); + QSignalSpy spy(&context, &IfdServiceContext::fireUserError); + + context.userError(StatusCode::INPUT_TIMEOUT); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).value(), StatusCode::INPUT_TIMEOUT); + } + + void test_PinLength_data() { QTest::addColumn("inputData"); diff --git a/test/qt/workflows/ifd/test_StateChangePinIfd.cpp b/test/qt/workflows/ifd/test_StateChangePinIfd.cpp index d4d8b8102..e5b8e824c 100644 --- a/test/qt/workflows/ifd/test_StateChangePinIfd.cpp +++ b/test/qt/workflows/ifd/test_StateChangePinIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateChangePinIfd.h" diff --git a/test/qt/workflows/ifd/test_StateEnterNewPacePinIfd.cpp b/test/qt/workflows/ifd/test_StateEnterNewPacePinIfd.cpp new file mode 100644 index 000000000..335de1f88 --- /dev/null +++ b/test/qt/workflows/ifd/test_StateEnterNewPacePinIfd.cpp @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "states/StateEnterNewPacePinIfd.h" + +#include "context/IfdServiceContext.h" +#include "states/StateBuilder.h" + +#include "MockIfdServer.h" + +#include + + +using namespace governikus; + + +class test_StateEnterNewPacePinIfd + : public QObject +{ + Q_OBJECT + QSharedPointer mIfdServer; + QSharedPointer mContext; + QSharedPointer mState; + + private Q_SLOTS: + void init() + { + mIfdServer.reset(new MockIfdServer()); + mContext.reset(new IfdServiceContext(mIfdServer)); + mState.reset(StateBuilder::createState(mContext)); + } + + + void cleanup() + { + mState.clear(); + mContext.clear(); + mIfdServer.clear(); + } + + + void test_onEntry() + { + QSignalSpy spyAbort(mState.data(), &AbstractState::fireAbort); + + mState->onEntry(nullptr); + QCOMPARE(spyAbort.count(), 0); + QVERIFY(mContext->getModifyPinMessageResponseApdu().isEmpty()); + + Q_EMIT mContext->fireUserError(StatusCode::FILE_NOT_FOUND); + QCOMPARE(spyAbort.count(), 1); + QCOMPARE(mContext->getModifyPinMessageResponseApdu().getStatusCode(), StatusCode::FILE_NOT_FOUND); + spyAbort.clear(); + + Q_EMIT mIfdServer->getMessageHandler()->destroyed(); + QCOMPARE(spyAbort.count(), 1); + QCOMPARE(mContext->getModifyPinMessageResponseApdu().getStatusCode(), StatusCode::INPUT_CANCELLED); + } + + +}; + +QTEST_GUILESS_MAIN(test_StateEnterNewPacePinIfd) +#include "test_StateEnterNewPacePinIfd.moc" diff --git a/test/qt/workflows/ifd/test_StateEnterPacePasswordIfd.cpp b/test/qt/workflows/ifd/test_StateEnterPacePasswordIfd.cpp new file mode 100644 index 000000000..8a67db692 --- /dev/null +++ b/test/qt/workflows/ifd/test_StateEnterPacePasswordIfd.cpp @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "states/StateEnterPacePasswordIfd.h" + +#include "context/IfdServiceContext.h" +#include "states/StateBuilder.h" + +#include "MockIfdServer.h" + +#include + + +using namespace governikus; + + +class test_StateEnterPacePasswordIfd + : public QObject +{ + Q_OBJECT + QSharedPointer mIfdServer; + QSharedPointer mContext; + QSharedPointer mState; + + private Q_SLOTS: + void init() + { + mIfdServer.reset(new MockIfdServer()); + mContext.reset(new IfdServiceContext(mIfdServer)); + mState.reset(StateBuilder::createState(mContext)); + } + + + void cleanup() + { + mState.clear(); + mContext.clear(); + mIfdServer.clear(); + } + + + void test_onEntry() + { + QSignalSpy spyAbort(mState.data(), &AbstractState::fireAbort); + + mState->onEntry(nullptr); + QCOMPARE(spyAbort.count(), 0); + QVERIFY(mContext->getModifyPinMessageResponseApdu().isEmpty()); + + Q_EMIT mContext->fireUserError(StatusCode::FILE_NOT_FOUND); + QCOMPARE(spyAbort.count(), 1); + QCOMPARE(mContext->getEstablishPaceChannelOutput().getPaceReturnCode(), CardReturnCode::CANCELLATION_BY_USER); + spyAbort.clear(); + + Q_EMIT mIfdServer->getMessageHandler()->destroyed(); + QCOMPARE(spyAbort.count(), 1); + QCOMPARE(mContext->getEstablishPaceChannelOutput().getPaceReturnCode(), CardReturnCode::CANCELLATION_BY_USER); + } + + +}; + +QTEST_GUILESS_MAIN(test_StateEnterPacePasswordIfd) +#include "test_StateEnterPacePasswordIfd.moc" diff --git a/test/qt/workflows/ifd/test_StateEstablishPaceChannelIfd.cpp b/test/qt/workflows/ifd/test_StateEstablishPaceChannelIfd.cpp index e76da65e2..27275512e 100644 --- a/test/qt/workflows/ifd/test_StateEstablishPaceChannelIfd.cpp +++ b/test/qt/workflows/ifd/test_StateEstablishPaceChannelIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateEstablishPaceChannelIfd.h" @@ -12,7 +12,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockEstablishPaceChannelCommand @@ -71,7 +71,7 @@ class test_StateEstablishPaceChannelIfd void test_RunNoCardConnection() { - const QSharedPointer message(new IfdEstablishPaceChannel("SlotHandle", EstablishPaceChannel(), 6)); + const QSharedPointer message(new IfdEstablishPaceChannel("SlotHandle"_L1, EstablishPaceChannel(), 6)); mContext->setEstablishPaceChannel(message); QSignalSpy spy(mState.data(), &StateEstablishPaceChannelIfd::fireContinue); @@ -83,12 +83,12 @@ class test_StateEstablishPaceChannelIfd void test_Run() { EstablishPaceChannel establishPaceChannel(PacePasswordId::PACE_PIN); - const QSharedPointer message(new IfdEstablishPaceChannel("SlotHandle", establishPaceChannel, 6)); + const QSharedPointer message(new IfdEstablishPaceChannel("SlotHandle"_L1, establishPaceChannel, 6)); mContext->setEstablishPaceChannel(message); mWorker->moveToThread(&mThread); const QSharedPointer connection(new CardConnection(mWorker)); mContext->setCardConnection(connection); - mContext->setPin("0000"); + mContext->setPin("0000"_L1); mState->run(); QCOMPARE(mState->mConnections.size(), 1); diff --git a/test/qt/workflows/ifd/test_StateEstablishPaceChannelResponse.cpp b/test/qt/workflows/ifd/test_StateEstablishPaceChannelResponse.cpp index 7c4d9456d..d36bddc9b 100644 --- a/test/qt/workflows/ifd/test_StateEstablishPaceChannelResponse.cpp +++ b/test/qt/workflows/ifd/test_StateEstablishPaceChannelResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateEstablishPaceChannelResponse.h" @@ -11,6 +11,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockServerMsgHandler @@ -41,7 +42,7 @@ class MockServerMsgHandler } - void setAllowedCardTypes(const QVector& pAllowedCardTypes) override + void setAllowedCardTypes(const QList& pAllowedCardTypes) override { Q_UNUSED(pAllowedCardTypes) } @@ -112,7 +113,7 @@ class test_StateEstablishPaceChannelResponse QSignalSpy spyWrongPacePassword(mState.data(), &StateEstablishPaceChannelResponse::fireWrongPacePassword); QSignalSpy spyContinue(mState.data(), &StateEstablishPaceChannelResponse::fireContinue); - const QString slotHandle("slot handle"); + const QString slotHandle("slot handle"_L1); const QSharedPointer msg(new IfdEstablishPaceChannel(slotHandle, EstablishPaceChannel(), 6)); mContext->setEstablishPaceChannel(msg); EstablishPaceChannelOutput channelOutput; diff --git a/test/qt/workflows/ifd/test_StatePreparePaceIfd.cpp b/test/qt/workflows/ifd/test_StatePreparePaceIfd.cpp index 214a445ab..1eed475bf 100644 --- a/test/qt/workflows/ifd/test_StatePreparePaceIfd.cpp +++ b/test/qt/workflows/ifd/test_StatePreparePaceIfd.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StatePreparePaceIfd.h" @@ -10,7 +10,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StatePreparePaceIfd @@ -23,7 +23,7 @@ class test_StatePreparePaceIfd static QSharedPointer createMessage(PacePasswordId pId) { EstablishPaceChannel establishPaceChannel(pId); - return QSharedPointer(new IfdEstablishPaceChannel("slot", establishPaceChannel, 6)); + return QSharedPointer(new IfdEstablishPaceChannel("slot"_L1, establishPaceChannel, 6)); } private Q_SLOTS: @@ -55,7 +55,7 @@ class test_StatePreparePaceIfd QTRY_COMPARE(spyEnterPacePassword.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(spyContinue.count(), 0); - mContext->setPin(QString("111111")); + mContext->setPin("111111"_L1); mContext->setStateApproved(false); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations @@ -73,7 +73,7 @@ class test_StatePreparePaceIfd QTRY_COMPARE(spyEnterPacePassword.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(spyContinue.count(), 0); - mContext->setCan(QString("111111")); + mContext->setCan("111111"_L1); mContext->setStateApproved(false); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations @@ -91,7 +91,7 @@ class test_StatePreparePaceIfd QTRY_COMPARE(spyEnterPacePassword.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(spyContinue.count(), 0); - mContext->setPuk(QString("111111")); + mContext->setPuk("111111"_L1); mContext->setStateApproved(false); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/workflows/ifd/test_StateProcessIfdMessages.cpp b/test/qt/workflows/ifd/test_StateProcessIfdMessages.cpp index 9265c6baa..1f042a9dc 100644 --- a/test/qt/workflows/ifd/test_StateProcessIfdMessages.cpp +++ b/test/qt/workflows/ifd/test_StateProcessIfdMessages.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateProcessIfdMessages.h" @@ -13,7 +13,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StateProcessIfdMessages @@ -71,7 +71,7 @@ class test_StateProcessIfdMessages const QSharedPointer context(new IfdServiceContext(mIfdServer)); StateProcessIfdMessages state(context); - const QSharedPointer message(new IfdEstablishPaceChannel("test", establishPaceChannel, 6)); + const QSharedPointer message(new IfdEstablishPaceChannel("test"_L1, establishPaceChannel, 6)); const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); @@ -79,7 +79,7 @@ class test_StateProcessIfdMessages state.onEstablishPaceChannel(message, connection); QVERIFY(!context->getSlotHandle().isEmpty()); - QCOMPARE(context->getSlotHandle(), "test"); + QCOMPARE(context->getSlotHandle(), "test"_L1); const auto& paceChannel = context->getEstablishPaceChannel(); QCOMPARE(paceChannel.getPasswordId(), pinId); QCOMPARE(paceChannel.getChat(), chat); diff --git a/test/qt/workflows/ifd/test_StateStartIfdService.cpp b/test/qt/workflows/ifd/test_StateStartIfdService.cpp index 4277bbd22..cd28efcc4 100644 --- a/test/qt/workflows/ifd/test_StateStartIfdService.cpp +++ b/test/qt/workflows/ifd/test_StateStartIfdService.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateStartIfdService.h" diff --git a/test/qt/workflows/ifd/test_StateStopIfdService.cpp b/test/qt/workflows/ifd/test_StateStopIfdService.cpp index 471e104c0..e2b4288bb 100644 --- a/test/qt/workflows/ifd/test_StateStopIfdService.cpp +++ b/test/qt/workflows/ifd/test_StateStopIfdService.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateStopIfdService.h" diff --git a/test/qt/workflows/paos/element/test_ElementParser.cpp b/test/qt/workflows/paos/element/test_ElementParser.cpp index 1b89a356f..91d01e93c 100644 --- a/test/qt/workflows/paos/element/test_ElementParser.cpp +++ b/test/qt/workflows/paos/element/test_ElementParser.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; const auto dummyXmlData = "" @@ -39,12 +40,12 @@ class test_ElementParser { mParser.initData(dummyXmlData); - QVERIFY(nextElementNameEquals("rootElement")); + QVERIFY(nextElementNameEquals("rootElement"_L1)); mParser.initData(dummyXmlData); - QVERIFY(nextElementNameEquals("rootElement")); - QVERIFY(nextElementNameEquals("subElement")); + QVERIFY(nextElementNameEquals("rootElement"_L1)); + QVERIFY(nextElementNameEquals("subElement"_L1)); } diff --git a/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC1.cpp b/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC1.cpp index ff609c6ec..1de483671 100644 --- a/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC1.cpp +++ b/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -8,12 +8,15 @@ #include "paos/invoke/DidAuthenticateResponseEac1.h" -#include "TestFileHelper.h" #include "asn1/CVCertificate.h" #include "pinpad/EstablishPaceChannelOutput.h" +#include "CertificateHelper.h" +#include "TestFileHelper.h" + #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DidAuthenticateResponseEAC1 @@ -23,7 +26,7 @@ class test_DidAuthenticateResponseEAC1 QByteArray readFile(const QString& pFileName) { - return TestFileHelper::readFile(QString(":/card/").append(pFileName)); + return TestFileHelper::readFile(QStringLiteral(":/card/").append(pFileName)); } private Q_SLOTS: @@ -71,8 +74,8 @@ class test_DidAuthenticateResponseEAC1 void certificationAuthorityReference() { - const auto& cvca_DETESTeID00002 = CVCertificate::fromHex(readFile("cvca-DETESTeID00002.hex")); - const auto& cvca_DETESTeID00001 = CVCertificate::fromHex(readFile("cvca-DETESTeID00001.hex")); + const auto& cvca_DETESTeID00002 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00002.hex"_L1)); + const auto& cvca_DETESTeID00001 = CertificateHelper::fromHex(readFile("cvca-DETESTeID00001.hex"_L1)); EstablishPaceChannelOutput channel; channel.setCarCurr(cvca_DETESTeID00002->getBody().getCertificateHolderReference()); @@ -80,14 +83,14 @@ class test_DidAuthenticateResponseEAC1 DIDAuthenticateResponseEAC1 msg; msg.setCertificationAuthorityReference(channel); - QVERIFY(msg.marshall().contains("DETESTeID00002\n DETESTeID00001")); + QVERIFY(msg.marshall().contains("DETESTeID00002\n DETESTeID00001"_L1)); } void checkTemplate() { DIDAuthenticateResponseEAC1 msg; - msg.setRelatedMessageId("urn:uuid:A9CF4F0B8BFE483B8A5C7E6738C178FE"); + msg.setRelatedMessageId("urn:uuid:A9CF4F0B8BFE483B8A5C7E6738C178FE"_L1); msg.setCertificateHolderAuthorizationTemplate("a"); EstablishPaceChannelOutput output; output.setCarCurr("b"); @@ -97,8 +100,8 @@ class test_DidAuthenticateResponseEAC1 msg.setChallenge("e"); auto data = QString::fromLatin1(msg.marshall()); - data.replace(QRegularExpression(".*"), "STRIP ME"); - QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/DIDAuthenticateResponse2.xml"))); + data.replace(QRegularExpression(".*"_L1), "STRIP ME"_L1); + QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/DIDAuthenticateResponse2.xml"_L1))); } diff --git a/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC2.cpp b/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC2.cpp index 79205f1ff..e3e4c8d95 100644 --- a/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC2.cpp +++ b/test/qt/workflows/paos/invoke/test_DidAuthenticateResponseEAC2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DidAuthenticateResponseEAC2 @@ -83,8 +84,8 @@ class test_DidAuthenticateResponseEAC2 msg.setAuthenticationToken("b"); msg.setNonce("c"); auto data = QString::fromLatin1(msg.marshall()); - data.replace(QRegularExpression(".*"), "STRIP ME"); - QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/DIDAuthenticateResponse.xml"))); + data.replace(QRegularExpression(".*"_L1), "STRIP ME"_L1); + QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/DIDAuthenticateResponse.xml"_L1))); } diff --git a/test/qt/workflows/paos/invoke/test_PaosCreator.cpp b/test/qt/workflows/paos/invoke/test_PaosCreator.cpp index df1e46f50..b11a4c8d4 100644 --- a/test/qt/workflows/paos/invoke/test_PaosCreator.cpp +++ b/test/qt/workflows/paos/invoke/test_PaosCreator.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(PaosCreator::Namespace) @@ -26,15 +27,15 @@ struct test_PaosCreatorDummy bool mNamespace = false; const QString mTag = QStringLiteral("content"); - void createBodyElement() override + void createBodyElement(QXmlStreamWriter& pWriter) override { if (mNamespace) { - mWriter.writeTextElement(getNamespaceType(Namespace::SOAP, mTag), mText); + pWriter.writeTextElement(getNamespaceType(Namespace::SOAP, mTag), mText); } else { - mWriter.writeTextElement(mTag, mText); + pWriter.writeTextElement(mTag, mText); } } @@ -68,12 +69,12 @@ class test_PaosCreator QVERIFY(elem.contains("")); - creator.mText = "some test"; + creator.mText = "some test"_L1; elem = creator.marshall(); QVERIFY(elem.contains("")); // marshall() can be called once! test_PaosCreatorDummy creator2; - creator2.mText = "hello again"; + creator2.mText = "hello again"_L1; creator2.mNamespace = true; elem = creator2.marshall(); QVERIFY(elem.contains("hello again")); @@ -105,29 +106,29 @@ class test_PaosCreator void namespaces_data() { QTest::addColumn("namespaceName"); - QTest::addColumn("suffix"); - QTest::addColumn("namespaceString"); - QTest::addColumn("prefixString"); - QTest::addColumn("type"); - - QTest::newRow("addressing") << PaosCreator::Namespace::ADDRESSING << QString("test") << QString("http://www.w3.org/2005/03/addressing") << QString("wsa:test") << QString("wsa:test"); - QTest::newRow("dss") << PaosCreator::Namespace::DSS << QString() << QString("urn:oasis:names:tc:dss:1.0:core:schema") << QString("xmlns:dss") << QString("dss:"); - QTest::newRow("ecard") << PaosCreator::Namespace::ECARD << QString("ecard") << QString("http://www.bsi.bund.de/ecard/api/1.1") << QString("ecard:ecard") << QString("ecard:ecard"); - QTest::newRow("paos") << PaosCreator::Namespace::PAOS << QString("") << QString("urn:liberty:paos:2006-08") << QString("paos:") << QString("paos:"); - QTest::newRow("techschema") << PaosCreator::Namespace::TECHSCHEMA << QString(" ") << QString("urn:iso:std:iso-iec:24727:tech:schema") << QString("iso: ") << QString("iso: "); - QTest::newRow("xsd") << PaosCreator::Namespace::XSD << QString() << QString("http://www.w3.org/2001/XMLSchema") << QString("xmlns:xsd") << QString("xsd:"); - QTest::newRow("xsi") << PaosCreator::Namespace::XSI << QString() << QString("http://www.w3.org/2001/XMLSchema-instance") << QString("xmlns:xsi") << QString("xsi:"); - QTest::newRow("soap") << PaosCreator::Namespace::SOAP << QString("test") << QString("http://schemas.xmlsoap.org/soap/envelope/") << QString("soap:test") << QString("soap:test"); + QTest::addColumn("suffix"); + QTest::addColumn("namespaceString"); + QTest::addColumn("prefixString"); + QTest::addColumn("type"); + + QTest::newRow("addressing") << PaosCreator::Namespace::ADDRESSING << "test"_L1 << "http://www.w3.org/2005/03/addressing"_L1 << "wsa:test"_L1 << "wsa:test"_L1; + QTest::newRow("dss") << PaosCreator::Namespace::DSS << QLatin1String() << "urn:oasis:names:tc:dss:1.0:core:schema"_L1 << "xmlns:dss"_L1 << "dss:"_L1; + QTest::newRow("ecard") << PaosCreator::Namespace::ECARD << "ecard"_L1 << "http://www.bsi.bund.de/ecard/api/1.1"_L1 << "ecard:ecard"_L1 << "ecard:ecard"_L1; + QTest::newRow("paos") << PaosCreator::Namespace::PAOS << ""_L1 << "urn:liberty:paos:2006-08"_L1 << "paos:"_L1 << "paos:"_L1; + QTest::newRow("techschema") << PaosCreator::Namespace::TECHSCHEMA << " "_L1 << "urn:iso:std:iso-iec:24727:tech:schema"_L1 << "iso: "_L1 << "iso: "_L1; + QTest::newRow("xsd") << PaosCreator::Namespace::XSD << QLatin1String() << "http://www.w3.org/2001/XMLSchema"_L1 << "xmlns:xsd"_L1 << "xsd:"_L1; + QTest::newRow("xsi") << PaosCreator::Namespace::XSI << QLatin1String() << "http://www.w3.org/2001/XMLSchema-instance"_L1 << "xmlns:xsi"_L1 << "xsi:"_L1; + QTest::newRow("soap") << PaosCreator::Namespace::SOAP << "test"_L1 << "http://schemas.xmlsoap.org/soap/envelope/"_L1 << "soap:test"_L1 << "soap:test"_L1; } void namespaces() { QFETCH(PaosCreator::Namespace, namespaceName); - QFETCH(QString, suffix); - QFETCH(QString, namespaceString); - QFETCH(QString, prefixString); - QFETCH(QString, type); + QFETCH(QLatin1String, suffix); + QFETCH(QLatin1String, namespaceString); + QFETCH(QLatin1String, prefixString); + QFETCH(QLatin1String, type); QCOMPARE(PaosCreator::getNamespace(namespaceName), namespaceString); QCOMPARE(PaosCreator::getNamespacePrefix(namespaceName, suffix), prefixString); diff --git a/test/qt/workflows/paos/invoke/test_StartPaos.cpp b/test/qt/workflows/paos/invoke/test_StartPaos.cpp index cefce42a4..3892e448e 100644 --- a/test/qt/workflows/paos/invoke/test_StartPaos.cpp +++ b/test/qt/workflows/paos/invoke/test_StartPaos.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StartPaos @@ -23,7 +24,7 @@ class test_StartPaos private Q_SLOTS: void initTestCase() { - QCoreApplication::setApplicationVersion("123.456.789"); + QCoreApplication::setApplicationVersion("123.456.789"_L1); } @@ -63,10 +64,10 @@ class test_StartPaos void checkTemplate() { StartPaos startPaos("abcd"); - startPaos.setRelatedMessageId("urn:uuid:dummy"); + startPaos.setRelatedMessageId("urn:uuid:dummy"_L1); auto data = QString::fromLatin1(startPaos.marshall()); - data.replace(QRegularExpression(".*"), "STRIP ME"); - QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/StartPAOS.xml"))); + data.replace(QRegularExpression(".*"_L1), "STRIP ME"_L1); + QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/StartPAOS.xml"_L1))); } diff --git a/test/qt/workflows/paos/invoke/test_TransmitResponse.cpp b/test/qt/workflows/paos/invoke/test_TransmitResponse.cpp index 686080d7f..67af507a4 100644 --- a/test/qt/workflows/paos/invoke/test_TransmitResponse.cpp +++ b/test/qt/workflows/paos/invoke/test_TransmitResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_TransmitResponse @@ -38,7 +39,7 @@ class test_TransmitResponse QVERIFY(!elem.contains("OutputAPDU")); TransmitResponse responseWithApdu; - responseWithApdu.setMessageId("dummy"); + responseWithApdu.setMessageId("dummy"_L1); responseWithApdu.setOutputApdus(QByteArrayList{"bla"}); elem = responseWithApdu.marshall(); @@ -52,8 +53,8 @@ class test_TransmitResponse response.setResult(ECardApiResult(GlobalStatus::Code::Workflow_Wrong_Parameter_Invocation)); response.setOutputApdus(QByteArrayList{"a", "b", "c"}); auto data = QString::fromLatin1(response.marshall()); - data.replace(QRegularExpression(".*"), "STRIP ME"); - QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/TransmitResponse.xml"))); + data.replace(QRegularExpression(".*"_L1), "STRIP ME"_L1); + QCOMPARE(data, QString::fromLatin1(TestFileHelper::readFile(":/paos/TransmitResponse.xml"_L1))); } diff --git a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac1.cpp b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac1.cpp index 825da0fec..dfd6a2328 100644 --- a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac1.cpp +++ b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,6 +17,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DidAuthenticateEac1 @@ -39,17 +40,17 @@ class test_DidAuthenticateEac1 void parseXml() { - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"_L1); QScopedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); QVERIFY(!eac1.isNull()); - QCOMPARE(eac1->getConnectionHandle().getCardApplication(), QString("4549445F49534F5F32343732375F42415345")); - QCOMPARE(eac1->getConnectionHandle().getContextHandle(), QString("4549445F4946445F434F4E544558545F42415345")); - QCOMPARE(eac1->getConnectionHandle().getIfdName(), QString("REINER SCT cyberJack RFID komfort USB 52")); - QCOMPARE(eac1->getConnectionHandle().getSlotHandle(), QString("37343139303333612D616163352D343331352D386464392D656166393664636661653361")); - QCOMPARE(eac1->getConnectionHandle().getSlotIndex(), QString("0")); + QCOMPARE(eac1->getConnectionHandle().getCardApplication(), "4549445F49534F5F32343732375F42415345"_L1); + QCOMPARE(eac1->getConnectionHandle().getContextHandle(), "4549445F4946445F434F4E544558545F42415345"_L1); + QCOMPARE(eac1->getConnectionHandle().getIfdName(), "REINER SCT cyberJack RFID komfort USB 52"_L1); + QCOMPARE(eac1->getConnectionHandle().getSlotHandle(), "37343139303333612D616163352D343331352D386464392D656166393664636661653361"_L1); + QCOMPARE(eac1->getConnectionHandle().getSlotIndex(), "0"_L1); - QCOMPARE(eac1->getDidName(), QString("PIN")); + QCOMPARE(eac1->getDidName(), "PIN"_L1); QCOMPARE(eac1->getAuthenticatedAuxiliaryDataAsBinary(), QByteArray::fromHex("67447315060904007F000703010401530831393932313230367315060904007F000703010402530832303133313230367314060904007F000703010403530702760400110000")); QCOMPARE(eac1->getAuthenticatedAuxiliaryData()->getAgeVerificationDate(), QDate(1992, 12, 6)); @@ -58,14 +59,14 @@ class test_DidAuthenticateEac1 QCOMPARE(eac1->getCertificateDescription()->getIssuerName(), QStringLiteral("Governikus Test DVCA")); QVERIFY(eac1->getOptionalChat()); QVERIFY(eac1->getRequiredChat()); - QCOMPARE(eac1->getTransactionInfo(), QString("this is a test for TransactionInfo")); + QCOMPARE(eac1->getTransactionInfo(), "this is a test for TransactionInfo"_L1); } // Test data from Test TS_TA_2.1.1 from TR-03105-5.2 void test_TS_TA_2_1_1() { - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_TS_TA_2.1.1.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_TS_TA_2.1.1.xml"_L1); QScopedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); QVERIFY(eac1 == nullptr); @@ -79,8 +80,8 @@ class test_DidAuthenticateEac1 QTest::addColumn("templateXml"); const QByteArray placeHolder(""); - const QString templ1(":/paos/DIDAuthenticateEAC1_template.xml"); - const QString templ2(":/paos/DIDAuthenticateEAC1_template2.xml"); + const QString templ1(":/paos/DIDAuthenticateEAC1_template.xml"_L1); + const QString templ2(":/paos/DIDAuthenticateEAC1_template2.xml"_L1); QTest::newRow("DIDName") << QByteArray("") << QByteArray("PIN") << templ1; QTest::newRow("CertificateDescription") << placeHolder << QByteArray("3082013b060a04007f00070301030101a1160c14476f7665726e696b757320546573742044564341a21a1318687474703a2f2f7777772e676f7665726e696b75732e6465a31a0c18476f7665726e696b757320476d6248202620436f2e204b47a420131e68747470733a2f2f746573742e676f7665726e696b75732d6569642e6465a581940c81914e616d652c20416e7363687269667420756e6420452d4d61696c2d4164726573736520646573204469656e737465616e626965746572733a0d0a476f7665726e696b757320476d6248202620436f2e204b470d0a486f6368736368756c72696e6720340d0a3238333539204272656d656e0d0a452d4d61696c3a206b6f6e74616b7440676f7665726e696b75732e646509a72431220420ccb65ac1d48e9cd43876ca82cfe83c43d711294d4a40f68811acb715aaa6c8ab") << templ1; @@ -143,7 +144,7 @@ class test_DidAuthenticateEac1 QFETCH(bool, parsingSuccessful); QFETCH(QList, acceptedEidTypes); - QByteArray content = TestFileHelper::readFile(QString(":/paos/DIDAuthenticateEAC1_template.xml")); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_template.xml"_L1); content = content.replace(QByteArray(""), replaceContent); QScopedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); diff --git a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac2.cpp b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac2.cpp index cb7264b0a..f73d62a65 100644 --- a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac2.cpp +++ b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -17,6 +17,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DidAuthenticateEac2 @@ -39,20 +40,20 @@ class test_DidAuthenticateEac2 void parseXml() { - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"_L1); QScopedPointer eac2(static_cast(DidAuthenticateEac2Parser().parse(content))); QVERIFY(!eac2.isNull()); - QCOMPARE(eac2->getConnectionHandle().getCardApplication(), QString("4549445F49534F5F32343732375F42415345")); - QCOMPARE(eac2->getConnectionHandle().getContextHandle(), QString("4549445F4946445F434F4E544558545F42415345")); - QCOMPARE(eac2->getConnectionHandle().getIfdName(), QString("REINER SCT cyberJack RFID komfort USB 52")); - QCOMPARE(eac2->getConnectionHandle().getSlotHandle(), QString("34366364653038392D623031322D346664372D386233362D343664346232393537636236")); - QCOMPARE(eac2->getConnectionHandle().getSlotIndex(), QString("0")); + QCOMPARE(eac2->getConnectionHandle().getCardApplication(), "4549445F49534F5F32343732375F42415345"_L1); + QCOMPARE(eac2->getConnectionHandle().getContextHandle(), "4549445F4946445F434F4E544558545F42415345"_L1); + QCOMPARE(eac2->getConnectionHandle().getIfdName(), "REINER SCT cyberJack RFID komfort USB 52"_L1); + QCOMPARE(eac2->getConnectionHandle().getSlotHandle(), "34366364653038392D623031322D346664372D386233362D343664346232393537636236"_L1); + QCOMPARE(eac2->getConnectionHandle().getSlotIndex(), "0"_L1); - QCOMPARE(eac2->getDidName(), QString("PIN")); + QCOMPARE(eac2->getDidName(), "PIN"_L1); QCOMPARE(eac2->getCvCertificates().size(), 0); - QCOMPARE(eac2->getEphemeralPublicKey(), QString("046E35D82A4F370F9B4C7B6415B7FF936B2FE2DAFD8E008037E8B0464918FDACD33AE730BABAE05C45E9567F010A4A40CA3CF04409C2EEBAC0E38B9E36975E2AE1")); - QCOMPARE(eac2->getSignature(), QString("2DE1E928C7E6C40F3389BF1973214EAB082F816EB42B6A3C3B36EF4BDD61A2594C7814DDBF7D5A32ADE60188BFCA12BBF7C2FB8DF93A4FE042121015F1FAC7EA")); + QCOMPARE(eac2->getEphemeralPublicKey(), "046E35D82A4F370F9B4C7B6415B7FF936B2FE2DAFD8E008037E8B0464918FDACD33AE730BABAE05C45E9567F010A4A40CA3CF04409C2EEBAC0E38B9E36975E2AE1"_L1); + QCOMPARE(eac2->getSignature(), "2DE1E928C7E6C40F3389BF1973214EAB082F816EB42B6A3C3B36EF4BDD61A2594C7814DDBF7D5A32ADE60188BFCA12BBF7C2FB8DF93A4FE042121015F1FAC7EA"_L1); } @@ -60,11 +61,11 @@ class test_DidAuthenticateEac2 { QTest::addColumn("replaceIdentifier"); QTest::addColumn("replaceContent"); - QTest::addColumn("templateXml"); + QTest::addColumn("templateXml"); const QByteArray placeHolder(""); - const QString templ1(":/paos/DIDAuthenticateEAC2_template.xml"); - const QString templ2(":/paos/DIDAuthenticateEAC2_template2.xml"); + const QLatin1String templ1(":/paos/DIDAuthenticateEAC2_template.xml"); + const QLatin1String templ2(":/paos/DIDAuthenticateEAC2_template2.xml"); QTest::newRow("DIDName") << QByteArray("") << QByteArray("PIN") << templ1; QTest::newRow("EphemeralPublicKey") << placeHolder << QByteArray("046E35D82A4F370F9B4C7B6415B7FF936B2FE2DAFD8E008037E8B0464918FDACD33AE730BABAE05C45E9567F010A4A40CA3CF04409C2EEBAC0E38B9E36975E2AE1") << templ1; @@ -82,7 +83,7 @@ class test_DidAuthenticateEac2 { QFETCH(QByteArray, replaceIdentifier); QFETCH(QByteArray, replaceContent); - QFETCH(QString, templateXml); + QFETCH(QLatin1String, templateXml); const QByteArray tag = QByteArray(QTest::currentDataTag()); const QByteArray data = '<' + tag + '>' + replaceContent + "'; diff --git a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEacAdditional.cpp b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEacAdditional.cpp index c6e369e11..7b16ec8ef 100644 --- a/test/qt/workflows/paos/retrieve/test_DidAuthenticateEacAdditional.cpp +++ b/test/qt/workflows/paos/retrieve/test_DidAuthenticateEacAdditional.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_DidAuthenticateEacAdditional @@ -38,19 +39,19 @@ class test_DidAuthenticateEacAdditional void parse() { - QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput.xml"); + QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput.xml"_L1); PaosMessage* paosMessage = DidAuthenticateEacAdditionalParser().parse(content); QScopedPointer eacAdd(static_cast(paosMessage)); QVERIFY(eacAdd); - QCOMPARE(eacAdd->getSignature(), QString("86E24ACCE25E2B4623A3558EED7AA65658FEE70CC7B46CB9D34BD50B2F27E1E2221473D5B871497563693E0F28BE9C8896062A9C02CE3959AD4BD58DEA0E984B")); + QCOMPARE(eacAdd->getSignature(), "86E24ACCE25E2B4623A3558EED7AA65658FEE70CC7B46CB9D34BD50B2F27E1E2221473D5B871497563693E0F28BE9C8896062A9C02CE3959AD4BD58DEA0E984B"_L1); } void noSignature() { - QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput_noSignature.xml"); + QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput_noSignature.xml"_L1); PaosMessage* paosMessage = DidAuthenticateEacAdditionalParser().parse(content); QVERIFY(paosMessage == nullptr); @@ -59,7 +60,7 @@ class test_DidAuthenticateEacAdditional void manySignature() { - QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput_manySignature.xml"); + QByteArray content = TestFileHelper::readFile(":paos/DIDAuthenticateEACAdditionalInput_manySignature.xml"_L1); PaosMessage* paosMessage = DidAuthenticateEacAdditionalParser().parse(content); QVERIFY(paosMessage == nullptr); @@ -72,8 +73,8 @@ class test_DidAuthenticateEacAdditional QTest::addColumn("replaceContent"); QTest::addColumn("templateXml"); - const QString templ1(":/paos/DIDAuthenticateEACAdditionalInput_template.xml"); - const QString templ2(":/paos/DIDAuthenticateEACAdditionalInput_template2.xml"); + const QString templ1(":/paos/DIDAuthenticateEACAdditionalInput_template.xml"_L1); + const QString templ2(":/paos/DIDAuthenticateEACAdditionalInput_template2.xml"_L1); QTest::newRow("ConnectionHandle") << QByteArray("") << QByteArray("3189905F82823FB6F8EF871E315CC9F0") << templ1; QTest::newRow("DIDName") << QByteArray("") << QByteArray("PIN") << templ1; diff --git a/test/qt/workflows/paos/retrieve/test_InitializeFramework.cpp b/test/qt/workflows/paos/retrieve/test_InitializeFramework.cpp index e67f51c2d..b5d7606fb 100644 --- a/test/qt/workflows/paos/retrieve/test_InitializeFramework.cpp +++ b/test/qt/workflows/paos/retrieve/test_InitializeFramework.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_InitializeFramework @@ -28,11 +29,11 @@ class test_InitializeFramework void parse() { - QByteArray content = TestFileHelper::readFile(":paos/InitializeFramework_withMessageID.xml"); + QByteArray content = TestFileHelper::readFile(":paos/InitializeFramework_withMessageID.xml"_L1); InitializeFramework message(content); - QCOMPARE(message.getMessageId(), QString("urn:uuid:c0f05ac0-1a67-4a0b-acbd-78309fcdb002")); + QCOMPARE(message.getMessageId(), "urn:uuid:c0f05ac0-1a67-4a0b-acbd-78309fcdb002"_L1); QCOMPARE(message.getRelatesTo(), QString()); } diff --git a/test/qt/workflows/paos/retrieve/test_StartPAOSResponse.cpp b/test/qt/workflows/paos/retrieve/test_StartPAOSResponse.cpp index ce7635376..5b5ff2aff 100644 --- a/test/qt/workflows/paos/retrieve/test_StartPAOSResponse.cpp +++ b/test/qt/workflows/paos/retrieve/test_StartPAOSResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StartPAOSResponse @@ -23,23 +24,23 @@ class test_StartPAOSResponse private Q_SLOTS: void parsing_data() { - QTest::addColumn("filename"); + QTest::addColumn("filename"); QTest::addColumn("major"); QTest::addColumn("minor"); - QTest::addColumn("message"); + QTest::addColumn("message"); - QTest::newRow("Major") << ":paos/StartPAOSResponse1.xml" << ECardApiResult::Major::Ok << ECardApiResult::Minor::null << QString(); - QTest::newRow("MajorMinor") << ":paos/StartPAOSResponse2.xml" << ECardApiResult::Major::Error << ECardApiResult::Minor::DP_Timeout_Error << QString(); - QTest::newRow("MajorMinorMessage") << ":paos/StartPAOSResponse3.xml" << ECardApiResult::Major::Error << ECardApiResult::Minor::DP_Timeout_Error << QString("Detail message"); + QTest::newRow("Major") << ":paos/StartPAOSResponse1.xml"_L1 << ECardApiResult::Major::Ok << ECardApiResult::Minor::null << QLatin1String(); + QTest::newRow("MajorMinor") << ":paos/StartPAOSResponse2.xml"_L1 << ECardApiResult::Major::Error << ECardApiResult::Minor::DP_Timeout_Error << QLatin1String(); + QTest::newRow("MajorMinorMessage") << ":paos/StartPAOSResponse3.xml"_L1 << ECardApiResult::Major::Error << ECardApiResult::Minor::DP_Timeout_Error << "Detail message"_L1; } void parsing() { - QFETCH(QString, filename); + QFETCH(QLatin1String, filename); QFETCH(ECardApiResult::Major, major); QFETCH(ECardApiResult::Minor, minor); - QFETCH(QString, message); + QFETCH(QLatin1String, message); QByteArray content = TestFileHelper::readFile(filename); StartPaosResponse startPaosResponse(content); diff --git a/test/qt/workflows/paos/retrieve/test_transmit.cpp b/test/qt/workflows/paos/retrieve/test_transmit.cpp index 4510f8cd5..a75b58462 100644 --- a/test/qt/workflows/paos/retrieve/test_transmit.cpp +++ b/test/qt/workflows/paos/retrieve/test_transmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_transmit @@ -38,12 +39,12 @@ class test_transmit void parseXml() { - QByteArray content = TestFileHelper::readFile(":/paos/Transmit.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit.xml"_L1); QScopedPointer transmit(static_cast(TransmitParser().parse(content))); QVERIFY(!transmit.isNull()); auto inputApdusInfos = transmit->getInputApduInfos(); - QCOMPARE(transmit->getSlotHandle(), QString("34366364653038392D623031322D346664372D386233362D343664346232393537636236")); + QCOMPARE(transmit->getSlotHandle(), "34366364653038392D623031322D346664372D386233362D343664346232393537636236"_L1); QCOMPARE(inputApdusInfos.size(), 7); QCOMPARE(inputApdusInfos[0].getInputApdu(), @@ -73,14 +74,14 @@ class test_transmit void parseXmlWithAddressing() { - QByteArray content = TestFileHelper::readFile(":/paos/Transmit3.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit3.xml"_L1); QScopedPointer transmit(static_cast(TransmitParser().parse(content))); QVERIFY(!transmit.isNull()); auto inputApdusInfos = transmit->getInputApduInfos(); - QCOMPARE(transmit->getSlotHandle(), QString("34366364653038392D623031322D346664372D386233362D343664346232393537636236")); - QCOMPARE(transmit->getMessageId(), QString("urn:uuid:015c4aba-4b51-463d-95e4-df127c94a5ce")); - QCOMPARE(transmit->getRelatesTo(), QString("urn:uuid:04b2b166-77ad-42c9-bb7d-0c5e9798d337")); + QCOMPARE(transmit->getSlotHandle(), "34366364653038392D623031322D346664372D386233362D343664346232393537636236"_L1); + QCOMPARE(transmit->getMessageId(), "urn:uuid:015c4aba-4b51-463d-95e4-df127c94a5ce"_L1); + QCOMPARE(transmit->getRelatesTo(), "urn:uuid:04b2b166-77ad-42c9-bb7d-0c5e9798d337"_L1); QCOMPARE(inputApdusInfos.size(), 7); QCOMPARE(inputApdusInfos[0].getInputApdu(), @@ -110,12 +111,12 @@ class test_transmit void parseAnswerAutent() { - QByteArray content = TestFileHelper::readFile(":/paos/Transmit2.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit2.xml"_L1); QScopedPointer transmit(static_cast(TransmitParser().parse(content))); QVERIFY(!transmit.isNull()); auto inputApduInfos = transmit->getInputApduInfos(); - QCOMPARE(transmit->getSlotHandle(), QString("33393236303635313532")); + QCOMPARE(transmit->getSlotHandle(), "33393236303635313532"_L1); QCOMPARE(inputApduInfos.size(), 26); QByteArrayList expectedInputApdus; @@ -173,7 +174,7 @@ class test_transmit const QByteArray tag = QByteArray(QTest::currentDataTag()); const QByteArray data = '<' + tag + '>' + replaceContent + "'; - QByteArray content = TestFileHelper::readFile(":/paos/Transmit_template.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit_template.xml"_L1); content = content.replace(replaceIdentifier, data + data); QScopedPointer transmit(static_cast(TransmitParser().parse(content))); diff --git a/test/qt/workflows/paos/test_PaosMessage.cpp b/test/qt/workflows/paos/test_PaosMessage.cpp index 320da508d..ea367268e 100644 --- a/test/qt/workflows/paos/test_PaosMessage.cpp +++ b/test/qt/workflows/paos/test_PaosMessage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/workflows/paos/test_RequestType.cpp b/test/qt/workflows/paos/test_RequestType.cpp index e8537a1f0..cd2fde999 100644 --- a/test/qt/workflows/paos/test_RequestType.cpp +++ b/test/qt/workflows/paos/test_RequestType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/workflows/paos/test_UserAgent.cpp b/test/qt/workflows/paos/test_UserAgent.cpp index 862e568dd..4e4bbc903 100644 --- a/test/qt/workflows/paos/test_UserAgent.cpp +++ b/test/qt/workflows/paos/test_UserAgent.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2016-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -11,6 +11,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_UserAgent @@ -21,13 +22,13 @@ class test_UserAgent private Q_SLOTS: void getter() { - QCoreApplication::setApplicationVersion("1.32.4"); + QCoreApplication::setApplicationVersion("1.32.4"_L1); UserAgent obj; - QCOMPARE(obj.getName(), QString("AusweisApp2")); - QCOMPARE(obj.getVersionMajor(), QString("1")); - QCOMPARE(obj.getVersionMinor(), QString("32")); - QCOMPARE(obj.getVersionSubminor(), QString("4")); + QCOMPARE(obj.getName(), "AusweisApp2"_L1); + QCOMPARE(obj.getVersionMajor(), "1"_L1); + QCOMPARE(obj.getVersionMinor(), "32"_L1); + QCOMPARE(obj.getVersionSubminor(), "4"_L1); } diff --git a/test/qt/workflows/paos/test_paoshandler.cpp b/test/qt/workflows/paos/test_paoshandler.cpp index de92f84da..488d17489 100644 --- a/test/qt/workflows/paos/test_paoshandler.cpp +++ b/test/qt/workflows/paos/test_paoshandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include @@ -11,6 +11,7 @@ #include "paos/PaosHandler.h" +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -22,7 +23,7 @@ class test_paoshandler private Q_SLOTS: void parseDIDAuthenticateEAC1() { - QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::DID_AUTHENTICATE_EAC1); } @@ -31,7 +32,7 @@ class test_paoshandler // test data of testbed (the attribute value of xsi:type contains a namespace identifier) void parseDIDAuthenticateEAC1_fromTestbed() { - QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_2.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1_2.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::DID_AUTHENTICATE_EAC1); } @@ -39,7 +40,7 @@ class test_paoshandler void parseDIDAuthenticateEAC2() { - QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::DID_AUTHENTICATE_EAC2); } @@ -47,7 +48,7 @@ class test_paoshandler void parseDIDAuthenticateEACAdditionalInputType() { - QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEACAdditionalInput.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/DIDAuthenticateEACAdditionalInput.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::DID_AUTHENTICATE_EAC_ADDITIONAL_INPUT_TYPE); } @@ -55,7 +56,7 @@ class test_paoshandler void parseInitializeFramework() { - QByteArray initFW = TestFileHelper::readFile(":/paos/InitializeFramework.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/InitializeFramework.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::INITIALIZE_FRAMEWORK); } @@ -63,7 +64,7 @@ class test_paoshandler void parseStartPAOSResponse() { - QByteArray initFW = TestFileHelper::readFile(":/paos/StartPAOSResponse1.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/StartPAOSResponse1.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::STARTPAOS_RESPONSE); } @@ -71,7 +72,7 @@ class test_paoshandler void parseTransmit() { - QByteArray initFW = TestFileHelper::readFile(":/paos/Transmit.xml"); + QByteArray initFW = TestFileHelper::readFile(":/paos/Transmit.xml"_L1); PaosHandler handler(initFW); QVERIFY(handler.getDetectedPaosType() == PaosType::TRANSMIT); } diff --git a/test/qt/workflows/personalization/test_PersonalizationContext.cpp b/test/qt/workflows/personalization/test_PersonalizationContext.cpp index 4d33b5d8d..f12a11d10 100644 --- a/test/qt/workflows/personalization/test_PersonalizationContext.cpp +++ b/test/qt/workflows/personalization/test_PersonalizationContext.cpp @@ -1,12 +1,12 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "context/PersonalizationContext.h" #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -33,8 +33,8 @@ class test_PersonalizationContext QCOMPARE(context.getChallenge(), QString()); - context.setChallenge(QString("Q2hhbGxlbmdl")); - QCOMPARE(context.getChallenge(), QString("Q2hhbGxlbmdl")); + context.setChallenge("Q2hhbGxlbmdl"_L1); + QCOMPARE(context.getChallenge(), "Q2hhbGxlbmdl"_L1); } @@ -44,8 +44,8 @@ class test_PersonalizationContext QCOMPARE(context.getPreparePersonalizationData(), QString()); - context.setPreparePersonalizationData(QString("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE=")); - QCOMPARE(context.getPreparePersonalizationData(), QString("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE=")); + context.setPreparePersonalizationData("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE="_L1); + QCOMPARE(context.getPreparePersonalizationData(), "UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE="_L1); } diff --git a/test/qt/workflows/personalization/test_StateChangeSmartPin.cpp b/test/qt/workflows/personalization/test_StateChangeSmartPin.cpp index 9aff5e280..1da4912c2 100644 --- a/test/qt/workflows/personalization/test_StateChangeSmartPin.cpp +++ b/test/qt/workflows/personalization/test_StateChangeSmartPin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,6 +15,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -62,7 +63,7 @@ class test_StateChangeSmartPin worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); const QSharedPointer context(new PersonalizationContext(QString())); - context->setNewPin("123456"); + context->setNewPin("123456"_L1); context->setCardConnection(connection); StateChangeSmartPin state(context); @@ -93,7 +94,7 @@ class test_StateChangeSmartPin QCOMPARE(state.mConnections.size(), 1); QTest::ignoreMessage(QtDebugMsg, "Invoke set Eid PIN command"); - context->setNewPin("123456"); + context->setNewPin("123456"_L1); QCOMPARE(state.mConnections.size(), 2); } @@ -108,7 +109,7 @@ class test_StateChangeSmartPin StateChangeSmartPin state(context); const QSharedPointer worker(new MockCardConnectionWorker()); const QSharedPointer command(new MockEstablishPaceChannelCommand(worker)); - const ReaderInfo readerInfo("NFC", ReaderManagerPlugInType::SMART); + const ReaderInfo readerInfo("NFC"_L1, ReaderManagerPluginType::SMART); const QSharedPointer connection(new MockCardConnection(readerInfo)); context->setCardConnection(connection); diff --git a/test/qt/workflows/personalization/test_StateCheckApplet.cpp b/test/qt/workflows/personalization/test_StateCheckApplet.cpp index cbe349133..745a81b5e 100644 --- a/test/qt/workflows/personalization/test_StateCheckApplet.cpp +++ b/test/qt/workflows/personalization/test_StateCheckApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateCheckApplet.h" @@ -30,7 +30,7 @@ class test_StateCheckApplet private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/workflows/personalization/test_StateDeleteApplet.cpp b/test/qt/workflows/personalization/test_StateDeleteApplet.cpp index a56595dae..6350034db 100644 --- a/test/qt/workflows/personalization/test_StateDeleteApplet.cpp +++ b/test/qt/workflows/personalization/test_StateDeleteApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateDeleteApplet.h" @@ -16,6 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -31,7 +32,7 @@ class test_StateDeleteApplet private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -59,42 +60,42 @@ class test_StateDeleteApplet QTest::addRow("SUCCESS") << EidServiceResult::SUCCESS - << QStringList {"Successfully deleted Smart-eID"} + << QStringList {"Successfully deleted Smart-eID"_L1} << GlobalStatus::Code::No_Error << std::optional(); QTest::addRow("ERROR") << EidServiceResult::ERROR - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Fail); QTest::addRow("UNSUPPORTED") << EidServiceResult::UNSUPPORTED - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Unsupported); QTest::addRow("NFC_NOT_ACTIVATED") << EidServiceResult::NFC_NOT_ACTIVATED - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Nfc_Disabled); QTest::addRow("OVERLOAD_PROTECTION") << EidServiceResult::OVERLOAD_PROTECTION - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Overload); QTest::addRow("UNDER_MAINTENANCE") << EidServiceResult::UNDER_MAINTENANCE - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Maintenance); QTest::addRow("INTEGRITY_CHECK_FAILED") << EidServiceResult::INTEGRITY_CHECK_FAILED - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Integrity_Check_Failed); QTest::addRow("NOT_AUTHENTICATED") << EidServiceResult::NOT_AUTHENTICATED - << QStringList {"Deletion of Smart-eID failed"} + << QStringList {"Deletion of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Smart_Service_Response_Not_Authenticated); } diff --git a/test/qt/workflows/personalization/test_StateDeletePersonalization.cpp b/test/qt/workflows/personalization/test_StateDeletePersonalization.cpp index eb417b194..59526ccc6 100644 --- a/test/qt/workflows/personalization/test_StateDeletePersonalization.cpp +++ b/test/qt/workflows/personalization/test_StateDeletePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateDeletePersonalization.h" @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -28,7 +29,7 @@ class test_StateDeletePersonalization private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -56,42 +57,42 @@ class test_StateDeletePersonalization QTest::addRow("SUCCESS") << EidServiceResult::SUCCESS - << QStringList {"Successfully deleted the Smart-eID personalization"} + << QStringList {"Successfully deleted the Smart-eID personalization"_L1} << GlobalStatus::Code::No_Error << std::optional(); QTest::addRow("ERROR") << EidServiceResult::ERROR - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("UNSUPPORTED") << EidServiceResult::UNSUPPORTED - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("OVERLOAD_PROTECTION") << EidServiceResult::OVERLOAD_PROTECTION - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("UNDER_MAINTENANCE") << EidServiceResult::UNDER_MAINTENANCE - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("NFC_NOT_ACTIVATED") << EidServiceResult::NFC_NOT_ACTIVATED - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("INTEGRITY_CHECK_FAILED") << EidServiceResult::INTEGRITY_CHECK_FAILED - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); QTest::addRow("NOT_AUTHENTICATED") << EidServiceResult::NOT_AUTHENTICATED - << QStringList {"Deletion of Smart-eID personalization failed"} + << QStringList {"Deletion of Smart-eID personalization failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Delete_Personalization_Failed); } diff --git a/test/qt/workflows/personalization/test_StateFinalizePersonalization.cpp b/test/qt/workflows/personalization/test_StateFinalizePersonalization.cpp index a165b38d5..c71c91574 100644 --- a/test/qt/workflows/personalization/test_StateFinalizePersonalization.cpp +++ b/test/qt/workflows/personalization/test_StateFinalizePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateFinalizePersonalization.h" @@ -29,7 +29,7 @@ class test_StateFinalizePersonalization private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/workflows/personalization/test_StateGetChallenge.cpp b/test/qt/workflows/personalization/test_StateGetChallenge.cpp index 0c51ed6cc..454f3092e 100644 --- a/test/qt/workflows/personalization/test_StateGetChallenge.cpp +++ b/test/qt/workflows/personalization/test_StateGetChallenge.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateGetChallenge.h" @@ -14,7 +14,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -49,16 +49,16 @@ class test_StateGetChallenge void test_CheckRequestUrl() { - mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003")); + mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1)); const auto& url = mState->getRequestUrl().toString(); - QCOMPARE(url, QString("https://dummy/v1/challenge")); + QCOMPARE(url, "https://dummy/v1/challenge"_L1); } void test_CheckPayload() { - mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003")); + mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1)); mContext->setServiceInformation(SmartEidType::APPLET, QStringLiteral("FooBar"), QString()); const auto& payload = mState->getPayload(); @@ -68,8 +68,8 @@ class test_StateGetChallenge const auto obj = json.object(); QCOMPARE(obj.size(), 2); - QCOMPARE(obj.value(QLatin1String("sessionID")).toString(), QString("135a32d8-ccfa-11eb-b8bc-0242ac130003")); - QCOMPARE(obj.value(QLatin1String("challengeType")).toString(), QString("FooBar")); + QCOMPARE(obj.value(QLatin1String("sessionID")).toString(), "135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1); + QCOMPARE(obj.value(QLatin1String("challengeType")).toString(), "FooBar"_L1); } @@ -98,13 +98,13 @@ class test_StateGetChallenge mState->onNetworkReply(); QCOMPARE(spyContinue.count(), 1); - QCOMPARE(mContext->getChallenge(), QString("Q2hhbGxlbmdl")); + QCOMPARE(mContext->getChallenge(), "Q2hhbGxlbmdl"_L1); } void test_OnNetworkReplyWrongHttpStatus() { - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); mState->mReply.reset(reply, &QObject::deleteLater); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, 500); reply->setError(QNetworkReply::NetworkError::InternalServerError, QString()); @@ -116,9 +116,9 @@ class test_StateGetChallenge QCOMPARE(mState->getContext()->getStatus().getStatusCode(), GlobalStatus::Code::Workflow_TrustedChannel_Server_Error); const FailureCode::FailureInfoMap infoMap { - {FailureCode::Info::State_Name, "StateGetChallenge"}, + {FailureCode::Info::State_Name, "StateGetChallenge"_L1}, {FailureCode::Info::Http_Status_Code, QString::number(500)}, - {FailureCode::Info::Network_Error, "Unknown error"} + {FailureCode::Info::Network_Error, "Unknown error"_L1} }; const FailureCode failureCode(FailureCode::Reason::Generic_Provider_Communication_Server_Error, infoMap); QCOMPARE(mState->getContext()->getFailureCode(), failureCode); diff --git a/test/qt/workflows/personalization/test_StateGetServiceInformation.cpp b/test/qt/workflows/personalization/test_StateGetServiceInformation.cpp index a3f89e4a7..b30111052 100644 --- a/test/qt/workflows/personalization/test_StateGetServiceInformation.cpp +++ b/test/qt/workflows/personalization/test_StateGetServiceInformation.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateGetServiceInformation.h" @@ -17,7 +17,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -31,7 +31,7 @@ class test_StateGetServiceInformation private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -58,7 +58,7 @@ class test_StateGetServiceInformation QSignalSpy spyContinue(&state, &StateGetServiceInformation::fireContinue); setServiceInformation({EidServiceResult::ERROR}); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("ServiceInformation query failed")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("ServiceInformation query failed"_L1)); state.run(); QTRY_COMPARE(spyAbort.size(), 1); // clazy:exclude=qstring-allocations @@ -85,7 +85,7 @@ class test_StateGetServiceInformation QCOMPARE(spyAbort.size(), 0); QCOMPARE(mContext->getStatus(), GlobalStatus::Code::No_Error); QCOMPARE(mContext->getSmartEidType(), SmartEidType::APPLET); - QCOMPARE(mContext->getChallengeType(), QString("UUID")); + QCOMPARE(mContext->getChallengeType(), "UUID"_L1); } diff --git a/test/qt/workflows/personalization/test_StateGetSessionId.cpp b/test/qt/workflows/personalization/test_StateGetSessionId.cpp index 1237d28ee..e7863a2d9 100644 --- a/test/qt/workflows/personalization/test_StateGetSessionId.cpp +++ b/test/qt/workflows/personalization/test_StateGetSessionId.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateGetSessionId.h" @@ -14,6 +14,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -42,41 +43,40 @@ class test_StateGetSessionId void test_CheckRequestUrl() { - mContext->setRefreshUrl(QUrl("https://dummy.url.de/refresh")); + mContext->setRefreshUrl(QUrl("https://dummy.url.de/refresh"_L1)); const auto& url = mState->getRequestUrl().toString(); - QCOMPARE(url, QString("https://dummy.url.de/refresh")); + QCOMPARE(url, "https://dummy.url.de/refresh"_L1); } void test_OnNetworkReplyNoValidData_data() { QTest::addColumn("data"); - QTest::addColumn("logMsg"); + QTest::addColumn("logMsg"); - QTest::newRow("empty") << QByteArray() << QString("JSON parsing failed: \"illegal value\""); + QTest::newRow("empty") << QByteArray() << "JSON parsing failed: \"illegal value\""_ba; QTest::newRow("empty object") << QByteArray(R"({ - })") << QString("No valid sessionID to prepare personalization"); + })") << "No valid sessionID to prepare personalization"_ba; QTest::newRow("wrong sessionID type") << QByteArray(R"({ "sessionID": 0 - })") << QString("No valid sessionID to prepare personalization"); + })") << "No valid sessionID to prepare personalization"_ba; QTest::newRow("wrong sessionID value") << QByteArray(R"({ "sessionID": "HelloWorld!" - })") << QString("No valid sessionID to prepare personalization"); + })") << "No valid sessionID to prepare personalization"_ba; } void test_OnNetworkReplyNoValidData() { QFETCH(QByteArray, data); - QFETCH(QString, logMsg); + QFETCH(QByteArray, logMsg); mState->mReply.reset(new MockNetworkReply(data), &QObject::deleteLater); QSignalSpy spyAbort(mState.data(), &StateGetSessionId::fireAbort); - const auto bytes = logMsg.toUtf8(); - QTest::ignoreMessage(QtDebugMsg, bytes.data()); + QTest::ignoreMessage(QtDebugMsg, logMsg.data()); mState->onNetworkReply(); QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus(), GlobalStatus::Code::Workflow_Smart_eID_Authentication_Failed); @@ -118,7 +118,7 @@ class test_StateGetSessionId void test_OnNetworkReplyWrongHttpStatus() { - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); mState->mReply.reset(reply, &QObject::deleteLater); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, 500); reply->setError(QNetworkReply::NetworkError::InternalServerError, QString()); @@ -129,9 +129,9 @@ class test_StateGetSessionId QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus().getStatusCode(), GlobalStatus::Code::Workflow_TrustedChannel_Server_Error); const FailureCode::FailureInfoMap infoMap { - {FailureCode::Info::State_Name, "StateGetSessionId"}, + {FailureCode::Info::State_Name, "StateGetSessionId"_L1}, {FailureCode::Info::Http_Status_Code, QString::number(500)}, - {FailureCode::Info::Network_Error, "Unknown error"} + {FailureCode::Info::Network_Error, "Unknown error"_L1} }; const FailureCode failureCode(FailureCode::Reason::Generic_Provider_Communication_Server_Error, infoMap); QCOMPARE(mState->getContext()->getFailureCode(), failureCode); diff --git a/test/qt/workflows/personalization/test_StateInitializePersonalization.cpp b/test/qt/workflows/personalization/test_StateInitializePersonalization.cpp index c161192a6..34986f750 100644 --- a/test/qt/workflows/personalization/test_StateInitializePersonalization.cpp +++ b/test/qt/workflows/personalization/test_StateInitializePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateInitializePersonalization.h" @@ -19,6 +19,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -32,7 +33,7 @@ class test_StateInitializePersonalization private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -65,7 +66,7 @@ class test_StateInitializePersonalization QSignalSpy spyContinue(&state, &StateInitializePersonalization::fireContinue); setInitializePersonalizationResult({EidServiceResult::ERROR}); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Initialization of personalization failed")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Initialization of personalization failed"_L1)); state.run(); QTRY_COMPARE(spyAbort.size(), 1); // clazy:exclude=qstring-allocations @@ -81,24 +82,24 @@ class test_StateInitializePersonalization void success_data() { QTest::addColumn("type"); - QTest::addColumn("pin"); + QTest::addColumn("pin"); - QTest::newRow("UNKNOWN") << SmartEidType::UNKNOWN << QString(); - QTest::newRow("APPLET") << SmartEidType::APPLET << QString(); - QTest::newRow("NON_APPLET") << SmartEidType::NON_APPLET << QString("123456"); + QTest::newRow("UNKNOWN") << SmartEidType::UNKNOWN << QLatin1String(); + QTest::newRow("APPLET") << SmartEidType::APPLET << QLatin1String(); + QTest::newRow("NON_APPLET") << SmartEidType::NON_APPLET << "123456"_L1; } void success() { QFETCH(SmartEidType, type); - QFETCH(QString, pin); + QFETCH(QLatin1String, pin); setSmartEidStatus(EidStatus::NO_PERSONALIZATION); setInitializePersonalizationResult({EidServiceResult::SUCCESS, std::string("data containing the PIN when Smart-eID is of type HWKeyStore")}); mContext->setServiceInformation(type, QString(), QString()); - mContext->setNewPin(QString("123456")); - mContext->setChallenge(QString("FooBar")); + mContext->setNewPin("123456"_L1); + mContext->setChallenge("FooBar"_L1); StateInitializePersonalization state(mContext); QSignalSpy spyAbort(&state, &StateInitializePersonalization::fireAbort); @@ -110,14 +111,14 @@ class test_StateInitializePersonalization QTRY_COMPARE(spyContinue.size(), 1); // clazy:exclude=qstring-allocations QCOMPARE(spyAbort.size(), 0); QCOMPARE(mContext->getStatus(), GlobalStatus::Code::No_Error); - QCOMPARE(mContext->getPreparePersonalizationData(), QString("data containing the PIN when Smart-eID is of type HWKeyStore")); + QCOMPARE(mContext->getPreparePersonalizationData(), "data containing the PIN when Smart-eID is of type HWKeyStore"_L1); for (const auto& entry : logSpy) { - QVERIFY(!entry.at(0).toString().contains(QLatin1String("data containing the PIN"))); + QVERIFY(!entry.at(0).toString().contains("data containing the PIN"_L1)); } - QCOMPARE(dequeueReceivedParameter(), QString("FooBar")); + QCOMPARE(dequeueReceivedParameter(), "FooBar"_L1); QCOMPARE(dequeueReceivedParameter(), pin); } diff --git a/test/qt/workflows/personalization/test_StateInstallApplet.cpp b/test/qt/workflows/personalization/test_StateInstallApplet.cpp index a53b6f6ac..fa29e62d6 100644 --- a/test/qt/workflows/personalization/test_StateInstallApplet.cpp +++ b/test/qt/workflows/personalization/test_StateInstallApplet.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateInstallApplet.h" @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -28,7 +29,7 @@ class test_StateInstallApplet private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -56,42 +57,42 @@ class test_StateInstallApplet QTest::addRow("SUCCESS") << EidServiceResult::SUCCESS - << QStringList {"Successfully installed Smart-eID"} + << QStringList {"Successfully installed Smart-eID"_L1} << GlobalStatus::Code::No_Error << std::optional(); QTest::addRow("ERROR") << EidServiceResult::ERROR - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Fail); QTest::addRow("UNSUPPORTED") << EidServiceResult::UNSUPPORTED - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Unsupported); QTest::addRow("NFC_NOT_ACTIVATED") << EidServiceResult::NFC_NOT_ACTIVATED - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Nfc_Disabled); QTest::addRow("OVERLOAD_PROTECTION") << EidServiceResult::OVERLOAD_PROTECTION - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Overload); QTest::addRow("UNDER_MAINTENANCE") << EidServiceResult::UNDER_MAINTENANCE - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Maintenance); QTest::addRow("INTEGRITY_CHECK_FAILED") << EidServiceResult::INTEGRITY_CHECK_FAILED - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Integrity_Check_Failed); QTest::addRow("NOT_AUTHENTICATED") << EidServiceResult::NOT_AUTHENTICATED - << QStringList {"Installation of Smart-eID failed"} + << QStringList {"Installation of Smart-eID failed"_L1} << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Install_Smart_Service_Response_Not_Authenticated); } diff --git a/test/qt/workflows/personalization/test_StatePreparePersonalization.cpp b/test/qt/workflows/personalization/test_StatePreparePersonalization.cpp index c71f7184a..c62de6d14 100644 --- a/test/qt/workflows/personalization/test_StatePreparePersonalization.cpp +++ b/test/qt/workflows/personalization/test_StatePreparePersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StatePreparePersonalization.h" @@ -15,7 +15,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -55,15 +55,15 @@ class test_StatePreparePersonalization void test_CheckRequestUrl() { const auto& url = mState->getRequestUrl().toString(); - QCOMPARE(url, QString("https://dummy/preparePersonalization")); + QCOMPARE(url, "https://dummy/preparePersonalization"_L1); } void test_CheckPayload() { - mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003")); - mContext->setPreparePersonalizationData(QString("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE=")); + mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1)); + mContext->setPreparePersonalizationData("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE="_L1); const auto& payload = mState->getPayload(); QJsonParseError jsonError {}; @@ -72,8 +72,8 @@ class test_StatePreparePersonalization const auto obj = json.object(); QCOMPARE(obj.size(), 2); - QCOMPARE(obj.value(QLatin1String("sessionID")).toString(), QString("135a32d8-ccfa-11eb-b8bc-0242ac130003")); - QCOMPARE(obj.value(QLatin1String("preparePersonalizationData")).toString(), QString("UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE=")); + QCOMPARE(obj.value(QLatin1String("sessionID")).toString(), "135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1); + QCOMPARE(obj.value(QLatin1String("preparePersonalizationData")).toString(), "UHJlcGFyZVBlcnNvbmFsaXphdGlvbkRhdGE="_L1); } @@ -84,7 +84,7 @@ class test_StatePreparePersonalization QSignalSpy spyAbort(mState.data(), &StatePreparePersonalization::fireAbort); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("No valid network response")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("No valid network response"_L1)); mState->onNetworkReply(); QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus(), GlobalStatus::Code::Workflow_Server_Incomplete_Information_Provided); @@ -99,7 +99,7 @@ class test_StatePreparePersonalization QSignalSpy spyAbort(mState.data(), &StatePreparePersonalization::fireAbort); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("preparePersonalization failed with statusCode -1")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("preparePersonalization failed with statusCode -1"_L1)); mState->onNetworkReply(); QCOMPARE(spyAbort.count(), 1); QCOMPARE(mContext->getFinalizeStatus(), -1); @@ -116,7 +116,7 @@ class test_StatePreparePersonalization mState->onNetworkReply(); const QString logMsg(logSpy.takeLast().at(0).toString()); - QVERIFY(logMsg.contains("preparePersonalization finished with statusCode 1")); + QVERIFY(logMsg.contains("preparePersonalization finished with statusCode 1"_L1)); QCOMPARE(spyContinue.count(), 1); QCOMPARE(mContext->getFinalizeStatus(), 1); } @@ -129,7 +129,7 @@ class test_StatePreparePersonalization QSignalSpy spyAbort(mState.data(), &StatePreparePersonalization::fireAbort); - QTest::ignoreMessage(QtWarningMsg, QRegularExpression("preparePersonalization failed with statusCode -2")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("preparePersonalization failed with statusCode -2"_L1)); mState->onNetworkReply(); QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus(), GlobalStatus::Code::Workflow_Smart_eID_PrePersonalization_Failed); @@ -145,7 +145,7 @@ class test_StatePreparePersonalization QSignalSpy spyAbort(mState.data(), &StatePreparePersonalization::fireAbort); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("JSON parsing failed: statusCode is missing")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("JSON parsing failed: statusCode is missing"_L1)); mState->onNetworkReply(); QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus(), GlobalStatus::Code::Workflow_Server_Incomplete_Information_Provided); @@ -156,7 +156,7 @@ class test_StatePreparePersonalization void test_OnNetworkReplyWrongHttpStatus() { - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); mState->mReply.reset(reply, &QObject::deleteLater); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, 500); reply->setError(QNetworkReply::NetworkError::InternalServerError, QString()); @@ -167,9 +167,9 @@ class test_StatePreparePersonalization QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus().getStatusCode(), GlobalStatus::Code::Workflow_TrustedChannel_Server_Error); const FailureCode::FailureInfoMap infoMap { - {FailureCode::Info::State_Name, "StatePreparePersonalization"}, + {FailureCode::Info::State_Name, "StatePreparePersonalization"_L1}, {FailureCode::Info::Http_Status_Code, QString::number(500)}, - {FailureCode::Info::Network_Error, "Unknown error"} + {FailureCode::Info::Network_Error, "Unknown error"_L1} }; const FailureCode failureCode(FailureCode::Reason::Generic_Provider_Communication_Server_Error, infoMap); QCOMPARE(mState->getContext()->getFailureCode(), failureCode); @@ -180,8 +180,8 @@ class test_StatePreparePersonalization void test_AvoidLoggingOfTheRequest() { - mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003")); - mContext->setPreparePersonalizationData(QString("data containing the PIN when Smart-eID is of type HWKeyStore")); + mContext->setSessionIdentifier(QUuid("135a32d8-ccfa-11eb-b8bc-0242ac130003"_L1)); + mContext->setPreparePersonalizationData("data containing the PIN when Smart-eID is of type HWKeyStore"_L1); mState->onEntry(nullptr); mNetworkManager->setNextReply(new MockNetworkReply(QByteArrayLiteral(R"({ "statusCode": 1 })"))); diff --git a/test/qt/workflows/personalization/test_StateStartPaosPersonalizationResponse.cpp b/test/qt/workflows/personalization/test_StateStartPaosPersonalizationResponse.cpp index c375d67b7..e070fa8da 100644 --- a/test/qt/workflows/personalization/test_StateStartPaosPersonalizationResponse.cpp +++ b/test/qt/workflows/personalization/test_StateStartPaosPersonalizationResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2022-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2022-2024 Governikus GmbH & Co. KG, Germany */ #include "TestFileHelper.h" @@ -10,6 +10,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -75,7 +76,7 @@ class test_StateStartPaosPersonalizationResponse void testPersonalization_data() { - const auto& dateFormat = "d. MMMM yyyy"; + const auto& dateFormat = "d. MMMM yyyy"_L1; QTest::addColumn("finalizeStatus"); QTest::addColumn("restrictionDate"); @@ -124,7 +125,7 @@ class test_StateStartPaosPersonalizationResponse QFETCH(QByteArray, resultContent); QFETCH(QByteArray, outputsContent); - QByteArray content = TestFileHelper::readFile(":/paos/StartPAOSResponse_template.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/StartPAOSResponse_template.xml"_L1); content.replace("", resultContent); content.replace("", outputsContent); diff --git a/test/qt/workflows/personalization/test_StateTransmitPersonalization.cpp b/test/qt/workflows/personalization/test_StateTransmitPersonalization.cpp index 3e5208fac..b28cb76b7 100644 --- a/test/qt/workflows/personalization/test_StateTransmitPersonalization.cpp +++ b/test/qt/workflows/personalization/test_StateTransmitPersonalization.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateTransmitPersonalization.h" @@ -18,7 +18,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -32,7 +32,7 @@ class test_StateTransmitPersonalization private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -48,7 +48,7 @@ class test_StateTransmitPersonalization void init() { mContext = QSharedPointer::create(QString()); - QByteArray content = TestFileHelper::readFile(":/paos/Transmit.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit.xml"_L1); QSharedPointer transmit(static_cast(TransmitParser().parse(content))); QVERIFY(!transmit.isNull()); mContext->setTransmit(transmit); @@ -114,7 +114,7 @@ class test_StateTransmitPersonalization void performPersonalizationSuccess() { - QByteArray content = TestFileHelper::readFile(":/paos/Transmit2.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/Transmit2.xml"_L1); QSharedPointer transmit(static_cast(TransmitParser().parse(content))); QVERIFY(!transmit.isNull()); mContext->setTransmit(transmit); diff --git a/test/qt/workflows/personalization/test_StateUpdateSupportInfo.cpp b/test/qt/workflows/personalization/test_StateUpdateSupportInfo.cpp index c020c7e67..e7bb2e2ca 100644 --- a/test/qt/workflows/personalization/test_StateUpdateSupportInfo.cpp +++ b/test/qt/workflows/personalization/test_StateUpdateSupportInfo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateUpdateSupportInfo.h" @@ -12,7 +12,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -28,7 +28,7 @@ class test_StateUpdateSupportInfo private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -50,7 +50,7 @@ class test_StateUpdateSupportInfo void run_data() { QTest::addColumn("updateSupportInfo"); - QTest::addColumn("logEntry"); + QTest::addColumn("logEntry"); QTest::addColumn("statusCode"); QTest::addColumn>("failureCode"); QTest::addColumn("signal"); @@ -58,43 +58,43 @@ class test_StateUpdateSupportInfo // EidServiceResult tests QTest::addRow("ERROR") << EidSupportStatusResult {EidServiceResult::ERROR, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"ERROR\" 0x33000000") + << "updateSupportInfo() failed with \"ERROR\" 0x33000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Fail) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("UNSUPPORTED") << EidSupportStatusResult {EidServiceResult::UNSUPPORTED, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"UNSUPPORTED\" 0x34000000") + << "updateSupportInfo() failed with \"UNSUPPORTED\" 0x34000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Unsupported) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("OVERLOAD_PROTECTION") << EidSupportStatusResult {EidServiceResult::OVERLOAD_PROTECTION, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"OVERLOAD_PROTECTION\" 0x35000000") + << "updateSupportInfo() failed with \"OVERLOAD_PROTECTION\" 0x35000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Overload) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("UNDER_MAINTENANCE") << EidSupportStatusResult {EidServiceResult::UNDER_MAINTENANCE, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"UNDER_MAINTENANCE\" 0x36000000") + << "updateSupportInfo() failed with \"UNDER_MAINTENANCE\" 0x36000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Maintenance) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("NFC_NOT_ACTIVATED") << EidSupportStatusResult {EidServiceResult::NFC_NOT_ACTIVATED, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"NFC_NOT_ACTIVATED\" 0x37000000") + << "updateSupportInfo() failed with \"NFC_NOT_ACTIVATED\" 0x37000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Nfc_Disabled) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("INTEGRITY_CHECK_FAILED") << EidSupportStatusResult {EidServiceResult::INTEGRITY_CHECK_FAILED, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"INTEGRITY_CHECK_FAILED\" 0x38000000") + << "updateSupportInfo() failed with \"INTEGRITY_CHECK_FAILED\" 0x38000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Integrity_Check_Failed) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("NOT_AUTHENTICATED") << EidSupportStatusResult {EidServiceResult::NOT_AUTHENTICATED, EidSupportStatus::AVAILABLE} - << QString("updateSupportInfo() failed with \"NOT_AUTHENTICATED\" 0x39000000") + << "updateSupportInfo() failed with \"NOT_AUTHENTICATED\" 0x39000000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Service_Response_Not_Authenticated) << SIGNAL(fireAbort(const FailureCode&)); @@ -102,31 +102,31 @@ class test_StateUpdateSupportInfo // EidSupportStatus tests QTest::addRow("UNAVAILABLE") << EidSupportStatusResult {EidServiceResult::SUCCESS, EidSupportStatus::UNAVAILABLE} - << QString("getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UNAVAILABLE\" 0x400010") + << "getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UNAVAILABLE\" 0x400010"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Call_Failed) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("AVAILABLE") << EidSupportStatusResult {EidServiceResult::SUCCESS, EidSupportStatus::AVAILABLE} - << QString("getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"AVAILABLE\" 0x400020") + << "getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"AVAILABLE\" 0x400020"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Call_Failed) << SIGNAL(fireAbort(const FailureCode&)); QTest::addRow("UP_TO_DATE") << EidSupportStatusResult {EidServiceResult::SUCCESS, EidSupportStatus::UP_TO_DATE} - << QString("getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UP_TO_DATE\" 0x400040") + << "getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UP_TO_DATE\" 0x400040"_ba << GlobalStatus::Code::No_Error << std::optional() << SIGNAL(fireContinue()); QTest::addRow("UPDATE_AVAILABLE") << EidSupportStatusResult {EidServiceResult::SUCCESS, EidSupportStatus::UPDATE_AVAILABLE} - << QString("getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UPDATE_AVAILABLE\" 0x400030") + << "getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"UPDATE_AVAILABLE\" 0x400030"_ba << GlobalStatus::Code::No_Error << std::optional() << SIGNAL(fireUpdateAvailable()); QTest::addRow("INTERNAL_ERROR") << EidSupportStatusResult {EidServiceResult::SUCCESS, EidSupportStatus::INTERNAL_ERROR} - << QString("getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"INTERNAL_ERROR\" 0x2100000") + << "getSmartEidSupportInfo() finished with result \"SUCCESS\" 0x0 and status \"INTERNAL_ERROR\" 0x2100000"_ba << GlobalStatus::Code::Workflow_Smart_eID_Applet_Preparation_Failed << std::optional(FailureCode::Reason::Update_Support_Info_Call_Failed) << SIGNAL(fireAbort(const FailureCode&)); @@ -136,7 +136,7 @@ class test_StateUpdateSupportInfo void run() { QFETCH(EidSupportStatusResult, updateSupportInfo); - QFETCH(QString, logEntry); + QFETCH(QByteArray, logEntry); QFETCH(GlobalStatus::Code, statusCode); QFETCH(std::optional, failureCode); QFETCH(QString, signal); @@ -148,7 +148,7 @@ class test_StateUpdateSupportInfo StateUpdateSupportInfo state(context); QSignalSpy spy(&state, qPrintable(signal)); - QTest::ignoreMessage(QtDebugMsg, logEntry.toUtf8().data()); + QTest::ignoreMessage(QtDebugMsg, logEntry.data()); state.run(); QTRY_COMPARE(spy.size(), 1); // clazy:exclude=qstring-allocations diff --git a/test/qt/workflows/selfauth/test_SelfAuthenticationData.cpp b/test/qt/workflows/selfauth/test_SelfAuthenticationData.cpp index 9eedf51c5..35b20e315 100644 --- a/test/qt/workflows/selfauth/test_SelfAuthenticationData.cpp +++ b/test/qt/workflows/selfauth/test_SelfAuthenticationData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; char* toString(const SelfAuthenticationData::OrderedSelfData& pData) @@ -65,10 +66,10 @@ class test_SelfAuthenticationData void dateFormat() { SelfAuthenticationData::OrderedSelfData expected; - expected << qMakePair(QString("Date of birth"), QString("xx.xx.1946")); - expected << qMakePair(QString("Date of expiry"), QString("xx.11.2029")); + expected << qMakePair("Date of birth"_L1, "xx.xx.1946"_L1); + expected << qMakePair("Date of expiry"_L1, "xx.11.2029"_L1); - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataDateFormat.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataDateFormat.json"_L1); const SelfAuthenticationData selfAuthenticationData(data); QVERIFY(selfAuthenticationData.isValid()); QVERIFY(selfAuthenticationData.getDateTime().isValid()); @@ -79,22 +80,22 @@ class test_SelfAuthenticationData void orderedSelfData() { SelfAuthenticationData::OrderedSelfData expected; - expected << qMakePair(QString("Family name"), QStringLiteral("von Drebenbusch-Dalgo\u00DFen")); - expected << qMakePair(QString("Birth name"), QStringLiteral("Wei\u00dF")); - expected << qMakePair(QString("Given name(s)"), QStringLiteral("Hans-G\u00FCnther")); - expected << qMakePair(QString("Doctoral degree"), QString("Dr.eh.Dr.")); - expected << qMakePair(QString("Date of birth"), QString("25.01.1946")); - expected << qMakePair(QString("Place of birth"), QString("BREMERHAVEN")); - expected << qMakePair(QString("Address"), QString("WEG NR.12 8E")); - expected << qMakePair(QString(), QString("22043 HAMBURG")); - expected << qMakePair(QString(), QString("D")); - expected << qMakePair(QString("Document type"), QString("ID")); - expected << qMakePair(QString("Nationality"), QString("D")); - expected << qMakePair(QString("Religious / artistic name"), QStringLiteral("Freiherr zu M\u00F6ckern-Windensberg")); - expected << qMakePair(QString("Issuing country"), QString("D")); - expected << qMakePair(QString("Date of expiry"), QString("30.11.2029")); - - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataID.json"); + expected << qMakePair("Family name"_L1, QStringLiteral("von Drebenbusch-Dalgo\u00DFen")); + expected << qMakePair("Birth name"_L1, QStringLiteral("Wei\u00dF")); + expected << qMakePair("Given name(s)"_L1, QStringLiteral("Hans-G\u00FCnther")); + expected << qMakePair("Doctoral degree"_L1, "Dr.eh.Dr."_L1); + expected << qMakePair("Date of birth"_L1, "25.01.1946"_L1); + expected << qMakePair("Place of birth"_L1, "BREMERHAVEN"_L1); + expected << qMakePair("Address"_L1, "WEG NR.12 8E"_L1); + expected << qMakePair(QString(), "22043 HAMBURG"_L1); + expected << qMakePair(QString(), "D"_L1); + expected << qMakePair("Document type"_L1, "ID"_L1); + expected << qMakePair("Nationality"_L1, "D"_L1); + expected << qMakePair("Religious / artistic name"_L1, QStringLiteral("Freiherr zu M\u00F6ckern-Windensberg")); + expected << qMakePair("Issuing country"_L1, "D"_L1); + expected << qMakePair("Date of expiry"_L1, "30.11.2029"_L1); + + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataID.json"_L1); SelfAuthenticationData selfAuthenticationData(data); QVERIFY(selfAuthenticationData.isValid()); QVERIFY(selfAuthenticationData.getDateTime().isValid()); @@ -104,72 +105,72 @@ class test_SelfAuthenticationData void parsedValues() { - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationData.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationData.json"_L1); SelfAuthenticationData selfAuthenticationData(data); QVERIFY(selfAuthenticationData.isValid()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfExpiry), QString("2020-10-31+01:00")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), QString("TA")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), QString("D")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::Nationality), QString("AZE")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfExpiry), "2020-10-31+01:00"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), "TA"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), "D"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::Nationality), "AZE"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::GivenNames), QStringLiteral("ANDR\u00c9")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), QString("MUSTERMANN")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), "MUSTERMANN"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::ArtisticName), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::AcademicTitle), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::BirthName), QString()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), QString("1981-06-17+02:00")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfBirth), QString("FRANKFURT (ODER)")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), "1981-06-17+02:00"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfBirth), "FRANKFURT (ODER)"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceStreet), QStringLiteral("EHM-WELK-STRA\u00dfE 33")); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCity), QStringLiteral("L\u00dcBBENAU/SPREEWALD")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCountry), QString("D")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceZipCode), QString("03222")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCountry), "D"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceZipCode), "03222"_L1); } void parsedValuesNoAddress() { - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoAddress.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoAddress.json"_L1); SelfAuthenticationData selfAuthenticationData(data); QVERIFY(selfAuthenticationData.isValid()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), QString("TP")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), QString("D")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::GivenNames), QString("KARL")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), QString("HILLEBRANDT")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), "TP"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), "D"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::GivenNames), "KARL"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), "HILLEBRANDT"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::ArtisticName), QStringLiteral("GRAF V. L\u00DDSKY")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::AcademicTitle), QString("DR.HC.")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::BirthName), QString("This data has not been stored in this chip generation.")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), QString("1952-06-17+01:00")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfBirth), QString("TRIER")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::AcademicTitle), "DR.HC."_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::BirthName), "This data has not been stored in this chip generation."_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), "1952-06-17+01:00"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfBirth), "TRIER"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceStreet), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCountry), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceZipCode), QString()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceNoPlaceInfo), QString("keine Hauptwohnung in Deutschland")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceNoPlaceInfo), "keine Hauptwohnung in Deutschland"_L1); } void parsedValuesNoStreet() { - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoStreet.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationDataNoStreet.json"_L1); SelfAuthenticationData selfAuthenticationData(data); QVERIFY(selfAuthenticationData.isValid()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), QString("TP")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), QString("D")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::GivenNames), QString("ANNEKATHRIN")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), QString("LERCH")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DocumentType), "TP"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::IssuingState), "D"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::GivenNames), "ANNEKATHRIN"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::FamilyNames), "LERCH"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::ArtisticName), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::AcademicTitle), QString()); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::BirthName), QString()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), QString("1976-07-05+01:00")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::DateOfBirth), "1976-07-05+01:00"_L1); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfBirth), QStringLiteral("BAD K\u00D6NIGSHOFEN I. GRABFELD")); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCity), QStringLiteral("L\u00DCBBENAU/SPREEWALD")); QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceStreet), QString()); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCountry), QString("D")); - QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceZipCode), QString("06108")); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceCountry), "D"_L1); + QCOMPARE(selfAuthenticationData.getValue(SelfAuthData::PlaceOfResidenceZipCode), "06108"_L1); } diff --git a/test/qt/workflows/states/test_StateCertificateDescriptionCheck.cpp b/test/qt/workflows/states/test_StateCertificateDescriptionCheck.cpp index 8dd8296ca..ebb803f7e 100644 --- a/test/qt/workflows/states/test_StateCertificateDescriptionCheck.cpp +++ b/test/qt/workflows/states/test_StateCertificateDescriptionCheck.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateCertificateDescriptionCheck.h" @@ -9,6 +9,7 @@ #include "context/AuthContext.h" #include "states/StateBuilder.h" +#include "CertificateHelper.h" #include "TestAuthContext.h" #include "TestFileHelper.h" @@ -16,6 +17,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -29,8 +31,8 @@ class test_StateCertificateDescriptionCheck private Q_SLOTS: void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); - mAuthContext->setTcTokenUrl(QUrl("https://test.governikus-eid.de:443/Autent-DemoApplication/RequestServlet?provider=demo_epa_can&redirect=true")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); + mAuthContext->setTcTokenUrl(QUrl("https://test.governikus-eid.de:443/Autent-DemoApplication/RequestServlet?provider=demo_epa_can&redirect=true"_L1)); mState.reset(StateBuilder::createState(mAuthContext)); @@ -77,8 +79,8 @@ class test_StateCertificateDescriptionCheck void nonMatchingDescription() { - QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"); - auto cert = CVCertificate::fromHex(source); + QByteArray source = TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"_L1); + auto cert = CertificateHelper::fromHex(source); mAuthContext->initAccessRightManager(cert); QSignalSpy spy(mState.data(), &StateCertificateDescriptionCheck::fireAbort); @@ -104,7 +106,7 @@ class test_StateCertificateDescriptionCheck void subjectUrlNoSameOrigin() { - mAuthContext->setTcTokenUrl(QUrl("https://dev-demo.governikus-eid.de:8442/Autent-DemoApplication/RequestServlet;jsessionid=14w5aKuENyd2D4ZsMmuaeX2g")); + mAuthContext->setTcTokenUrl(QUrl("https://dev-demo.governikus-eid.de:8442/Autent-DemoApplication/RequestServlet;jsessionid=14w5aKuENyd2D4ZsMmuaeX2g"_L1)); QSignalSpy spy(mState.data(), &StateCertificateDescriptionCheck::fireAbort); diff --git a/test/qt/workflows/states/test_StateChangePin.cpp b/test/qt/workflows/states/test_StateChangePin.cpp index 970df135f..7d0f8776d 100644 --- a/test/qt/workflows/states/test_StateChangePin.cpp +++ b/test/qt/workflows/states/test_StateChangePin.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,6 +13,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockEstablishPaceChannelCommand @@ -117,20 +118,23 @@ class test_StateChangePin QTest::addColumn("fireRetry"); QTest::addColumn>("failureCode"); - QTest::newRow("1") << CardReturnCode::OK << QByteArray() << GlobalStatus::Code::Card_Unexpected_Transmit_Status << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unexpected_Transmit_Status); - QTest::newRow("2") << CardReturnCode::OK << QByteArray("9000") << GlobalStatus::Code::No_Error << 1 << 0 << 0 << std::optional(); - QTest::newRow("3") << CardReturnCode::OK << QByteArray("6400") << GlobalStatus::Code::Card_Input_TimeOut << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Input_Timeout); - QTest::newRow("4") << CardReturnCode::OK << QByteArray("6401") << GlobalStatus::Code::Card_Cancellation_By_User << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_User_Cancelled); - QTest::newRow("5") << CardReturnCode::OK << QByteArray("6402") << GlobalStatus::Code::Card_NewPin_Mismatch << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_New_Pin_Mismatch); - QTest::newRow("6") << CardReturnCode::OK << QByteArray("6403") << GlobalStatus::Code::Card_NewPin_Invalid_Length << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_New_Pin_Invalid_Length); - QTest::newRow("7") << CardReturnCode::INPUT_TIME_OUT << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); - QTest::newRow("8") << CardReturnCode::CANCELLATION_BY_USER << QByteArray() << GlobalStatus::Code::Card_Cancellation_By_User << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Card_User_Cancelled); - QTest::newRow("9") << CardReturnCode::NEW_PIN_MISMATCH << QByteArray() << GlobalStatus::Code::Card_NewPin_Mismatch << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Card_New_Pin_Mismatch); - QTest::newRow("10") << CardReturnCode::NEW_PIN_INVALID_LENGTH << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); - QTest::newRow("11") << CardReturnCode::PROTOCOL_ERROR << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); - QTest::newRow("12") << CardReturnCode::CARD_NOT_FOUND << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); - QTest::newRow("13") << CardReturnCode::COMMAND_FAILED << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); - QTest::newRow("14") << CardReturnCode::PIN_BLOCKED << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); + QTest::newRow("OK") << CardReturnCode::OK << QByteArray() << GlobalStatus::Code::Card_Unexpected_Transmit_Status << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unexpected_Transmit_Status); + QTest::newRow("OK_9000") << CardReturnCode::OK << QByteArray("9000") << GlobalStatus::Code::No_Error << 1 << 0 << 0 << std::optional(); + QTest::newRow("OK_6400") << CardReturnCode::OK << QByteArray("6400") << GlobalStatus::Code::Card_Input_TimeOut << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Input_Timeout); + QTest::newRow("OK_6401") << CardReturnCode::OK << QByteArray("6401") << GlobalStatus::Code::Card_Cancellation_By_User << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_User_Cancelled); + QTest::newRow("OK_6402") << CardReturnCode::OK << QByteArray("6402") << GlobalStatus::Code::Card_NewPin_Mismatch << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_New_Pin_Mismatch); + QTest::newRow("OK_6403") << CardReturnCode::OK << QByteArray("6403") << GlobalStatus::Code::Card_NewPin_Invalid_Length << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_New_Pin_Invalid_Length); + //Should retry + QTest::newRow("CARD_NOT_FOUND") << CardReturnCode::CARD_NOT_FOUND << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); + QTest::newRow("RESPONSE_EMPTY") << CardReturnCode::RESPONSE_EMPTY << QByteArray() << GlobalStatus::Code::No_Error << 0 << 0 << 1 << std::optional(); + //Should abort + QTest::newRow("INPUT_TIME_OUT") << CardReturnCode::INPUT_TIME_OUT << QByteArray() << GlobalStatus::Code::Card_Input_TimeOut << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unrecoverable); + QTest::newRow("CANCELLATION_BY_USER") << CardReturnCode::CANCELLATION_BY_USER << QByteArray() << GlobalStatus::Code::Card_Cancellation_By_User << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Card_User_Cancelled); + QTest::newRow("NEW_PIN_MISMATCH") << CardReturnCode::NEW_PIN_MISMATCH << QByteArray() << GlobalStatus::Code::Card_NewPin_Mismatch << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Card_New_Pin_Mismatch); + QTest::newRow("PROTOCOL_ERROR") << CardReturnCode::PROTOCOL_ERROR << QByteArray() << GlobalStatus::Code::Card_Protocol_Error << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unrecoverable); + QTest::newRow("NEW_PIN_INVALID_LENGTH") << CardReturnCode::NEW_PIN_INVALID_LENGTH << QByteArray() << GlobalStatus::Code::Card_NewPin_Invalid_Length << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unrecoverable); + QTest::newRow("COMMAND_FAILED") << CardReturnCode::COMMAND_FAILED << QByteArray() << GlobalStatus::Code::Card_Communication_Error << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unrecoverable); + QTest::newRow("PIN_BLOCKED") << CardReturnCode::PIN_BLOCKED << QByteArray() << GlobalStatus::Code::Card_Pin_Blocked << 0 << 1 << 0 << std::optional(FailureCode::Reason::Change_Pin_Unrecoverable); } @@ -148,13 +152,13 @@ class test_StateChangePin StateChangePin state(context); const QSharedPointer worker(new MockCardConnectionWorker()); const QSharedPointer command(new MockSetEidPinCommand(worker)); - const ReaderInfo readerInfo("NFC", ReaderManagerPlugInType::NFC); + const ReaderInfo readerInfo("NFC"_L1, ReaderManagerPluginType::NFC); const QSharedPointer connection(new MockCardConnection(readerInfo)); context->setCardConnection(connection); QSignalSpy spyContinue(&state, &StateChangePin::fireContinue); QSignalSpy spyAbort(&state, &StateChangePin::fireAbort); - QSignalSpy spyRetry(&state, &StateChangePin::fireRetry); + QSignalSpy spyRetry(&state, &StateChangePin::fireNoCardConnection); command->setMockReturnCode(returnCode); command->setData(QByteArray::fromHex(response)); @@ -174,9 +178,9 @@ class test_StateChangePin void test_OnSetSmartEidPinDone_data() { - QTest::addColumn("type"); + QTest::addColumn("type"); - const auto& readerTypes = Enum::getList(); + const auto& readerTypes = Enum::getList(); for (const auto& type : readerTypes) { QTest::newRow(getEnumName(type).data()) << type; @@ -186,13 +190,13 @@ class test_StateChangePin void test_OnSetSmartEidPinDone() { - QFETCH(ReaderManagerPlugInType, type); + QFETCH(ReaderManagerPluginType, type); const QSharedPointer context(new ChangePinContext()); StateChangePin state(context); const QSharedPointer worker(new MockCardConnectionWorker()); const QSharedPointer command(new MockSetEidPinCommand(worker)); - const ReaderInfo readerInfo("SMART", type, CardInfo(CardType::SMART_EID)); + const ReaderInfo readerInfo("SMART"_L1, type, CardInfo(CardType::SMART_EID)); const QSharedPointer connection(new MockCardConnection(readerInfo)); context->setCardConnection(connection); diff --git a/test/qt/workflows/states/test_StateCheckRefreshAddress.cpp b/test/qt/workflows/states/test_StateCheckRefreshAddress.cpp index 671bce082..dc1154734 100644 --- a/test/qt/workflows/states/test_StateCheckRefreshAddress.cpp +++ b/test/qt/workflows/states/test_StateCheckRefreshAddress.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateCheckRefreshAddress.h" @@ -16,6 +16,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -79,25 +80,25 @@ class test_StateCheckRefreshAddress void run_data() { QTest::addColumn("redirectUrl"); - QTest::addColumn("tcTokenUrl"); + QTest::addColumn("tcTokenUrl"); QTest::addColumn("messages"); - const QStringList msg1(QString("Invalid RefreshAddress: test")); - const QStringList msg2(QString("Invalid RefreshAddress: http://service.governikus.de/loggedin?7eb39f62")); - const QStringList msg3 = {QString("Subject URL from AT CVC (eService certificate) description: \"https://service.governikus.de\""), QString("Current redirect URL: \"https://service.governikus.de/loggedin?7eb39f62\""), QString("SOP-Check succeeded, abort process.")}; - const QStringList msg4 = {QString("Subject URL from AT CVC (eService certificate) description: \"https://governikus.de\""), QString("Current redirect URL: \"https://service.governikus.de/loggedin?7eb39f62\""), QString("SOP-Check failed, start process.")}; + const QStringList msg1("Invalid RefreshAddress: test"_L1); + const QStringList msg2("Invalid RefreshAddress: http://service.governikus.de/loggedin?7eb39f62"_L1); + const QStringList msg3 = {"Subject URL from AT CVC (eService certificate) description: \"https://service.governikus.de\""_L1, "Current redirect URL: \"https://service.governikus.de/loggedin?7eb39f62\""_L1, "SOP-Check succeeded, abort process."_L1}; + const QStringList msg4 = {"Subject URL from AT CVC (eService certificate) description: \"https://governikus.de\""_L1, "Current redirect URL: \"https://service.governikus.de/loggedin?7eb39f62\""_L1, "SOP-Check failed, start process."_L1}; - QTest::newRow("urlInvalid") << QByteArray("test") << QString() << msg1; - QTest::newRow("notHttps") << QByteArray("http://service.governikus.de/loggedin?7eb39f62") << QString("http://service.governikus.de") << msg2; - QTest::newRow("matchingSameOriginPolicy") << QByteArray("https://service.governikus.de/loggedin?7eb39f62") << QString("https://service.governikus.de") << msg3; - QTest::newRow("notMatchingSameOriginPolicy") << QByteArray("https://service.governikus.de/loggedin?7eb39f62") << QString("https://governikus.de") << msg4; + QTest::newRow("urlInvalid") << QByteArray("test") << QLatin1String() << msg1; + QTest::newRow("notHttps") << QByteArray("http://service.governikus.de/loggedin?7eb39f62") << "http://service.governikus.de"_L1 << msg2; + QTest::newRow("matchingSameOriginPolicy") << QByteArray("https://service.governikus.de/loggedin?7eb39f62") << "https://service.governikus.de"_L1 << msg3; + QTest::newRow("notMatchingSameOriginPolicy") << QByteArray("https://service.governikus.de/loggedin?7eb39f62") << "https://governikus.de"_L1 << msg4; } void run() { QFETCH(QByteArray, redirectUrl); - QFETCH(QString, tcTokenUrl); + QFETCH(QLatin1String, tcTokenUrl); QFETCH(QStringList, messages); QSignalSpy spyContinue(mState.data(), &StateCheckRefreshAddress::fireContinue); @@ -128,7 +129,7 @@ class test_StateCheckRefreshAddress void mappingToCommunicationError() { - const QVector states = QVector() + const QList states = QList() << GlobalStatus::Code::Network_Ssl_Establishment_Error << GlobalStatus::Code::Network_Ssl_Establishment_Error << GlobalStatus::Code::Workflow_Network_Ssl_Connection_Unsupported_Algorithm_Or_Length @@ -151,7 +152,7 @@ class test_StateCheckRefreshAddress void sendGetRequestWithoutAnyAdditionalParameters() { - QUrl redirectUrl("http://localhost:12345/test_StateCheckRefreshAddress/"); + QUrl redirectUrl("http://localhost:12345/test_StateCheckRefreshAddress/"_L1); mAuthContext->setStatus(GlobalStatus::Code::Workflow_Server_Incomplete_Information_Provided); mState->mUrl = redirectUrl; @@ -193,9 +194,9 @@ class test_StateCheckRefreshAddress QVERIFY(!mState->isMatchingSameOriginPolicyInDevMode()); Env::getSingleton()->getGeneralSettings().setDeveloperMode(true); - const QUrl pUrlHttps("https://invalidhost/"); - const QUrl pUrlHttp("http://localhost:12345/test_StateCheckRefreshAddress/"); - const QUrl pSubjectUrl("http://localhost:12345/test_StateCheckRefreshAddress/"); + const QUrl pUrlHttps("https://invalidhost/"_L1); + const QUrl pUrlHttp("http://localhost:12345/test_StateCheckRefreshAddress/"_L1); + const QUrl pSubjectUrl("http://localhost:12345/test_StateCheckRefreshAddress/"_L1); mState->mUrl = pUrlHttps; mState->mSubjectUrl = pSubjectUrl; @@ -211,10 +212,10 @@ class test_StateCheckRefreshAddress void determinateSubjectUrl() { - const QUrl tcTokenUrl("http://invalidhost/"); + const QUrl tcTokenUrl("http://invalidhost/"_L1); mAuthContext->setTcTokenUrl(tcTokenUrl); - QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"); + QByteArray content = TestFileHelper::readFile(":/paos/DIDAuthenticateEAC1.xml"_L1); QSharedPointer eac1(static_cast(DidAuthenticateEac1Parser().parse(content))); SDK_MODE(false); @@ -223,7 +224,7 @@ class test_StateCheckRefreshAddress QCOMPARE(mState->determineSubjectUrl(), tcTokenUrl); mAuthContext->setDidAuthenticateEac1(eac1); - QCOMPARE(mState->determineSubjectUrl(), QUrl("https://test.governikus-eid.de")); + QCOMPARE(mState->determineSubjectUrl(), QUrl("https://test.governikus-eid.de"_L1)); Env::getSingleton()->getGeneralSettings().setDeveloperMode(true); QCOMPARE(mState->determineSubjectUrl(), tcTokenUrl); @@ -265,19 +266,19 @@ class test_StateCheckRefreshAddress QTest::addColumn("redirectUrl"); QTest::addColumn("developerMode"); - QTest::newRow("http service unavailable") << QNetworkReply::NetworkError::ServiceUnavailableError << GlobalStatus::Code::Network_ServiceUnavailable << FailureCode::Reason::Check_Refresh_Address_Service_Unavailable << 503 << QUrl("http://governikus.com/") << false; - QTest::newRow("http internal server error") << QNetworkReply::NetworkError::InternalServerError << GlobalStatus::Code::Network_ServerError << FailureCode::Reason::Check_Refresh_Address_Server_Error << 500 << QUrl("http://governikus.com/") << false; - QTest::newRow("http not found") << QNetworkReply::NetworkError::ContentNotFoundError << GlobalStatus::Code::Network_ClientError << FailureCode::Reason::Check_Refresh_Address_Client_Error << 404 << QUrl("https://governikus.com/") << false; - QTest::newRow("http other error") << QNetworkReply::NetworkError::ProtocolUnknownError << GlobalStatus::Code::Network_Other_Error << FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error << 304 << QUrl("http://governikus.com/") << false; + QTest::newRow("http service unavailable") << QNetworkReply::NetworkError::ServiceUnavailableError << GlobalStatus::Code::Network_ServiceUnavailable << FailureCode::Reason::Check_Refresh_Address_Service_Unavailable << 503 << QUrl("http://governikus.com/"_L1) << false; + QTest::newRow("http internal server error") << QNetworkReply::NetworkError::InternalServerError << GlobalStatus::Code::Network_ServerError << FailureCode::Reason::Check_Refresh_Address_Server_Error << 500 << QUrl("http://governikus.com/"_L1) << false; + QTest::newRow("http not found") << QNetworkReply::NetworkError::ContentNotFoundError << GlobalStatus::Code::Network_ClientError << FailureCode::Reason::Check_Refresh_Address_Client_Error << 404 << QUrl("https://governikus.com/"_L1) << false; + QTest::newRow("http other error") << QNetworkReply::NetworkError::ProtocolUnknownError << GlobalStatus::Code::Network_Other_Error << FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error << 304 << QUrl("http://governikus.com/"_L1) << false; QTest::newRow("timeout") << QNetworkReply::NetworkError::TimeoutError << GlobalStatus::Code::Network_TimeOut << FailureCode::Reason::Check_Refresh_Address_Service_Timeout << 2 << QUrl() << false; - QTest::newRow("proxy error") << QNetworkReply::NetworkError::ProxyNotFoundError << GlobalStatus::Code::Network_Proxy_Error << FailureCode::Reason::Check_Refresh_Address_Proxy_Error << 0 << QUrl("test") << false; - QTest::newRow("ssl error") << QNetworkReply::NetworkError::SslHandshakeFailedError << GlobalStatus::Code::Network_Ssl_Establishment_Error << FailureCode::Reason::Check_Refresh_Address_Fatal_Tls_Error_After_Reply << 1 << QUrl("https://governikus.com/") << false; - QTest::newRow("other error") << QNetworkReply::NetworkError::OperationCanceledError << GlobalStatus::Code::Network_Other_Error << FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error << 2 << QUrl("https://governikus.com/") << false; - QTest::newRow("no error unexpected status") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Expected_Redirect << FailureCode::Reason::Check_Refresh_Address_Invalid_Http_Response << 2 << QUrl("https://governikus.com/") << false; + QTest::newRow("proxy error") << QNetworkReply::NetworkError::ProxyNotFoundError << GlobalStatus::Code::Network_Proxy_Error << FailureCode::Reason::Check_Refresh_Address_Proxy_Error << 0 << QUrl("test"_L1) << false; + QTest::newRow("ssl error") << QNetworkReply::NetworkError::SslHandshakeFailedError << GlobalStatus::Code::Network_Ssl_Establishment_Error << FailureCode::Reason::Check_Refresh_Address_Fatal_Tls_Error_After_Reply << 1 << QUrl("https://governikus.com/"_L1) << false; + QTest::newRow("other error") << QNetworkReply::NetworkError::OperationCanceledError << GlobalStatus::Code::Network_Other_Error << FailureCode::Reason::Check_Refresh_Address_Unknown_Network_Error << 2 << QUrl("https://governikus.com/"_L1) << false; + QTest::newRow("no error unexpected status") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Expected_Redirect << FailureCode::Reason::Check_Refresh_Address_Invalid_Http_Response << 2 << QUrl("https://governikus.com/"_L1) << false; QTest::newRow("no error empty url") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Empty_Redirect_Url << FailureCode::Reason::Check_Refresh_Address_Empty << 302 << QUrl() << false; - QTest::newRow("no error invalid url") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Malformed_Redirect_Url << FailureCode::Reason::Check_Refresh_Address_Invalid_Url << 302 << QUrl("://://") << false; - QTest::newRow("no error http") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Invalid_Scheme << FailureCode::Reason::Check_Refresh_Address_No_Https_Scheme << 302 << QUrl("http://governikus.com/") << false; - QTest::newRow("no error http developer mode") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::No_Error << FailureCode::Reason::Check_Refresh_Address_No_Https_Scheme << 302 << QUrl("http://governikus.com/") << true; + QTest::newRow("no error invalid url") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Malformed_Redirect_Url << FailureCode::Reason::Check_Refresh_Address_Invalid_Url << 302 << QUrl("://://"_L1) << false; + QTest::newRow("no error http") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::Workflow_Network_Invalid_Scheme << FailureCode::Reason::Check_Refresh_Address_No_Https_Scheme << 302 << QUrl("http://governikus.com/"_L1) << false; + QTest::newRow("no error http developer mode") << QNetworkReply::NetworkError::NoError << GlobalStatus::Code::No_Error << FailureCode::Reason::Check_Refresh_Address_No_Https_Scheme << 302 << QUrl("http://governikus.com/"_L1) << true; } @@ -317,7 +318,7 @@ class test_StateCheckRefreshAddress { SDK_MODE(false); Env::getSingleton()->getGeneralSettings().setDeveloperMode(true); - const QUrl url("http://governikus.de/"); + const QUrl url("http://governikus.de/"_L1); mState->mUrl = url; QTest::ignoreMessage(QtWarningMsg, "Refresh URL is http only. Certificate check skipped."); mState->fetchServerCertificate(); @@ -327,7 +328,7 @@ class test_StateCheckRefreshAddress void fetchServerCertificate_AlreadyVerified() { Env::getSingleton()->getGeneralSettings().setDeveloperMode(false); - const QUrl url("https://governikus.de/"); + const QUrl url("https://governikus.de/"_L1); mState->mUrl = url; mState->mVerifiedRefreshUrlHosts.insert(0, url); QTest::ignoreMessage(QtDebugMsg, "SSL certificate already collected for QUrl(\"https://governikus.de/\")"); @@ -338,7 +339,7 @@ class test_StateCheckRefreshAddress void fetchServerCertificate() { Env::getSingleton()->getGeneralSettings().setDeveloperMode(false); - const QUrl url("https://governikus.de/"); + const QUrl url("https://governikus.de/"_L1); mState->mUrl = url; QTest::ignoreMessage(QtDebugMsg, "Fetch TLS certificate for URL QUrl(\"https://governikus.de/\")"); mState->fetchServerCertificate(); @@ -347,7 +348,7 @@ class test_StateCheckRefreshAddress void doneSuccess() { - const QUrl url("https://governikus.de/"); + const QUrl url("https://governikus.de/"_L1); mState->mUrl = url; QSignalSpy spy(mState.data(), &StateCheckRefreshAddress::fireContinue); diff --git a/test/qt/workflows/states/test_StateConnectCard.cpp b/test/qt/workflows/states/test_StateConnectCard.cpp index 40b0037e0..59ecabce9 100644 --- a/test/qt/workflows/states/test_StateConnectCard.cpp +++ b/test/qt/workflows/states/test_StateConnectCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,6 +16,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StateConnectCard @@ -23,13 +24,15 @@ class test_StateConnectCard { Q_OBJECT QSharedPointer mState; - QSharedPointer mContext; + QSharedPointer mContext; ReaderInfo mReaderInfo; private: - QSharedPointer createCardConnection(QThread& workerThread) + QSharedPointer createCardConnection(QThread& workerThread, const QString& readerName) { - QSharedPointer connectionWorker(new MockCardConnectionWorker()); + MockReader* reader = new MockReader(); + reader->setReaderInfo(ReaderInfo(readerName, ReaderManagerPluginType::NFC, CardInfo(CardType::EID_CARD))); + QSharedPointer connectionWorker(new MockCardConnectionWorker(reader)); connectionWorker->moveToThread(&workerThread); return QSharedPointer(new CardConnection(connectionWorker)); } @@ -62,7 +65,7 @@ class test_StateConnectCard void init() { - mReaderInfo = ReaderInfo(QString("test"), ReaderManagerPlugInType::UNKNOWN, CardInfo(CardType::EID_CARD)); + mReaderInfo = ReaderInfo("test"_L1, ReaderManagerPluginType::UNKNOWN, CardInfo(CardType::EID_CARD)); mContext.reset(new TestWorkflowContext()); mState.reset(new StateConnectCard(mContext)); @@ -76,12 +79,27 @@ class test_StateConnectCard } + void test_OnCommandDone_data() + { + QTest::addColumn("eidTypeMismatch"); + + QTest::addRow("No eID type mismatch") << false; + QTest::addRow("eID type mismatch") << true; + } + + void test_OnCommandDone() { + QFETCH(bool, eidTypeMismatch); + if (eidTypeMismatch) + { + mContext->setAcceptedEidTypes({AcceptedEidType::SE_ENDORSED}); + } + QThread workerThread; workerThread.start(); - const QString rName("reader name"); + const QString rName("reader name"_L1); QSignalSpy spyContinue(mState.data(), &StateConnectCard::fireContinue); QSignalSpy spyAbort(mState.data(), &StateConnectCard::fireAbort); @@ -94,10 +112,10 @@ class test_StateConnectCard QTest::ignoreMessage(QtDebugMsg, "Card connection command completed"); QTest::ignoreMessage(QtDebugMsg, "Card connection was successful"); - const auto& cardConnection = createCardConnection(workerThread); + const auto& cardConnection = createCardConnection(workerThread, rName); mState->onCommandDone(createCardConnectionCommand(rName, cardConnection)); QCOMPARE(mContext->getCardConnection(), cardConnection); - QCOMPARE(spyContinue.count(), 1); + QCOMPARE(spyContinue.count(), eidTypeMismatch ? 0 : 1); workerThread.quit(); workerThread.wait(); @@ -110,7 +128,7 @@ class test_StateConnectCard workerThread.start(); const auto info = ReaderInfo(QStringLiteral("name")); - const auto cardConnection = createCardConnection(workerThread); + const auto cardConnection = createCardConnection(workerThread, info.getName()); QSignalSpy spy(mState.data(), &StateConnectCard::fireRetry); @@ -143,7 +161,7 @@ class test_StateConnectCard mState->onEntry(nullptr); - Q_EMIT mContext->fireReaderPlugInTypesChanged(); + Q_EMIT mContext->fireReaderPluginTypesChanged(); QCOMPARE(spyRetry.count(), 1); } diff --git a/test/qt/workflows/states/test_StateDestroyPace.cpp b/test/qt/workflows/states/test_StateDestroyPace.cpp index ee61803be..7c792c228 100644 --- a/test/qt/workflows/states/test_StateDestroyPace.cpp +++ b/test/qt/workflows/states/test_StateDestroyPace.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateDestroyPace.h" diff --git a/test/qt/workflows/states/test_StateDidAuthenticateEac1.cpp b/test/qt/workflows/states/test_StateDidAuthenticateEac1.cpp index c13098bc0..c77750f4f 100644 --- a/test/qt/workflows/states/test_StateDidAuthenticateEac1.cpp +++ b/test/qt/workflows/states/test_StateDidAuthenticateEac1.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockEstablishPaceChannelCommand @@ -46,7 +47,7 @@ class test_StateDidAuthenticateEac1 private Q_SLOTS: void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); } diff --git a/test/qt/workflows/states/test_StateDidAuthenticateEac2.cpp b/test/qt/workflows/states/test_StateDidAuthenticateEac2.cpp index 814cd8dc2..f03d7e8d1 100644 --- a/test/qt/workflows/states/test_StateDidAuthenticateEac2.cpp +++ b/test/qt/workflows/states/test_StateDidAuthenticateEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockDidAuthenticateEAC2Command @@ -50,7 +51,7 @@ class test_StateDidAuthenticateEac2 private Q_SLOTS: void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mState.reset(new StateDidAuthenticateEac2(mAuthContext)); workerThread.start(); } diff --git a/test/qt/workflows/states/test_StateEnterPacePassword.cpp b/test/qt/workflows/states/test_StateEnterPacePassword.cpp index 3d7b922d2..ce052fb15 100644 --- a/test/qt/workflows/states/test_StateEnterPacePassword.cpp +++ b/test/qt/workflows/states/test_StateEnterPacePassword.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2019-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateEnterPacePassword.h" @@ -8,6 +8,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -21,7 +22,7 @@ class test_StateEnterPacePassword private Q_SLOTS: void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mState.reset(new StateEnterPacePassword(mAuthContext)); } @@ -43,18 +44,6 @@ class test_StateEnterPacePassword } - void test_RunContextError() - { - mAuthContext->setStatus(GlobalStatus::Code::Card_Cancellation_By_User); - mAuthContext->setFailureCode(FailureCode::Reason::User_Cancelled); - QSignalSpy spyPropagateAbort(mState.data(), &StateEnterPacePassword::firePropagateAbort); - - mState->run(); - - QCOMPARE(spyPropagateAbort.count(), 1); - } - - }; QTEST_GUILESS_MAIN(test_StateEnterPacePassword) diff --git a/test/qt/workflows/states/test_StateEstablishPaceChannel.cpp b/test/qt/workflows/states/test_StateEstablishPaceChannel.cpp index 5cbb88be3..9ab9f6d66 100644 --- a/test/qt/workflows/states/test_StateEstablishPaceChannel.cpp +++ b/test/qt/workflows/states/test_StateEstablishPaceChannel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateEstablishPaceChannel.h" @@ -12,6 +12,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockEstablishPaceChannelCommand @@ -60,7 +61,7 @@ class test_StateEstablishPaceChannel void init() { mWorkerThread.start(); - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mState.reset(StateBuilder::createState(mAuthContext)); } @@ -105,7 +106,7 @@ class test_StateEstablishPaceChannel const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const QString password("0000000"); + const QString password("0000000"_L1); mAuthContext->setPin(password); mAuthContext->setCardConnection(connection); @@ -156,7 +157,7 @@ class test_StateEstablishPaceChannel const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cInfo(CardType::NONE, QSharedPointer(), 3, false, false); + const CardInfo cInfo(CardType::NONE, FileRef(), QSharedPointer(), 3, false, false); ReaderInfo rInfo; rInfo.setCardInfo(cInfo); Q_EMIT worker->fireReaderInfoChanged(rInfo); @@ -164,7 +165,7 @@ class test_StateEstablishPaceChannel QSignalSpy spyAbort(mState.data(), &AbstractState::fireAbort); - QTest::ignoreMessage(QtInfoMsg, "Cancellation by user"); + QTest::ignoreMessage(QtInfoMsg, "Cancellation by user in \"StateEstablishPaceChannel\""); mState->onUserCancelled(); QCOMPARE(mAuthContext->getStatus().getStatusCode(), GlobalStatus::Code::Workflow_Cancellation_By_User); QCOMPARE(mAuthContext->getLastPaceResult(), CardReturnCode::CANCELLATION_BY_USER); @@ -182,16 +183,17 @@ class test_StateEstablishPaceChannel QTest::addColumn>("failureCode"); QTest::newRow("PIN_OK") << PacePasswordId::PACE_PIN << 3 << CardReturnCode::OK << CardReturnCode::OK << false << std::optional(); - QTest::newRow("PIN_PUK_INOPERATIVE") << PacePasswordId::PACE_PIN << 1 << CardReturnCode::PUK_INOPERATIVE << CardReturnCode::PUK_INOPERATIVE << false << std::optional(FailureCode::Reason::Establish_Pace_Channel_Puk_Inoperative); QTest::newRow("PIN_CANCELLATION_BY_USER") << PacePasswordId::PACE_PIN << 2 << CardReturnCode::CANCELLATION_BY_USER << CardReturnCode::CANCELLATION_BY_USER << false << std::optional(FailureCode::Reason::Establish_Pace_Channel_User_Cancelled); QTest::newRow("PIN_INVALID_PIN_RETRY_COUNTER_3") << PacePasswordId::PACE_PIN << 3 << CardReturnCode::INVALID_PIN << CardReturnCode::INVALID_PIN << false << std::optional(); - QTest::newRow("PIN_INVALID_PIN_RETRY_COUNTER_2") << PacePasswordId::PACE_PIN << 2 << CardReturnCode::INVALID_PIN << CardReturnCode::INVALID_PIN_2 << false << std::optional(); - QTest::newRow("PIN_INVALID_PIN_RETRY_COUNTER_1") << PacePasswordId::PACE_PIN << 1 << CardReturnCode::INVALID_PIN << CardReturnCode::INVALID_PIN_3 << false << std::optional(); + QTest::newRow("PIN_INVALID_PIN_RETRY_COUNTER_2") << PacePasswordId::PACE_PIN << 2 << CardReturnCode::INVALID_PIN_2 << CardReturnCode::INVALID_PIN_2 << false << std::optional(); + QTest::newRow("PIN_INVALID_PIN_RETRY_COUNTER_1") << PacePasswordId::PACE_PIN << 1 << CardReturnCode::INVALID_PIN_3 << CardReturnCode::INVALID_PIN_3 << false << std::optional(); QTest::newRow("CAN_OK_CAN_ALLOWED") << PacePasswordId::PACE_CAN << 3 << CardReturnCode::OK << CardReturnCode::OK << true << std::optional(); - QTest::newRow("CAN_OK") << PacePasswordId::PACE_CAN << 2 << CardReturnCode::OK << CardReturnCode::OK << false << std::optional(); + QTest::newRow("CAN_OK") << PacePasswordId::PACE_CAN << 2 << CardReturnCode::OK << CardReturnCode::OK_CAN << false << std::optional(); QTest::newRow("CAN_CANCELLATION_BY_USER") << PacePasswordId::PACE_CAN << 2 << CardReturnCode::CANCELLATION_BY_USER << CardReturnCode::CANCELLATION_BY_USER << true << std::optional(FailureCode::Reason::Establish_Pace_Channel_User_Cancelled); QTest::newRow("PUK_OK") << PacePasswordId::PACE_PUK << 0 << CardReturnCode::OK << CardReturnCode::OK_PUK << false << std::optional(); QTest::newRow("PUK_INVALID_PIN_RETRY_COUNTER_1") << PacePasswordId::PACE_PUK << 0 << CardReturnCode::INVALID_PIN << CardReturnCode::INVALID_PIN << false << std::optional(); + QTest::newRow("MRZ") << PacePasswordId::PACE_MRZ << 3 << CardReturnCode::OK << CardReturnCode::OK << false << std::optional(FailureCode::Reason::Establish_Pace_Channel_Unknown_Password_Id); + QTest::newRow("UNKNOWN") << PacePasswordId::UNKNOWN << 3 << CardReturnCode::OK << CardReturnCode::OK << false << std::optional(FailureCode::Reason::Establish_Pace_Channel_Unknown_Password_Id); } @@ -204,8 +206,10 @@ class test_StateEstablishPaceChannel QFETCH(bool, canAllowed); QFETCH(std::optional, failureCode); - QSignalSpy spyPaceChannelEstablished(mState.data(), &StateEstablishPaceChannel::firePaceChannelEstablished); - QSignalSpy spyPaceChannelInoperative(mState.data(), &StateEstablishPaceChannel::firePaceChannelInoperative); + QSignalSpy spyWrongPin(mState.data(), &StateEstablishPaceChannel::fireWrongPassword); + QSignalSpy spyThirdPinAttemptFailed(mState.data(), &StateEstablishPaceChannel::fireThirdPinAttemptFailed); + QSignalSpy spyPaceCanEstablished(mState.data(), &StateEstablishPaceChannel::firePaceCanEstablished); + QSignalSpy spyPacePukEstablished(mState.data(), &StateEstablishPaceChannel::firePacePukEstablished); QSignalSpy spyAbort(mState.data(), &StateEstablishPaceChannel::fireAbort); QSignalSpy spyContinue(mState.data(), &StateEstablishPaceChannel::fireContinue); @@ -214,7 +218,7 @@ class test_StateEstablishPaceChannel const QSharedPointer command(new MockEstablishPaceChannelCommand(worker, PacePasswordId::PACE_PIN)); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cInfo(CardType::NONE, QSharedPointer(), retryCounter, false, false); + const CardInfo cInfo(CardType::NONE, FileRef(), QSharedPointer(), retryCounter, false, false); ReaderInfo rInfo; rInfo.setCardInfo(cInfo); Q_EMIT worker->fireReaderInfoChanged(rInfo); @@ -235,7 +239,7 @@ class test_StateEstablishPaceChannel mState->onEstablishConnectionDone(command); QCOMPARE(mAuthContext->getLastPaceResult(), result); QCOMPARE(mAuthContext->getExpectedRetryCounter(), 3); - QCOMPARE(spyPaceChannelEstablished.count(), 1); + QCOMPARE(spyContinue.count(), 1); return; } @@ -244,32 +248,30 @@ class test_StateEstablishPaceChannel if (!canAllowed) { mState->onEstablishConnectionDone(command); - QCOMPARE(spyContinue.count(), 1); + QCOMPARE(mAuthContext->getLastPaceResult(), result); + QCOMPARE(spyPaceCanEstablished.count(), 1); return; } mState->onEstablishConnectionDone(command); QCOMPARE(mAuthContext->getLastPaceResult(), result); - QCOMPARE(spyPaceChannelEstablished.count(), 1); + QCOMPARE(spyContinue.count(), 1); return; } if (code == CardReturnCode::OK && password == PacePasswordId::PACE_PUK) { - QTest::ignoreMessage(QtDebugMsg, "PACE_PUK succeeded. Resetting PACE passwords and setting expected retry counter to: -1"); + QTest::ignoreMessage(QtDebugMsg, "PACE_PUK succeeded"); mState->onEstablishConnectionDone(command); QCOMPARE(mAuthContext->getLastPaceResult(), result); QCOMPARE(mAuthContext->getExpectedRetryCounter(), -1); - QCOMPARE(spyPaceChannelInoperative.count(), 1); + QCOMPARE(spyWrongPin.count(), 0); + QCOMPARE(spyThirdPinAttemptFailed.count(), 0); + QCOMPARE(spyPacePukEstablished.count(), 1); return; } mState->onEstablishConnectionDone(command); - if (code == CardReturnCode::PUK_INOPERATIVE) - { - QCOMPARE(mAuthContext->getStatus().getStatusCode(), GlobalStatus::Code::Card_Puk_Blocked); - } - if (code == CardReturnCode::CANCELLATION_BY_USER) { QCOMPARE(mAuthContext->getStatus().getStatusCode(), GlobalStatus::Code::Card_Cancellation_By_User); @@ -277,13 +279,13 @@ class test_StateEstablishPaceChannel QCOMPARE(mAuthContext->getLastPaceResult(), result); if (password == PacePasswordId::PACE_PUK - || mAuthContext->getLastPaceResult() == CardReturnCode::INVALID_PIN - || mAuthContext->getLastPaceResult() == CardReturnCode::INVALID_PIN_2 - || mAuthContext->getLastPaceResult() == CardReturnCode::INVALID_PIN_3) + || result == CardReturnCode::INVALID_PIN + || result == CardReturnCode::INVALID_PIN_2 + || result == CardReturnCode::INVALID_PIN_3) { QCOMPARE(spyAbort.count(), 0); - QCOMPARE(spyPaceChannelInoperative.count(), 1); - + QCOMPARE(spyWrongPin.count(), result != CardReturnCode::INVALID_PIN_3 ? 1 : 0); + QCOMPARE(spyThirdPinAttemptFailed.count(), result == CardReturnCode::INVALID_PIN_3 ? 1 : 0); } else { diff --git a/test/qt/workflows/states/test_StateExtractCvcsFromEac1InputType.cpp b/test/qt/workflows/states/test_StateExtractCvcsFromEac1InputType.cpp index 5680d6c22..941507003 100644 --- a/test/qt/workflows/states/test_StateExtractCvcsFromEac1InputType.cpp +++ b/test/qt/workflows/states/test_StateExtractCvcsFromEac1InputType.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,12 +10,14 @@ #include "states/StateBuilder.h" +#include "CertificateHelper.h" #include "TestAuthContext.h" #include "TestFileHelper.h" #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -24,7 +26,7 @@ class test_StateExtractCvcsFromEac1InputType { Q_OBJECT - QVector> mTerminalCvcs, mDvCvcs, mLinkCvcs, mCvcas; + QList> mTerminalCvcs, mDvCvcs, mLinkCvcs, mCvcas; QScopedPointer mState; QSharedPointer mAuthContext; @@ -34,19 +36,19 @@ class test_StateExtractCvcsFromEac1InputType private Q_SLOTS: void initTestCase() { - mTerminalCvcs << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DE0000024001HW.hex")); - mTerminalCvcs << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMOPAA00079.hex")); - mDvCvcs << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00039.hex")); - mDvCvcs << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDTR101415.hex")); - mLinkCvcs << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00102_DECVCAeID00103.hex")); - mCvcas << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex")); - mCvcas << CVCertificate::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00102.hex")); + mTerminalCvcs << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DE0000024001HW.hex"_L1)); + mTerminalCvcs << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvat-DEDEMOPAA00079.hex"_L1)); + mDvCvcs << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDPST00039.hex"_L1)); + mDvCvcs << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvdv-DEDVeIDDTR101415.hex"_L1)); + mLinkCvcs << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00102_DECVCAeID00103.hex"_L1)); + mCvcas << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00103.hex"_L1)); + mCvcas << CertificateHelper::fromHex(TestFileHelper::readFile(":/card/cvca-DECVCAeID00102.hex"_L1)); } void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_3.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1_3.xml"_L1)); mState.reset(StateBuilder::createState(mAuthContext)); diff --git a/test/qt/workflows/states/test_StateGenericProviderCommunication.cpp b/test/qt/workflows/states/test_StateGenericProviderCommunication.cpp index f75e9618d..548e9a0a5 100644 --- a/test/qt/workflows/states/test_StateGenericProviderCommunication.cpp +++ b/test/qt/workflows/states/test_StateGenericProviderCommunication.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateGetSelfAuthenticationData.h" @@ -8,19 +8,19 @@ #include "MockNetworkManager.h" +#include #include -#include #include Q_DECLARE_LOGGING_CATEGORY(network) - +using namespace Qt::Literals::StringLiterals; using namespace governikus; using Pair = QPair; -Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(QList) class StateGenericProviderCommunicationImpl @@ -111,7 +111,7 @@ class test_StateGenericProviderCommunication QTest::ignoreMessage(QtDebugMsg, "Operation aborted"); mState->onSslHandshakeDone(); - QTest::ignoreMessage(QtInfoMsg, QRegularExpression("^Used session cipher")); + QTest::ignoreMessage(QtInfoMsg, QRegularExpression("^Used session cipher"_L1)); mState->mReply->setSslConfiguration(QSslConfiguration()); mState->onSslHandshakeDone(); } @@ -138,40 +138,40 @@ class test_StateGenericProviderCommunication void logging_data() { - QTest::addColumn>("attributes"); + QTest::addColumn>("attributes"); QTest::addColumn("enabled"); - QTest::newRow("no attr") << QVector() << true; + QTest::newRow("no attr") << QList() << true; - QTest::newRow("single attr lower-case single") << QVector({ + QTest::newRow("single attr lower-case single") << QList({ {QByteArray("pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("single attr upper-case single") << QVector({ + QTest::newRow("single attr upper-case single") << QList({ {QByteArray("Pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("single attr lower-case multi") << QVector({ + QTest::newRow("single attr lower-case multi") << QList({ {QByteArray("pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("single attr upper-case multi") << QVector({ + QTest::newRow("single attr upper-case multi") << QList({ {QByteArray("Pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("single attr other") << QVector({ + QTest::newRow("single attr other") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")} }) << true; - QTest::newRow("multi attr lower-case single") << QVector({ + QTest::newRow("multi attr lower-case single") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("multi attr upper-case single") << QVector({ + QTest::newRow("multi attr upper-case single") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("Pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("multi attr lower-case multi") << QVector({ + QTest::newRow("multi attr lower-case multi") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("multi attr upper-case multi") << QVector({ + QTest::newRow("multi attr upper-case multi") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("Pragma"), QByteArray("no-log no-cache")} }) << false; @@ -180,7 +180,7 @@ class test_StateGenericProviderCommunication void logging() { - QFETCH(QVector, attributes); + QFETCH(QList, attributes); QFETCH(bool, enabled); MockNetworkReply* reply = new MockNetworkReply(QByteArrayLiteral("TEST")); @@ -190,14 +190,14 @@ class test_StateGenericProviderCommunication } mNetworkManager->setNextReply(reply); - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Status Code: 200 \"OK\"")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Status Code: 200 \"OK\""_L1)); if (enabled) { - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Received raw data:\n TEST")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Received raw data:\n TEST"_L1)); } else { - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("no-log was requested, skip logging of raw data")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("no-log was requested, skip logging of raw data"_L1)); } QSignalSpy spyMock(mNetworkManager.data(), &MockNetworkManager::fireReply); @@ -231,7 +231,7 @@ class test_StateGenericProviderCommunication QFETCH(GlobalStatus::Code, globalStatusCode); QFETCH(FailureCode::Reason, failureCodeReason); - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); mState->mReply.reset(reply, &QObject::deleteLater); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, httpStatus); reply->setError(networkError, QString()); @@ -249,9 +249,9 @@ class test_StateGenericProviderCommunication QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus().getStatusCode(), globalStatusCode); const FailureCode::FailureInfoMap infoMap { - {FailureCode::Info::State_Name, "StateGenericProviderCommunicationImpl"}, + {FailureCode::Info::State_Name, "StateGenericProviderCommunicationImpl"_L1}, {FailureCode::Info::Http_Status_Code, QString::number(httpStatus)}, - {FailureCode::Info::Network_Error, "Unknown error"} + {FailureCode::Info::Network_Error, "Unknown error"_L1} }; const FailureCode failureCode(failureCodeReason, infoMap); QCOMPARE(mState->getContext()->getFailureCode(), failureCode); diff --git a/test/qt/workflows/states/test_StateGenericSendReceive.cpp b/test/qt/workflows/states/test_StateGenericSendReceive.cpp index 0cc30342b..7a8137f9c 100644 --- a/test/qt/workflows/states/test_StateGenericSendReceive.cpp +++ b/test/qt/workflows/states/test_StateGenericSendReceive.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "Env.h" @@ -8,17 +8,17 @@ #include "MockNetworkManager.h" #include "TestAuthContext.h" -#include "TestFileHelper.h" +#include #include -#include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QSharedPointer) using Pair = QPair; -Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(QList) class test_StateGenericSendReceive : public QObject @@ -36,9 +36,21 @@ class test_StateGenericSendReceive private Q_SLOTS: void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); - - QSharedPointer tcToken(new TcToken(TestFileHelper::readFile(":/tctoken/ok.xml"))); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); + + const QByteArray tokenData("" + "" + " https://eid-server.example.de/entrypoint" + " 1A2BB129" + " https://service.example.de/loggedin?7eb39f62" + " https://service.example.de/ComError?7eb39f62" + " urn:liberty:paos:2006-08 " + " urn:ietf:rfc:4279 " + " " + " 4BC1A0B5 " + " " + ""); + QSharedPointer tcToken(new TcToken(tokenData)); mAuthContext->setTcToken(tcToken); mNetworkManager.reset(new MockNetworkManager()); Env::set(NetworkManager::staticMetaObject, mNetworkManager.data()); @@ -60,8 +72,8 @@ class test_StateGenericSendReceive QTest::addColumn("personalization"); QTest::addColumn("url"); - QTest::newRow("authentication") << false << QUrl("https://eid-server.example.de/entrypoint"); - QTest::newRow("personalization") << true << QUrl("https://eid-server.example.de/personalization"); + QTest::newRow("authentication") << false << QUrl("https://eid-server.example.de/entrypoint"_L1); + QTest::newRow("personalization") << true << QUrl("https://eid-server.example.de/personalization"_L1); } @@ -72,7 +84,7 @@ class test_StateGenericSendReceive const_cast(mState->mPersonalization) = personalization; - mNetworkManager->setFilename(":/paos/DIDList.xml"); + mNetworkManager->setFilename(":/paos/DIDList.xml"_L1); QSharedPointer initializeFrameworkResponse(new InitializeFrameworkResponse()); mAuthContext->setInitializeFrameworkResponse(initializeFrameworkResponse); @@ -196,7 +208,7 @@ class test_StateGenericSendReceive void connectionError() { MockNetworkReply* reply = new MockNetworkReply(); - reply->setError(QNetworkReply::ConnectionRefusedError, "forced connection refused"); + reply->setError(QNetworkReply::ConnectionRefusedError, "forced connection refused"_L1); mNetworkManager->setNextReply(reply); QSharedPointer initializeFrameworkResponse(new InitializeFrameworkResponse()); mAuthContext->setInitializeFrameworkResponse(initializeFrameworkResponse); @@ -215,7 +227,7 @@ class test_StateGenericSendReceive void sendInitializeFrameworkResponse_receiveDIDAuthenticateEAC1() { - mNetworkManager->setFilename(":/paos/DIDAuthenticateEAC1.xml"); + mNetworkManager->setFilename(":/paos/DIDAuthenticateEAC1.xml"_L1); QSharedPointer initializeFrameworkResponse(new InitializeFrameworkResponse()); mAuthContext->setInitializeFrameworkResponse(initializeFrameworkResponse); @@ -232,7 +244,7 @@ class test_StateGenericSendReceive void sendInitializeFrameworkResponse_unexpected() { - mNetworkManager->setFilename(":/paos/Transmit.xml"); + mNetworkManager->setFilename(":/paos/Transmit.xml"_L1); QSharedPointer initializeFrameworkResponse(new InitializeFrameworkResponse()); mAuthContext->setInitializeFrameworkResponse(initializeFrameworkResponse); @@ -250,7 +262,7 @@ class test_StateGenericSendReceive void mappingToTrustedChannelError() { - const QVector states = QVector() + const QList states = QList() << GlobalStatus::Code::Workflow_TrustedChannel_Establishment_Error << GlobalStatus::Code::Workflow_TrustedChannel_Server_Error << GlobalStatus::Code::Workflow_TrustedChannel_Hash_Not_In_Description @@ -272,40 +284,40 @@ class test_StateGenericSendReceive void logging_data() { - QTest::addColumn>("attributes"); + QTest::addColumn>("attributes"); QTest::addColumn("enabled"); - QTest::newRow("no attr") << QVector() << true; + QTest::newRow("no attr") << QList() << true; - QTest::newRow("single attr lower-case single") << QVector({ + QTest::newRow("single attr lower-case single") << QList({ {QByteArray("pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("single attr upper-case single") << QVector({ + QTest::newRow("single attr upper-case single") << QList({ {QByteArray("Pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("single attr lower-case multi") << QVector({ + QTest::newRow("single attr lower-case multi") << QList({ {QByteArray("pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("single attr upper-case multi") << QVector({ + QTest::newRow("single attr upper-case multi") << QList({ {QByteArray("Pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("single attr other") << QVector({ + QTest::newRow("single attr other") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")} }) << true; - QTest::newRow("multi attr lower-case single") << QVector({ + QTest::newRow("multi attr lower-case single") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("multi attr upper-case single") << QVector({ + QTest::newRow("multi attr upper-case single") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("Pragma"), QByteArray("no-log")} }) << false; - QTest::newRow("multi attr lower-case multi") << QVector({ + QTest::newRow("multi attr lower-case multi") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("pragma"), QByteArray("no-log no-cache")} }) << false; - QTest::newRow("multi attr upper-case multi") << QVector({ + QTest::newRow("multi attr upper-case multi") << QList({ {QByteArray("Connection"), QByteArray("keep-alive")}, {QByteArray("Pragma"), QByteArray("no-log no-cache")} }) << false; @@ -314,7 +326,7 @@ class test_StateGenericSendReceive void logging() { - QFETCH(QVector, attributes); + QFETCH(QList, attributes); QFETCH(bool, enabled); MockNetworkReply* reply = new MockNetworkReply(QByteArrayLiteral("TEST")); diff --git a/test/qt/workflows/states/test_StateGetSelfAuthenticationData.cpp b/test/qt/workflows/states/test_StateGetSelfAuthenticationData.cpp index d58a1cc25..955f6b1b1 100644 --- a/test/qt/workflows/states/test_StateGetSelfAuthenticationData.cpp +++ b/test/qt/workflows/states/test_StateGetSelfAuthenticationData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateGetSelfAuthenticationData.h" @@ -15,6 +15,7 @@ Q_DECLARE_LOGGING_CATEGORY(network) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -56,7 +57,7 @@ class test_StateGetSelfAuthenticationData void test_OnNetworkReplyValidData() { - const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationData.json"); + const auto& data = TestFileHelper::readFile(":/self/SelfAuthenticationData.json"_L1); mState->mReply.reset(new MockNetworkReply(data), &QObject::deleteLater); QSignalSpy spyContinue(mState.data(), &StateGetSelfAuthenticationData::fireContinue); @@ -88,7 +89,7 @@ class test_StateGetSelfAuthenticationData QFETCH(GlobalStatus::Code, globalStatusCode); QFETCH(FailureCode::Reason, failureCodeReason); - auto reply = new MockNetworkReply(); + auto* reply = new MockNetworkReply(); mState->mReply.reset(reply, &QObject::deleteLater); reply->setAttribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute, httpStatus); reply->setError(networkError, QString()); @@ -100,9 +101,9 @@ class test_StateGetSelfAuthenticationData QCOMPARE(spyAbort.count(), 1); QCOMPARE(mState->getContext()->getStatus().getStatusCode(), globalStatusCode); const FailureCode::FailureInfoMap infoMap { - {FailureCode::Info::State_Name, "StateGetSelfAuthenticationData"}, + {FailureCode::Info::State_Name, "StateGetSelfAuthenticationData"_L1}, {FailureCode::Info::Http_Status_Code, QString::number(httpStatus)}, - {FailureCode::Info::Network_Error, "Unknown error"} + {FailureCode::Info::Network_Error, "Unknown error"_L1} }; const FailureCode failureCode(failureCodeReason, infoMap); QCOMPARE(mState->getContext()->getFailureCode(), failureCode); diff --git a/test/qt/workflows/states/test_StateGetTcToken.cpp b/test/qt/workflows/states/test_StateGetTcToken.cpp index 7bd1100d7..e13b7d966 100644 --- a/test/qt/workflows/states/test_StateGetTcToken.cpp +++ b/test/qt/workflows/states/test_StateGetTcToken.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -15,7 +15,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -35,8 +35,8 @@ class test_StateGetTcToken { const QSharedPointer context(new AuthContext()); StateGetTcToken state(context); - const QUrl validUrl(QString("https://a.not.existing.valid.test.url.com")); - const QUrl invalidUrl(QString("test")); + const QUrl validUrl("https://a.not.existing.valid.test.url.com"_L1); + const QUrl invalidUrl("test"_L1); QSignalSpy spyAbort(&state, &StateGetTcToken::fireAbort); context->setTcTokenUrl(validUrl); @@ -61,10 +61,10 @@ class test_StateGetTcToken const QUrl emptyUrl; QVERIFY(!state.isValidRedirectUrl(emptyUrl)); - const QUrl invalidUrl(QString("test")); + const QUrl invalidUrl("test"_L1); QVERIFY(!state.isValidRedirectUrl(invalidUrl)); - const QUrl validUrl(QString("https://a.not.existing.valid.test.url.com")); + const QUrl validUrl("https://a.not.existing.valid.test.url.com"_L1); QVERIFY(state.isValidRedirectUrl(validUrl)); } @@ -75,7 +75,7 @@ class test_StateGetTcToken StateGetTcToken state(context); QSignalSpy spyAbort(&state, &StateGetTcToken::fireAbort); - const QUrl url(QString("https://a.not.existing.valid.test.url.com")); + const QUrl url("https://a.not.existing.valid.test.url.com"_L1); state.sendRequest(url); QCOMPARE(state.mConnections.size(), 3); diff --git a/test/qt/workflows/states/test_StateInitializeFramework.cpp b/test/qt/workflows/states/test_StateInitializeFramework.cpp index fbf121d00..a5e131715 100644 --- a/test/qt/workflows/states/test_StateInitializeFramework.cpp +++ b/test/qt/workflows/states/test_StateInitializeFramework.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "TestFileHelper.h" @@ -11,6 +11,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -30,7 +31,7 @@ class test_StateInitializeFramework void initTestCase() { mAuthContext.reset(new AuthContext()); - auto fileContent = TestFileHelper::readFile(":/paos/InitializeFramework.xml"); + auto fileContent = TestFileHelper::readFile(":/paos/InitializeFramework.xml"_L1); mAuthContext->setInitializeFramework(QSharedPointer(new InitializeFramework(fileContent))); mState.reset(StateBuilder::createState(mAuthContext)); diff --git a/test/qt/workflows/states/test_StateMaintainCardConnection.cpp b/test/qt/workflows/states/test_StateMaintainCardConnection.cpp index 37e6aad04..3e436c19e 100644 --- a/test/qt/workflows/states/test_StateMaintainCardConnection.cpp +++ b/test/qt/workflows/states/test_StateMaintainCardConnection.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateMaintainCardConnection.h" @@ -9,6 +9,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StateMaintainCardConnection @@ -37,17 +38,6 @@ class test_StateMaintainCardConnection } - void test_Run_Error() - { - QSignalSpy spy(mState.data(), &StateMaintainCardConnection::firePropagateAbort); - - mContext->setStatus(GlobalStatus::Code::Unknown_Error); - mContext->setFailureCode(FailureCode::Reason::User_Cancelled); - mState->run(); - QCOMPARE(spy.count(), 1); - } - - void test_Run_ResultUnrecoverable_data() { QTest::addColumn("code"); @@ -97,13 +87,8 @@ class test_StateMaintainCardConnection QSignalSpy spyNoCardConnection(mState.data(), &StateMaintainCardConnection::fireNoCardConnection); QSignalSpy spyUpdateRetryCounter(mState.data(), &StateMaintainCardConnection::fireForceUpdateRetryCounter); - const QString password("111111"); - mContext->setPin(password); - mContext->setCan(password); - mContext->setPuk(password); mContext->setLastPaceResult(code); - QTest::ignoreMessage(QtDebugMsg, "Resetting all PACE passwords."); QTest::ignoreMessage(QtDebugMsg, "No card connection available."); mState->run(); QCOMPARE(spyNoCardConnection.count(), 1); @@ -113,14 +98,9 @@ class test_StateMaintainCardConnection const QSharedPointer connection(new CardConnection(worker)); mContext->setCardConnection(connection); - QTest::ignoreMessage(QtDebugMsg, "Resetting all PACE passwords."); QTest::ignoreMessage(QtDebugMsg, "Trigger retry counter update."); mState->run(); QCOMPARE(spyUpdateRetryCounter.count(), 1); - - QCOMPARE(mContext->getPin(), QString()); - QCOMPARE(mContext->getCan(), QString()); - QCOMPARE(mContext->getPuk(), QString()); } @@ -130,7 +110,7 @@ class test_StateMaintainCardConnection QTest::addColumn("doReset"); QTest::newRow("card_not_found") << CardReturnCode::CARD_NOT_FOUND << true; - QTest::newRow("retry_allowed") << CardReturnCode::RETRY_ALLOWED << true; + QTest::newRow("retry_allowed") << CardReturnCode::RESPONSE_EMPTY << true; QTest::newRow("undefined") << CardReturnCode::UNDEFINED << false; QTest::newRow("unknown") << CardReturnCode::UNKNOWN << false; @@ -158,7 +138,7 @@ class test_StateMaintainCardConnection } else { - QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Last PACE result: .*")); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Last PACE result: .*"_L1)); QTest::ignoreMessage(QtDebugMsg, "Last PACE result is unrecoverable. Aborting."); } mState->run(); @@ -197,7 +177,7 @@ class test_StateMaintainCardConnection QTest::ignoreMessage(QtDebugMsg, "PIN unblocked! Triggering retry counter update."); mState->run(); QCOMPARE(spyUpdateRetryCounter.count(), 1); - QCOMPARE(mContext->getLastPaceResult(), CardReturnCode::OK); + QCOMPARE(mContext->getLastPaceResult(), CardReturnCode::OK_PUK); } diff --git a/test/qt/workflows/states/test_StatePreVerification.cpp b/test/qt/workflows/states/test_StatePreVerification.cpp index fdf1053aa..f883f188c 100644 --- a/test/qt/workflows/states/test_StatePreVerification.cpp +++ b/test/qt/workflows/states/test_StatePreVerification.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -18,7 +18,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -42,7 +42,7 @@ class test_StatePreVerification void init() { AbstractSettings::mTestDir.clear(); - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mAuthContext->initCvcChainBuilder(); @@ -109,7 +109,7 @@ class test_StatePreVerification void testCvcaNotTrusted() { - const_cast>*>(&mState->mTrustedCvcas)->clear(); + const_cast>*>(&mState->mTrustedCvcas)->clear(); QSignalSpy spy(mState.data(), &StatePreVerification::fireAbort); mAuthContext->setStateApproved(); @@ -161,9 +161,9 @@ class test_StatePreVerification void testSaveLinkCertificates() { - const auto& remove = [](QVector>& pVector, const QSharedPointer& pCert) + const auto& remove = [](QList>& pVector, const QSharedPointer& pCert) { - QMutableVectorIterator> iter(pVector); + QMutableListIterator> iter(pVector); while (iter.hasNext()) { iter.next(); @@ -181,10 +181,10 @@ class test_StatePreVerification settings.removeLinkCertificate(cvc); } - const int expectedCvcaSize = 17; + const int expectedCvcaSize = 19; QCOMPARE(mState->mTrustedCvcas.size(), expectedCvcaSize); const_cast(&mState->mValidationDateTime)->setDate(QDate(2020, 05, 25)); - auto& trustedCvcas = const_cast>&>(mState->mTrustedCvcas); + auto& trustedCvcas = const_cast>&>(mState->mTrustedCvcas); remove(trustedCvcas, mAuthContext->getDidAuthenticateEac1()->getCvCertificates().at(3)); remove(trustedCvcas, mAuthContext->getDidAuthenticateEac1()->getCvCertificates().at(2)); diff --git a/test/qt/workflows/states/test_StatePreparePace.cpp b/test/qt/workflows/states/test_StatePreparePace.cpp index 87ed27ae5..e42decd6c 100644 --- a/test/qt/workflows/states/test_StatePreparePace.cpp +++ b/test/qt/workflows/states/test_StatePreparePace.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,7 +16,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StatePreparePace @@ -79,8 +79,8 @@ class test_StatePreparePace const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::SMART_EID, QSharedPointer(), 0); - const ReaderInfo readerInfo(QString(), ReaderManagerPlugInType::REMOTE_IFD, cardInfo); + const CardInfo cardInfo(CardType::SMART_EID, FileRef(), QSharedPointer(), 0); + const ReaderInfo readerInfo(QString(), ReaderManagerPluginType::REMOTE_IFD, cardInfo); mContext->setCardConnection(connection); Q_EMIT worker->fireReaderInfoChanged(readerInfo); QSignalSpy spyAbort(mState.data(), &StatePreparePace::fireAbort); @@ -94,9 +94,9 @@ class test_StatePreparePace void test_Run_RetryCounter0_data() { - QTest::addColumn("type"); + QTest::addColumn("type"); - const auto& readerTypes = Enum::getList(); + const auto& readerTypes = Enum::getList(); for (const auto& type : readerTypes) { QTest::newRow(getEnumName(type).data()) << type; @@ -106,17 +106,17 @@ class test_StatePreparePace void test_Run_RetryCounter0() { - QFETCH(ReaderManagerPlugInType, type); + QFETCH(ReaderManagerPluginType, type); const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 0); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 0); const ReaderInfo readerInfo(QString(), type, cardInfo); mContext->setCardConnection(connection); Q_EMIT worker->fireReaderInfoChanged(readerInfo); QSignalSpy spyEnterPacePassword(mState.data(), &StatePreparePace::fireEnterPacePassword); - QSignalSpy spyEstablishPaceChannel(mState.data(), &StatePreparePace::fireEstablishPaceChannel); + QSignalSpy spyContinue(mState.data(), &StatePreparePace::fireContinue); QTest::ignoreMessage(QtDebugMsg, "PUK required"); mContext->setStateApproved(); @@ -125,10 +125,10 @@ class test_StatePreparePace mContext->setStateApproved(false); - const QString puk("0987654321"); + const QString puk("0987654321"_L1); mContext->setPuk(puk); mContext->setStateApproved(); - QTRY_COMPARE(spyEstablishPaceChannel.count(), 1); // clazy:exclude=qstring-allocations + QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations } @@ -137,10 +137,10 @@ class test_StatePreparePace const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 1); - const ReaderInfo readerInfo(QString(), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 1); + const ReaderInfo readerInfo(QString(), ReaderManagerPluginType::UNKNOWN, cardInfo); QSignalSpy spyEnterPacePassword(mState.data(), &StatePreparePace::fireEnterPacePassword); - QSignalSpy spyEstablishPaceChannel(mState.data(), &StatePreparePace::fireEstablishPaceChannel); + QSignalSpy spyContinue(mState.data(), &StatePreparePace::fireContinue); mContext->setCardConnection(connection); Q_EMIT worker->fireReaderInfoChanged(readerInfo); @@ -151,12 +151,12 @@ class test_StatePreparePace mContext->setStateApproved(false); - const QString can("000000"); + const QString can("000000"_L1); mContext->setCan(can); QTest::ignoreMessage(QtDebugMsg, "CAN required"); QTest::ignoreMessage(QtDebugMsg, "PACE_CAN done: false"); mContext->setStateApproved(); - QTRY_COMPARE(spyEstablishPaceChannel.count(), 1); // clazy:exclude=qstring-allocations + QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations } @@ -165,27 +165,27 @@ class test_StatePreparePace const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&workerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3); - const ReaderInfo readerInfo(QString(), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3); + const ReaderInfo readerInfo(QString(), ReaderManagerPluginType::UNKNOWN, cardInfo); mContext->setCardConnection(connection); Q_EMIT worker->fireReaderInfoChanged(readerInfo); QSignalSpy spyEnterPacePassword(mState.data(), &StatePreparePace::fireEnterPacePassword); - QSignalSpy spyEstablishPaceChannel(mState.data(), &StatePreparePace::fireEstablishPaceChannel); + QSignalSpy spyContinue(mState.data(), &StatePreparePace::fireContinue); QTest::ignoreMessage(QtDebugMsg, "PIN allowed"); QTest::ignoreMessage(QtDebugMsg, "PACE_PIN done: false"); mContext->setStateApproved(); QTRY_COMPARE(spyEnterPacePassword.count(), 1); // clazy:exclude=qstring-allocations - QCOMPARE(spyEstablishPaceChannel.count(), 0); + QCOMPARE(spyContinue.count(), 0); QCOMPARE(mContext->getEstablishPaceChannelType(), PacePasswordId::PACE_PIN); mContext->setStateApproved(false); - const QString pin("000000"); + const QString pin("000000"_L1); mContext->setPin(pin); mContext->setStateApproved(); QCOMPARE(spyEnterPacePassword.count(), 1); - QTRY_COMPARE(spyEstablishPaceChannel.count(), 1); // clazy:exclude=qstring-allocations + QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations } diff --git a/test/qt/workflows/states/test_StateProcessCertificatesFromEac2.cpp b/test/qt/workflows/states/test_StateProcessCertificatesFromEac2.cpp index 593ceb78f..a388aaec5 100644 --- a/test/qt/workflows/states/test_StateProcessCertificatesFromEac2.cpp +++ b/test/qt/workflows/states/test_StateProcessCertificatesFromEac2.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -21,6 +21,7 @@ #include #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -43,8 +44,8 @@ class test_StateProcessCertificatesFromEac2 void init() { - mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); - QSharedPointer didAuthEac2(static_cast(DidAuthenticateEac2Parser().parse(TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml")))); + mAuthContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); + QSharedPointer didAuthEac2(static_cast(DidAuthenticateEac2Parser().parse(TestFileHelper::readFile(":/paos/DIDAuthenticateEAC2.xml"_L1)))); mAuthContext->setDidAuthenticateEac2(didAuthEac2); QByteArray hexBytes = QByteArray("00000000" diff --git a/test/qt/workflows/states/test_StateRedirectBrowser.cpp b/test/qt/workflows/states/test_StateRedirectBrowser.cpp index 1612608dd..74fd6330d 100644 --- a/test/qt/workflows/states/test_StateRedirectBrowser.cpp +++ b/test/qt/workflows/states/test_StateRedirectBrowser.cpp @@ -1,18 +1,20 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateRedirectBrowser.h" -#include "TestFileHelper.h" #include "states/StateBuilder.h" #include #include #include + +using namespace Qt::Literals::StringLiterals; using namespace governikus; + class test_StateRedirectBrowser : public QObject { @@ -27,6 +29,37 @@ class test_StateRedirectBrowser } private Q_SLOTS: + void majorMinor() + { + const QString URL_PREFIX("https://www.der-pott-kocht.net:8443/index.html"_L1); + const QUrl url(URL_PREFIX); + + // Ok + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Ok, ECardApiResult::Minor::null))).toString(), + URL_PREFIX + "?ResultMajor=ok"_L1); + + // General server error + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Unknown_Error, QString(), ECardApiResult::Origin::Server))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=serverError"_L1); + + // Minors defined in TR-03112-1 and TR-03124-1 2.5.4.2 + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Communication_Error))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=communicationError"_L1); + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::DP_Trusted_Channel_Establishment_Failed))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=trustedChannelEstablishmentFailed"_L1); + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::SAL_Cancellation_by_User))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=cancellationByUser"_L1); + + // No difference between client and server origin + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::SAL_Cancellation_by_User, QString(), ECardApiResult::Origin::Server))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=cancellationByUser"_L1); + + // General client error + QCOMPARE(StateRedirectBrowser::addMajorMinor(url, GlobalStatus(ECardApiResult(ECardApiResult::Major::Error, ECardApiResult::Minor::AL_Not_Initialized))).toString(), + URL_PREFIX + "?ResultMajor=error&ResultMinor=clientError"_L1); + } + + void noError() { auto state = getStateRedirectBrowser(); @@ -58,6 +91,66 @@ class test_StateRedirectBrowser } + void emptyRefreshUrlNoCommunicationErrorAddress() + { + auto state = getStateRedirectBrowser(); + QSignalSpy spyAbort(state.data(), &StateRedirectBrowser::fireAbort); + QSignalSpy spyContinue(state.data(), &StateRedirectBrowser::fireContinue); + + const auto& context = state->getContext(); + const QByteArray tokenData("" + "" + " https://eid-server.example.de/entrypoint" + " 1A2BB129" + " https://service.example.de/loggedin?7eb39f62" + " urn:liberty:paos:2006-08 " + " urn:ietf:rfc:4279 " + " " + " 4BC1A0B5 " + " " + ""); + context->setTcToken(QSharedPointer::create(tokenData)); + QTest::ignoreMessage(QtDebugMsg, "Refresh URL is not valid: QUrl(\"\")"); + QTest::ignoreMessage(QtDebugMsg, "CommunicationErrorAddress is not valid: QUrl(\"\")"); + + state->run(); + QCOMPARE(context->getRefreshUrl(), QString()); + QCOMPARE(spyAbort.count(), 0); + QCOMPARE(spyContinue.count(), 1); + } + + + void emptyRefreshUrl() + { + auto state = getStateRedirectBrowser(); + QSignalSpy spyAbort(state.data(), &StateRedirectBrowser::fireAbort); + QSignalSpy spyContinue(state.data(), &StateRedirectBrowser::fireContinue); + + const auto& context = state->getContext(); + const QByteArray tokenData("" + "" + " https://eid-server.example.de/entrypoint" + " 1A2BB129" + " https://service.example.de/loggedin?7eb39f62" + " https://flupp" + " urn:liberty:paos:2006-08 " + " urn:ietf:rfc:4279 " + " " + " 4BC1A0B5 " + " " + ""); + + context->setTcTokenNotFound(false); + context->setTcToken(QSharedPointer::create(tokenData)); + QTest::ignoreMessage(QtDebugMsg, "Refresh URL is not valid: QUrl(\"\")"); + + state->run(); + QCOMPARE(context->getRefreshUrl(), QStringLiteral("https://flupp?ResultMajor=error&ResultMinor=clientError")); + QCOMPARE(spyAbort.count(), 0); + QCOMPARE(spyContinue.count(), 1); + } + + }; QTEST_GUILESS_MAIN(test_StateRedirectBrowser) diff --git a/test/qt/workflows/states/test_StateResetRetryCounter.cpp b/test/qt/workflows/states/test_StateResetRetryCounter.cpp new file mode 100644 index 000000000..fd65f5af8 --- /dev/null +++ b/test/qt/workflows/states/test_StateResetRetryCounter.cpp @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "states/StateResetRetryCounter.h" + +#include "FailureCode.h" +#include "MockCardConnection.h" +#include "MockCardConnectionWorker.h" +#include "TestWorkflowContext.h" + +#include +#include +#include + +#include + +using namespace governikus; + + +class MockCardCommand + : public BaseCardCommand +{ + Q_OBJECT + + public: + explicit MockCardCommand(const QSharedPointer& pCardConnectionWorker) + : BaseCardCommand(pCardConnectionWorker) + { + } + + + void setMockReturnCode(CardReturnCode pReturnCode) + { + setReturnCode(pReturnCode); + } + + + void internalExecute() override + { + setReturnCode(getCardConnectionWorker()->updateRetryCounter()); + } + + +}; + +class test_StateResetRetryCounter + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void test_RunNoCardConnection() + { + const QSharedPointer context(new TestWorkflowContext()); + StateResetRetryCounter state(context); + + QSignalSpy spyContinue(&state, &StateResetRetryCounter::fireContinue); + QSignalSpy spyAbort(&state, &StateResetRetryCounter::fireAbort); + QSignalSpy spyNoCardConnection(&state, &StateResetRetryCounter::fireNoCardConnection); + + QTest::ignoreMessage(QtDebugMsg, "No card connection available."); + state.run(); + QCOMPARE(spyContinue.count(), 0); + QCOMPARE(spyAbort.count(), 0); + QCOMPARE(spyNoCardConnection.count(), 1); + QVERIFY(!context->getFailureCode().has_value()); + } + + + void test_ResetRetryCounterDone_data() + { + QTest::addColumn("returnCode"); + QTest::addColumn>("failureCode"); + + QTest::addRow("OK") << CardReturnCode::OK << std::optional(); + QTest::addRow("PUK inoperative") << CardReturnCode::PUK_INOPERATIVE << std::optional(FailureCode::Reason::Establish_Pace_Channel_Puk_Inoperative); + QTest::addRow("Error case") << CardReturnCode::INVALID_PUK << std::optional(); + } + + + void test_ResetRetryCounterDone() + { + QFETCH(CardReturnCode, returnCode); + QFETCH(std::optional, failureCode); + + const QSharedPointer context(new TestWorkflowContext()); + StateResetRetryCounter state(context); + const QSharedPointer worker(new MockCardConnectionWorker()); + const QSharedPointer command(new MockCardCommand(worker)); + QSignalSpy spyContinue(&state, &StateResetRetryCounter::fireContinue); + QSignalSpy spyAbort(&state, &StateResetRetryCounter::fireAbort); + QSignalSpy spyNoCardConnection(&state, &StateResetRetryCounter::fireNoCardConnection); + command->setMockReturnCode(returnCode); + context->setCardConnection(QSharedPointer::create()); + state.onResetRetryCounterDone(command); + if (returnCode == CardReturnCode::OK || returnCode == CardReturnCode::PUK_INOPERATIVE) + { + QCOMPARE(spyNoCardConnection.count(), 0); + QCOMPARE(spyContinue.count(), failureCode.has_value() ? 0 : 1); + QCOMPARE(spyAbort.count(), failureCode.has_value() ? 1 : 0); + } + else + { + QCOMPARE(spyNoCardConnection.count(), 1); + QCOMPARE(spyContinue.count(), 0); + QCOMPARE(spyAbort.count(), 0); + } + QCOMPARE(context->getFailureCode(), failureCode); + } + + +}; + +QTEST_GUILESS_MAIN(test_StateResetRetryCounter) +#include "test_StateResetRetryCounter.moc" diff --git a/test/qt/workflows/states/test_StateSelectReader.cpp b/test/qt/workflows/states/test_StateSelectReader.cpp index e6bb7c9ae..759f50efa 100644 --- a/test/qt/workflows/states/test_StateSelectReader.cpp +++ b/test/qt/workflows/states/test_StateSelectReader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -30,7 +30,7 @@ class test_StateSelectReader private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations @@ -60,9 +60,9 @@ class test_StateSelectReader void test_OnReaderInfoChangedNoSelectableReaders() { - mContext->setReaderPlugInTypes({ReaderManagerPlugInType::PCSC, ReaderManagerPlugInType::UNKNOWN, ReaderManagerPlugInType::REMOTE_IFD}); + mContext->setReaderPluginTypes({ReaderManagerPluginType::PCSC, ReaderManagerPluginType::UNKNOWN, ReaderManagerPluginType::REMOTE_IFD}); mContext->setStateApproved(); - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QTest::ignoreMessage(QtDebugMsg, "No selectable reader detected"); Q_EMIT readerManager->fireReaderAdded(ReaderInfo()); @@ -70,10 +70,10 @@ class test_StateSelectReader } - void test_fireReaderPlugInTypesChanged() + void test_fireReaderPluginTypesChanged() { QSignalSpy spyRetry(mState.data(), &StateSelectReader::fireRetry); - Q_EMIT mContext->fireReaderPlugInTypesChanged(); + Q_EMIT mContext->fireReaderPluginTypesChanged(); QCOMPARE(spyRetry.count(), 1); } diff --git a/test/qt/workflows/states/test_StateSendWhitelistSurvey.cpp b/test/qt/workflows/states/test_StateSendWhitelistSurvey.cpp index afbf14b26..721e30719 100644 --- a/test/qt/workflows/states/test_StateSendWhitelistSurvey.cpp +++ b/test/qt/workflows/states/test_StateSendWhitelistSurvey.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ #include "states/StateSendWhitelistSurvey.h" @@ -8,7 +8,7 @@ #include "HttpServer.h" #include "LogHandler.h" #include "SecureStorage.h" -#include "SurveyModel.h" +#include "Survey.h" #include "VolatileSettings.h" #include "states/StateBuilder.h" @@ -17,7 +17,7 @@ #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockSecureStorage @@ -46,7 +46,7 @@ class test_StateSendWhitelistSurvey private Q_SLOTS: void init() { - mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml")); + mContext.reset(new TestAuthContext(":/paos/DIDAuthenticateEAC1.xml"_L1)); mState.reset(StateBuilder::createState(mContext)); mState->onEntry(nullptr); } @@ -110,11 +110,11 @@ class test_StateSendWhitelistSurvey QTest::addColumn("spyCounter"); QTest::addColumn("url"); - QTest::newRow("successful") << quint16(25000) << 1 << QUrl("http://localhost:25000"); - QTest::newRow("invalidPort") << quint16(1515) << 0 << QUrl("http://localhost:25000"); - QTest::newRow("emptyPort") << quint16() << 0 << QUrl("http://localhost:25000"); - QTest::newRow("emptyPortinUrl") << quint16(1515) << 0 << QUrl("http://localhost"); - QTest::newRow("invalidHost") << quint16(25000) << 0 << QUrl("http://test:25000"); + QTest::newRow("successful") << quint16(25000) << 1 << QUrl("http://localhost:25000"_L1); + QTest::newRow("invalidPort") << quint16(1515) << 0 << QUrl("http://localhost:25000"_L1); + QTest::newRow("emptyPort") << quint16() << 0 << QUrl("http://localhost:25000"_L1); + QTest::newRow("emptyPortinUrl") << quint16(1515) << 0 << QUrl("http://localhost"_L1); + QTest::newRow("invalidHost") << quint16(25000) << 0 << QUrl("http://test:25000"_L1); } @@ -128,11 +128,11 @@ class test_StateSendWhitelistSurvey Env::getSingleton()->init(); Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(true); - const auto& surveyModel = Env::getSingleton(); - ReaderInfo readerInfo("reader", ReaderManagerPlugInType::NFC, CardInfo(CardType::EID_CARD)); + const auto& survey = Env::getSingleton(); + ReaderInfo readerInfo("reader"_L1, ReaderManagerPluginType::NFC, CardInfo(CardType::EID_CARD)); readerInfo.setMaxApduLength(0); - surveyModel->setReaderInfo(readerInfo); - surveyModel->setAuthWasSuccessful(true); + survey->setReaderInfo(readerInfo); + survey->setAuthWasSuccessful(true); QSignalSpy spyContinue(mState.data(), &StateSendWhitelistSurvey::fireContinue); QSignalSpy logSpy(Env::getSingleton()->getEventHandler(), &LogEventHandler::fireLog); @@ -140,7 +140,7 @@ class test_StateSendWhitelistSurvey HttpServer server(port); QSignalSpy spy(&server, &HttpServer::fireNewHttpRequest); - const QString name("reader"); + const QString name("reader"_L1); mContext->setReaderName(name); MockSecureStorage storage(url); Env::set(SecureStorage::staticMetaObject, &storage); @@ -154,7 +154,7 @@ class test_StateSendWhitelistSurvey QString message; for (int i = 0; i < logSpy.size(); i++) { - if (logSpy.at(i).at(0).toString().contains("Sent survey to whitelist server:")) + if (logSpy.at(i).at(0).toString().contains("Sent survey to whitelist server:"_L1)) { surveySent = true; message = logSpy.at(i).at(0).toString(); @@ -163,31 +163,31 @@ class test_StateSendWhitelistSurvey } QVERIFY(surveySent); - QVERIFY(message.contains("AusweisAppVersionNumber")); - QVERIFY(message.contains("ModelName")); - QVERIFY(message.contains("ModelNumber")); - QVERIFY(message.contains("Rom")); - QVERIFY(message.contains("OsVersion")); - QVERIFY(message.contains("BuildNumber")); - QVERIFY(message.contains("KernelVersion")); - QVERIFY(message.contains("\"MaximumNfcPacketLength\": 0")); - QVERIFY(message.contains("Vendor")); - QVERIFY(message.contains("NfcTagType")); + QVERIFY(message.contains("AusweisAppVersionNumber"_L1)); + QVERIFY(message.contains("ModelName"_L1)); + QVERIFY(message.contains("ModelNumber"_L1)); + QVERIFY(message.contains("Rom"_L1)); + QVERIFY(message.contains("OsVersion"_L1)); + QVERIFY(message.contains("BuildNumber"_L1)); + QVERIFY(message.contains("KernelVersion"_L1)); + QVERIFY(message.contains("\"MaximumNfcPacketLength\": 0"_L1)); + QVERIFY(message.contains("Vendor"_L1)); + QVERIFY(message.contains("NfcTagType"_L1)); if (spyCounter != 0) { const QSharedPointer request = spy.at(0).at(0).value>(); - QCOMPARE(request->getUrl(), QUrl("/new")); + QCOMPARE(request->getUrl(), QUrl("/new"_L1)); QCOMPARE(request->getHeader(QByteArray("host")), QByteArray("localhost:25000")); QCOMPARE(request->getHeader(QByteArray("content-type")), QByteArray("application/json; charset=UTF-8")); QJsonDocument json = QJsonDocument::fromJson(request->getBody()); QJsonObject jsonObject = json.object(); - QVERIFY(jsonObject.contains("AusweisAppVersionNumber")); - QVERIFY(jsonObject.contains("ModelName")); - QVERIFY(jsonObject.contains("ModelNumber")); - QVERIFY(jsonObject.contains("Rom")); - QVERIFY(jsonObject.contains("Vendor")); - QVERIFY(jsonObject.contains("NfcTagType")); + QVERIFY(jsonObject.contains("AusweisAppVersionNumber"_L1)); + QVERIFY(jsonObject.contains("ModelName"_L1)); + QVERIFY(jsonObject.contains("ModelNumber"_L1)); + QVERIFY(jsonObject.contains("Rom"_L1)); + QVERIFY(jsonObject.contains("Vendor"_L1)); + QVERIFY(jsonObject.contains("NfcTagType"_L1)); } } diff --git a/test/qt/workflows/states/test_StateStartPaosResponse.cpp b/test/qt/workflows/states/test_StateStartPaosResponse.cpp index d53e8d05e..b223c0904 100644 --- a/test/qt/workflows/states/test_StateStartPaosResponse.cpp +++ b/test/qt/workflows/states/test_StateStartPaosResponse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include @@ -10,6 +10,7 @@ #include "states/StateBuilder.h" #include "states/StateStartPaosResponse.h" +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -59,7 +60,7 @@ class test_StateStartPaosResponse void takeResultFromStartPAOSResponse() { - QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse3.xml"))); + QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse3.xml"_L1))); mAuthContext->setStartPaosResponse(startPAOSResponse); mAuthContext->setStatus(CardReturnCodeUtil::toGlobalStatus(CardReturnCode::CANCELLATION_BY_USER)); @@ -81,7 +82,7 @@ class test_StateStartPaosResponse void emitErrorIfResultError() { - QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse3.xml"))); + QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse3.xml"_L1))); mAuthContext->setStartPaosResponse(startPAOSResponse); QSignalSpy spy(mState.data(), &StateStartPaosResponse::fireAbort); @@ -95,7 +96,7 @@ class test_StateStartPaosResponse void emitSuccessIfResultOk() { - QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse1.xml"))); + QSharedPointer startPAOSResponse(new StartPaosResponse(TestFileHelper::readFile(":/paos/StartPAOSResponse1.xml"_L1))); mAuthContext->setStartPaosResponse(startPAOSResponse); QSignalSpy spy(mState.data(), &StateStartPaosResponse::fireContinue); diff --git a/test/qt/workflows/states/test_StateTransmit.cpp b/test/qt/workflows/states/test_StateTransmit.cpp index 5c1295a70..79a213038 100644 --- a/test/qt/workflows/states/test_StateTransmit.cpp +++ b/test/qt/workflows/states/test_StateTransmit.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -13,7 +13,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class MockTransmitCommand @@ -22,7 +22,7 @@ class MockTransmitCommand Q_OBJECT public: - MockTransmitCommand(const QSharedPointer& pCardConnectionWorker, const QVector& info, const QString& slot) + MockTransmitCommand(const QSharedPointer& pCardConnectionWorker, const QList& info, const QString& slot) : TransmitCommand(pCardConnectionWorker, info, slot) { } @@ -63,7 +63,7 @@ class test_StateTransmit context->setCardConnection(connection); StateTransmit stateTransmit(context); - const QString slotHandle("slot"); + const QString slotHandle("slot"_L1); const InputAPDUInfo info; const QSharedPointer transmit(new Transmit()); transmit->setSlotHandle(slotHandle); @@ -92,7 +92,7 @@ class test_StateTransmit context->setTransmitResponse(response); StateTransmit stateTransmit(context); const QSharedPointer worker(new MockCardConnectionWorker()); - QVector vector(5); + QList vector(5); const InputAPDUInfo info(QByteArray("info")); vector.insert(0, info); const QSharedPointer command(new MockTransmitCommand(worker, vector, QString())); diff --git a/test/qt/workflows/states/test_StateUpdRetryCounter.cpp b/test/qt/workflows/states/test_StateUpdRetryCounter.cpp index a4ff192bf..29233b95e 100644 --- a/test/qt/workflows/states/test_StateUpdRetryCounter.cpp +++ b/test/qt/workflows/states/test_StateUpdRetryCounter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/workflows/states/test_StateVerifyRetryCounter.cpp b/test/qt/workflows/states/test_StateVerifyRetryCounter.cpp index 6e3b0b198..7fc3e5629 100644 --- a/test/qt/workflows/states/test_StateVerifyRetryCounter.cpp +++ b/test/qt/workflows/states/test_StateVerifyRetryCounter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -16,7 +16,7 @@ #include #include - +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_StateVerifyRetryCounter @@ -51,14 +51,15 @@ class test_StateVerifyRetryCounter const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 3); - const ReaderInfo readerInfo(QString(), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3); + const ReaderInfo readerInfo(QString(), ReaderManagerPluginType::UNKNOWN, cardInfo); Q_EMIT worker->fireReaderInfoChanged(readerInfo); mContext->setCardConnection(connection); mContext->setExpectedRetryCounter(3); QSignalSpy spyContinue(mState.data(), &StateVerifyRetryCounter::fireContinue); QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 3 / expected: 3"); + QTest::ignoreMessage(QtDebugMsg, "Initially remembering the selected reader including the card with retry counter 3"); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations } @@ -77,21 +78,22 @@ class test_StateVerifyRetryCounter void test_Run_NoReader() { - const QString password("000000"); + const QString password("000000"_L1); mContext->setPin(password); mContext->setCan(password); mContext->setPuk(password); const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 2); - const ReaderInfo readerInfo(QString("test reader"), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 2); + const ReaderInfo readerInfo("test reader"_L1, ReaderManagerPluginType::UNKNOWN, cardInfo); Q_EMIT worker->fireReaderInfoChanged(readerInfo); mContext->setCardConnection(connection); - mContext->setReaderName(QString("test reader")); + mContext->setReaderName("test reader"_L1); QSignalSpy spyContinue(mState.data(), &StateVerifyRetryCounter::fireContinue); QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 2 / expected: -1"); + QTest::ignoreMessage(QtDebugMsg, "Initially remembering the selected reader including the card with retry counter 2"); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations QCOMPARE(mContext->getPin(), password); @@ -102,30 +104,45 @@ class test_StateVerifyRetryCounter } - void test_Run_NotExpectedReader() + void test_Run_ExpectedReader() { - const QString password("000000"); - mContext->setPin(password); - mContext->setCan(password); - mContext->setPuk(password); const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 2); - const ReaderInfo readerInfo(QString("test reader"), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 3); + const ReaderInfo readerInfo("test reader"_L1, ReaderManagerPluginType::UNKNOWN, cardInfo); Q_EMIT worker->fireReaderInfoChanged(readerInfo); mContext->setCardConnection(connection); mContext->rememberReader(); - mContext->setReaderName(QString("other reader")); + mContext->setReaderName("test reader"_L1); QSignalSpy spyContinue(mState.data(), &StateVerifyRetryCounter::fireContinue); - QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 2 / expected: 2"); - QTest::ignoreMessage(QtDebugMsg, "The reader changed or the connected card has an unexpected retry counter. Clearing PACE passwords."); + QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 3 / expected: 3"); + QTest::ignoreMessage(QtDebugMsg, "Found expected reader and retry counter matches"); mContext->setStateApproved(); QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations - QCOMPARE(mContext->getPin(), QString()); - QCOMPARE(mContext->getCan(), QString()); - QCOMPARE(mContext->getPuk(), QString()); + QVERIFY(mContext->isExpectedReader()); + QCOMPARE(mContext->getExpectedRetryCounter(), 3); + } + + + void test_Run_NotExpectedReader() + { + const QSharedPointer worker(new MockCardConnectionWorker()); + worker->moveToThread(&mWorkerThread); + const QSharedPointer connection(new CardConnection(worker)); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 2); + const ReaderInfo readerInfo("test reader"_L1, ReaderManagerPluginType::UNKNOWN, cardInfo); + Q_EMIT worker->fireReaderInfoChanged(readerInfo); + mContext->setCardConnection(connection); + mContext->rememberReader(); + mContext->setReaderName("other reader"_L1); + QSignalSpy spyChanged(mState.data(), &StateVerifyRetryCounter::fireReaderOrCardChanged); + + QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 2 / expected: 2"); + QTest::ignoreMessage(QtDebugMsg, "The reader changed or the connected card has an unexpected retry counter. Remembering the new reader including the card with retry counter 2"); + mContext->setStateApproved(); + QTRY_COMPARE(spyChanged.count(), 1); // clazy:exclude=qstring-allocations QVERIFY(!mContext->isExpectedReader()); QCOMPARE(mContext->getExpectedRetryCounter(), 2); } @@ -133,29 +150,22 @@ class test_StateVerifyRetryCounter void test_Run_ActualNotEqualExpectedRetryCounter() { - const QString password("000000"); - mContext->setPin(password); - mContext->setCan(password); - mContext->setPuk(password); const QSharedPointer worker(new MockCardConnectionWorker()); worker->moveToThread(&mWorkerThread); const QSharedPointer connection(new CardConnection(worker)); - const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer(), 2); - const ReaderInfo readerInfo(QString("test reader"), ReaderManagerPlugInType::UNKNOWN, cardInfo); + const CardInfo cardInfo(CardType::EID_CARD, FileRef(), QSharedPointer(), 2); + const ReaderInfo readerInfo("test reader"_L1, ReaderManagerPluginType::UNKNOWN, cardInfo); Q_EMIT worker->fireReaderInfoChanged(readerInfo); mContext->setCardConnection(connection); mContext->rememberReader(); - mContext->setReaderName(QString("test reader")); + mContext->setReaderName("test reader"_L1); mContext->setExpectedRetryCounter(1); - QSignalSpy spyContinue(mState.data(), &StateVerifyRetryCounter::fireContinue); + QSignalSpy spyChanged(mState.data(), &StateVerifyRetryCounter::fireReaderOrCardChanged); QTest::ignoreMessage(QtDebugMsg, "Retry counter | actual: 2 / expected: 1"); - QTest::ignoreMessage(QtDebugMsg, "The reader changed or the connected card has an unexpected retry counter. Clearing PACE passwords."); + QTest::ignoreMessage(QtDebugMsg, "The reader changed or the connected card has an unexpected retry counter. Remembering the new reader including the card with retry counter 2"); mContext->setStateApproved(); - QTRY_COMPARE(spyContinue.count(), 1); // clazy:exclude=qstring-allocations - QCOMPARE(mContext->getPin(), QString()); - QCOMPARE(mContext->getCan(), QString()); - QCOMPARE(mContext->getPuk(), QString()); + QTRY_COMPARE(spyChanged.count(), 1); // clazy:exclude=qstring-allocations QVERIFY(mContext->isExpectedReader()); QCOMPARE(mContext->getExpectedRetryCounter(), 2); } diff --git a/test/qt/workflows/states/test_TermsOfUsage.cpp b/test/qt/workflows/states/test_TermsOfUsage.cpp index 0bba3d43e..cc324ee93 100644 --- a/test/qt/workflows/states/test_TermsOfUsage.cpp +++ b/test/qt/workflows/states/test_TermsOfUsage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! diff --git a/test/qt/workflows/test_AuthController.cpp b/test/qt/workflows/test_AuthController.cpp new file mode 100644 index 000000000..2190fb4f9 --- /dev/null +++ b/test/qt/workflows/test_AuthController.cpp @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2024 Governikus GmbH & Co. KG, Germany + */ + +#include "controller/AuthController.h" + +#include + + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + + +class test_AuthController + : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void createWorkflowRequest() + { + const QUrl url("https://www.test.de"_L1); + const QVariant data(42); + const AuthContext::BrowserHandler handler = [](const QSharedPointer&){ + return QStringLiteral("HelloWorld"); + }; + const auto& request = AuthController::createWorkflowRequest(url, data, handler); + + const auto& context = request->getContext().objectCast(); + QVERIFY(context); + QVERIFY(context->isActivateUi()); + QCOMPARE(context->getActivationUrl(), url); + QCOMPARE(context->getBrowserHandler()(context), QStringLiteral("HelloWorld")); + QCOMPARE(request->getData().value(), 42); + QCOMPARE(context->isSkipMobileRedirect(), false); + + context->setWorkflowFinished(true); + const auto handling = request->handleBusyWorkflow(request, QSharedPointer()); + QCOMPARE(handling, WorkflowControl::ENQUEUE); + QCOMPARE(context->isStateApproved(), true); + QVERIFY(context->isSkipMobileRedirect()); + } + + +}; + +QTEST_GUILESS_MAIN(test_AuthController) +#include "test_AuthController.moc" diff --git a/test/qt/workflows/test_CertificateChecker.cpp b/test/qt/workflows/test_CertificateChecker.cpp index bbfe0fba4..a563cde33 100644 --- a/test/qt/workflows/test_CertificateChecker.cpp +++ b/test/qt/workflows/test_CertificateChecker.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2015-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -14,6 +14,7 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; class test_CertificateChecker @@ -21,7 +22,7 @@ class test_CertificateChecker { Q_OBJECT - QVector certs; + QList certs; private Q_SLOTS: void initTestCase() @@ -37,7 +38,7 @@ class test_CertificateChecker const QSharedPointer context(new AuthContext()); QCOMPARE(context->getCertificateList().size(), 0); - QCOMPARE(CertificateChecker::checkAndSaveCertificate(certs.at(0), QUrl("dummy"), context), CertificateChecker::CertificateStatus::Good); + QCOMPARE(CertificateChecker::checkAndSaveCertificate(certs.at(0), QUrl("dummy"_L1), context), CertificateChecker::CertificateStatus::Good); QCOMPARE(context->getCertificateList().size(), 1); } diff --git a/test/qt/workflows/test_ChangePinController.cpp b/test/qt/workflows/test_ChangePinController.cpp index 8afe576f8..4ad70f712 100644 --- a/test/qt/workflows/test_ChangePinController.cpp +++ b/test/qt/workflows/test_ChangePinController.cpp @@ -1,25 +1,23 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany - */ - -/*! - * \brief Test for the Change PIN functionality. + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ #include "controller/ChangePinController.h" +#include "AppSettings.h" #include "ReaderManager.h" +#include "VolatileSettings.h" #include "context/ChangePinContext.h" -#include "states/AbstractState.h" #include "states/StateUpdateRetryCounter.h" #include #include -Q_IMPORT_PLUGIN(SimulatorReaderManagerPlugIn) +Q_IMPORT_PLUGIN(SimulatorReaderManagerPlugin) +using namespace Qt::Literals::StringLiterals; using namespace governikus; @@ -58,7 +56,10 @@ class test_ChangePinController private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + Env::getSingleton()->setUsedAsSDK(false); + Env::getSingleton()->getSimulatorSettings().setEnabled(true); + + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); connect(readerManager, &ReaderManager::fireReaderPropertiesUpdated, this, [] (const ReaderInfo& pInfo){ if (pInfo.isInsertable()) @@ -74,39 +75,70 @@ class test_ChangePinController void cleanupTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); readerManager->disconnect(this); readerManager->shutdown(); } - void init() + void testSuccess_data() + { + QTest::addColumn("basicReader"); + + QTest::newRow("basic reader") << true; + QTest::newRow("comfort reader") << false; + } + + + void testSuccess() { + QFETCH(bool, basicReader); + Env::getSingleton()->getSimulatorSettings().setBasicReader(basicReader); + mChangePinContext.reset(new ChangePinContext()); - mChangePinContext->setReaderPlugInTypes({ReaderManagerPlugInType::SIMULATOR}); + if (basicReader) + { + mChangePinContext->setPin("123456"_L1); + mChangePinContext->setNewPin("123456"_L1); + } + mChangePinContext->setReaderPluginTypes({ReaderManagerPluginType::SIMULATOR}); connect(mChangePinContext.data(), &WorkflowContext::fireStateChanged, this, &test_ChangePinController::onStateChanged); - mChangePinController.reset(new ChangePinController(mChangePinContext)); - mRetryCounterUpdated = false; - } + QSignalSpy controllerFinishedSpy(mChangePinController.data(), &ChangePinController::fireComplete); + mChangePinController->run(); + QVERIFY(controllerFinishedSpy.wait()); + QCOMPARE(mChangePinContext->getStatus().getStatusCode(), GlobalStatus::Code::No_Error); - void cleanup() - { mChangePinContext->disconnect(this); mChangePinController.reset(); mChangePinContext.reset(); } - void testSuccess() + void createWorkflowRequest_data() { - QSignalSpy controllerFinishedSpy(mChangePinController.data(), &ChangePinController::fireComplete); + QTest::addColumn("requestTransportPin"); + QTest::addColumn("activateUi"); - mChangePinController->run(); - QVERIFY(controllerFinishedSpy.wait()); - QCOMPARE(mChangePinContext->getStatus().getStatusCode(), GlobalStatus::Code::No_Error); + QTest::newRow("PIN 5") << true << false; + QTest::newRow("PIN 5 + ACTIVATE") << true << true; + QTest::newRow("PIN 6") << false << false; + QTest::newRow("PIN 6 + ACTIVATE") << false << true; + } + + + void createWorkflowRequest() + { + QFETCH(bool, requestTransportPin); + QFETCH(bool, activateUi); + + const auto& request = ChangePinController::createWorkflowRequest(requestTransportPin, activateUi); + + const auto& context = request->getContext(); + QCOMPARE(context->isRequestTransportPin(), requestTransportPin); + QCOMPARE(context->isActivateUi(), activateUi); } diff --git a/test/qt/workflows/test_Survey.cpp b/test/qt/workflows/test_Survey.cpp new file mode 100644 index 000000000..0bce246d1 --- /dev/null +++ b/test/qt/workflows/test_Survey.cpp @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2018-2024 Governikus GmbH & Co. KG, Germany + */ + +#include "Survey.h" + +#include "AppSettings.h" +#include "DeviceInfo.h" +#include "Env.h" +#include "MockNetworkManager.h" +#include "VolatileSettings.h" + +#include +#include + +using namespace Qt::Literals::StringLiterals; +using namespace governikus; + +Q_DECLARE_METATYPE(CardInfo::TagType) + +class test_Survey + : public QObject +{ + Q_OBJECT + + private: + QSharedPointer mNetworkManager; + + void setReaderInfo(Survey& pSurvey, ReaderManagerPluginType pReaderPluginType, CardInfo::TagType pNfcTagType, int pMaxApduLength, bool pHasEid = true) + { + CardInfo cardInfo(pHasEid ? CardType::EID_CARD : CardType::NONE); + cardInfo.setTagType(pNfcTagType); + ReaderInfo readerInfo("TestReader"_L1, pReaderPluginType, cardInfo); + readerInfo.setMaxApduLength(pMaxApduLength); + pSurvey.setReaderInfo(readerInfo); + } + + private Q_SLOTS: + void init() + { + mNetworkManager.reset(new MockNetworkManager()); + Env::set(NetworkManager::staticMetaObject, mNetworkManager.data()); + } + + + void cleanup() + { + AbstractSettings::getStore()->clear(); + } + + + void testTransmitSurvey() + { + Survey survey; + + survey.transmitSurvey(); + mNetworkManager->fireFinished(); + const QByteArray json = mNetworkManager->getLastData(); + auto result = QJsonDocument::fromJson(json); + + QVERIFY(result["Rom"_L1].isObject()); + auto rom = result["Rom"_L1].toObject(); + QVERIFY(rom["BuildNumber"_L1].isString()); + QCOMPARE(rom["BuildNumber"_L1].toString(), DeviceInfo::getOSBuildNumber()); + QVERIFY(rom["OsVersion"_L1].isString()); + QCOMPARE(rom["OsVersion"_L1].toString(), DeviceInfo::getOSVersion()); + QVERIFY(rom["KernelVersion"_L1].isString()); + QCOMPARE(rom["KernelVersion"_L1].toString(), DeviceInfo::getKernelVersion()); + QVERIFY(rom["MaximumNfcPacketLength"_L1].isDouble()); + QCOMPARE(rom["MaximumNfcPacketLength"_L1].toDouble(), 0); + + QVERIFY(result["Vendor"_L1].isString()); + QCOMPARE(result["Vendor"_L1].toString(), DeviceInfo::getVendor()); + QVERIFY(result["ModelNumber"_L1].isString()); + QCOMPARE(result["ModelNumber"_L1].toString(), DeviceInfo::getModelNumber()); + QVERIFY(result["ModelName"_L1].isString()); + QCOMPARE(result["ModelName"_L1].toString(), DeviceInfo::getModelName()); + QVERIFY(result["AusweisAppVersionNumber"_L1].isString()); + QCOMPARE(result["AusweisAppVersionNumber"_L1].toString(), QCoreApplication::applicationVersion()); + QVERIFY(result["NfcTagType"_L1].isString()); + QCOMPARE(result["NfcTagType"_L1].toString(), "U"_L1); + } + + + void testOnCardInserted_data() + { + QTest::addColumn("usedAsSdk"); + QTest::addColumn("hasEid"); + QTest::addColumn("readerPluginType"); + QTest::addColumn("nfcTagType"); + QTest::addColumn("maxNfcPacketLength"); + QTest::addColumn("authSuccessful"); + + QTest::addColumn("askForDeviceSurvey"); + QTest::addColumn("nfcTagTypeJson"); + QTest::addColumn("maxNfcPacketLengthJson"); + + QTest::addRow("Normal NFC_4A") << false << true << ReaderManagerPluginType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << true << "A" << 9999.; + QTest::addRow("Normal NFC_4B") << false << true << ReaderManagerPluginType::NFC << CardInfo::TagType::NFC_4B << 500 << true << true << "B" << 500.; + + QTest::addRow("Unknown NFC") << false << true << ReaderManagerPluginType::NFC << CardInfo::TagType::UNKNOWN << 125 << true << true << "U" << 125.; + QTest::addRow("SDK") << true << true << ReaderManagerPluginType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + QTest::addRow("No card") << false << false << ReaderManagerPluginType::NFC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + + QTest::addRow("PCSC") << false << true << ReaderManagerPluginType::PCSC << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + QTest::addRow("REMOTE IFD") << false << true << ReaderManagerPluginType::REMOTE_IFD << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + QTest::addRow("LOCAL IFD") << false << true << ReaderManagerPluginType::LOCAL_IFD << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + QTest::addRow("SMART") << false << true << ReaderManagerPluginType::SMART << CardInfo::TagType::NFC_4A << 9999 << true << false << "U" << 0.; + + QTest::addRow("Auth Error") << false << true << ReaderManagerPluginType::NFC << CardInfo::TagType::NFC_4A << 9999 << false << false << "A" << 9999.; + } + + + void testOnCardInserted() + { + QFETCH(bool, usedAsSdk); + QFETCH(bool, hasEid); + QFETCH(ReaderManagerPluginType, readerPluginType); + QFETCH(CardInfo::TagType, nfcTagType); + QFETCH(int, maxNfcPacketLength); + QFETCH(bool, authSuccessful); + + QFETCH(bool, askForDeviceSurvey); + QFETCH(QString, nfcTagTypeJson); + QFETCH(double, maxNfcPacketLengthJson); + + SDK_MODE(usedAsSdk); + + Survey survey; + + survey.transmitSurvey(); + mNetworkManager->fireFinished(); + QByteArray json = mNetworkManager->getLastData(); + auto result = QJsonDocument::fromJson(json); + auto rom = result["Rom"_L1].toObject(); + QCOMPARE(rom["MaximumNfcPacketLength"_L1].toDouble(), 0); + QCOMPARE(result["NfcTagType"_L1].toString(), "U"_L1); + QCOMPARE(survey.askForDeviceSurvey(), false); + + setReaderInfo(survey, readerPluginType, nfcTagType, maxNfcPacketLength, hasEid); + survey.setAuthWasSuccessful(authSuccessful); + + QCOMPARE(survey.askForDeviceSurvey(), askForDeviceSurvey); + + Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(true); + + QCOMPARE(survey.askForDeviceSurvey(), false); + + survey.transmitSurvey(); + mNetworkManager->fireFinished(); + json = mNetworkManager->getLastData(); + result = QJsonDocument::fromJson(json); + rom = result["Rom"_L1].toObject(); + QCOMPARE(survey.isDeviceSurveyPending(), askForDeviceSurvey); + QCOMPARE(rom["MaximumNfcPacketLength"_L1].toDouble(), maxNfcPacketLengthJson); + QCOMPARE(result["NfcTagType"_L1].toString(), nfcTagTypeJson); + } + + + void testResetNfc() + { + Env::getSingleton()->setUsedAsSDK(false); + + Survey survey; + + survey.setAuthWasSuccessful(true); + setReaderInfo(survey, ReaderManagerPluginType::NFC, CardInfo::TagType::NFC_4A, 9999); + + survey.resetNfcData(); + + survey.transmitSurvey(); + mNetworkManager->fireFinished(); + QByteArray json = mNetworkManager->getLastData(); + auto result = QJsonDocument::fromJson(json); + auto rom = result["Rom"_L1].toObject(); + QCOMPARE(survey.askForDeviceSurvey(), false); + QCOMPARE(rom["MaximumNfcPacketLength"_L1].toDouble(), 0); + QCOMPARE(result["NfcTagType"_L1].toString(), "U"_L1); + } + + + void test_DeclineDeviceSurvey() + { + Env::getSingleton()->setUsedAsSDK(false); + + Survey survey; + + setReaderInfo(survey, ReaderManagerPluginType::NFC, CardInfo::TagType::NFC_4A, 9999); + survey.setAuthWasSuccessful(true); + + QCOMPARE(survey.askForDeviceSurvey(), true); + + Env::getSingleton()->getGeneralSettings().setDeviceSurveyPending(false); + + QCOMPARE(survey.askForDeviceSurvey(), false); + QCOMPARE(survey.isDeviceSurveyPending(), false); + } + + +}; + +QTEST_GUILESS_MAIN(test_Survey) +#include "test_Survey.moc" diff --git a/test/qt/workflows/test_TcToken.cpp b/test/qt/workflows/test_TcToken.cpp index e704c2b4a..99986cb46 100644 --- a/test/qt/workflows/test_TcToken.cpp +++ b/test/qt/workflows/test_TcToken.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2014-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2014-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -10,9 +10,11 @@ #include +using namespace Qt::Literals::StringLiterals; using namespace governikus; Q_DECLARE_METATYPE(QtMsgType) +Q_DECLARE_LOGGING_CATEGORY(secure) class test_TcToken : public QObject @@ -20,34 +22,29 @@ class test_TcToken Q_OBJECT private: - QFile tokenXmlOk; - QFile tokenXmlBroken; - - void checkAndOpenFile(QFile& file) - { - QVERIFY(file.exists()); - QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); - } - - public: - test_TcToken() - : tokenXmlOk(":/tctoken/ok.xml") - , tokenXmlBroken(":/tctoken/broken.xml") - { - checkAndOpenFile(tokenXmlOk); - checkAndOpenFile(tokenXmlBroken); - } + const QByteArray mValidToken = QByteArray("" + "" + " https://eid-server.example.de/entrypoint" + " 1A2BB129" + " https://service.example.de/loggedin?7eb39f62" + " https://service.example.de/ComError?7eb39f62" + " urn:liberty:paos:2006-08 " + " urn:ietf:rfc:4279 " + " " + " 4BC1A0B5 " + " " + ""); private Q_SLOTS: void parsedValues() { - TcToken token(tokenXmlOk.readAll()); + TcToken token(mValidToken); QVERIFY(token.isValid()); - QCOMPARE(token.getBinding(), QString("urn:liberty:paos:2006-08")); + QCOMPARE(token.getBinding(), "urn:liberty:paos:2006-08"_L1); QCOMPARE(token.getSessionIdentifier(), QByteArray("1A2BB129")); - QCOMPARE(token.getServerAddress().toString(), QString("https://eid-server.example.de/entrypoint")); - QCOMPARE(token.getRefreshAddress().toString(), QString("https://service.example.de/loggedin?7eb39f62")); - QCOMPARE(token.getCommunicationErrorAddress().toString(), QString("https://service.example.de/ComError?7eb39f62")); + QCOMPARE(token.getServerAddress().toString(), "https://eid-server.example.de/entrypoint"_L1); + QCOMPARE(token.getRefreshAddress().toString(), "https://service.example.de/loggedin?7eb39f62"_L1); + QCOMPARE(token.getCommunicationErrorAddress().toString(), "https://service.example.de/ComError?7eb39f62"_L1); QCOMPARE(token.getPsk(), QByteArray("4BC1A0B5")); } @@ -199,7 +196,13 @@ class test_TcToken void tryToParseCrap() { - TcToken token(tokenXmlBroken.readAll()); + TcToken token(QByteArray("" + "" + " https://eid-server.example.de/entrypoint" + " 1meters>" + " 4BC1A0B5 " + " " + "")); QVERIFY(!token.isValid()); QVERIFY(token.getBinding().isNull()); QVERIFY(token.getSessionIdentifier().isNull()); @@ -210,10 +213,10 @@ class test_TcToken } - void tryToParseClosedFile() + void tryToParseEmptyData() { - tokenXmlOk.close(); - TcToken token(tokenXmlOk.readAll()); + const QByteArray data; + TcToken token(data); QVERIFY(!token.isValid()); } @@ -353,12 +356,12 @@ class test_TcToken << QtCriticalMsg << false; QTest::newRow("Binding is no valid anyUri: \"://://\"") - << QString("://://") << pathProtocol << psk << identifier + << u"://://"_s << pathProtocol << psk << identifier << serverAdress << errorAdress << refreshAdress << QtCriticalMsg << false; QTest::newRow("PathSecurity-Protocol is no valid URI: \"\"") - << binding << QString("") << psk << identifier + << binding << u""_s << psk << identifier << serverAdress << errorAdress << refreshAdress << QtCriticalMsg << true; @@ -379,12 +382,12 @@ class test_TcToken QTest::newRow("ServerAddress no valid anyUri: \"://://\"") << binding << pathProtocol << psk << identifier - << QString("://://") << errorAdress << refreshAdress + << u"://://"_s << errorAdress << refreshAdress << QtCriticalMsg << false; QTest::newRow("CommunicationErrorAddress no valid anyUri: \"://://\"") << binding << pathProtocol << psk << identifier - << serverAdress << QString("://://") << refreshAdress + << serverAdress << u"://://"_s << refreshAdress << QtCriticalMsg << false; QTest::newRow("RefreshAddress no valid anyUri: \"\"") @@ -394,7 +397,7 @@ class test_TcToken QTest::newRow("RefreshAddress no valid anyUri: \"://://\"") << binding << pathProtocol << psk << identifier - << serverAdress << errorAdress << QString("://://") + << serverAdress << errorAdress << u"://://"_s << QtCriticalMsg << false; } @@ -430,6 +433,21 @@ class test_TcToken } + void pskOutput() + { + QTest::ignoreMessage(QtDebugMsg, "\"PSK\" = \"(...)\""); + TcToken token(mValidToken); + QVERIFY(token.isValid()); + QCOMPARE(token.getPsk(), "4BC1A0B5"); + + QLoggingCategory::setFilterRules(QStringLiteral("secure.debug=true")); + QTest::ignoreMessage(QtDebugMsg, "\"PSK\" = \"4BC1A0B5\""); + TcToken token2(mValidToken); + QVERIFY(token2.isValid()); + QCOMPARE(token.getPsk(), "4BC1A0B5"); + } + + }; QTEST_GUILESS_MAIN(test_TcToken) diff --git a/test/qt/workflows/test_WorkflowRequest.cpp b/test/qt/workflows/test_WorkflowRequest.cpp index bc676e51b..e54b8fee7 100644 --- a/test/qt/workflows/test_WorkflowRequest.cpp +++ b/test/qt/workflows/test_WorkflowRequest.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2023 Governikus GmbH & Co. KG, Germany + * Copyright (c) 2021-2024 Governikus GmbH & Co. KG, Germany */ /*! @@ -26,7 +26,7 @@ class test_WorkflowRequest private Q_SLOTS: void initTestCase() { - const auto readerManager = Env::getSingleton(); + auto* readerManager = Env::getSingleton(); QSignalSpy spy(readerManager, &ReaderManager::fireInitialized); readerManager->init(); QTRY_COMPARE(spy.count(), 1); // clazy:exclude=qstring-allocations diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt new file mode 100644 index 000000000..08372db29 --- /dev/null +++ b/test/tools/CMakeLists.txt @@ -0,0 +1,40 @@ +find_program(JSONSCHEMA_BIN NAMES check-jsonschema jsonschema jsonschema-3 python-jsonschema python3-jsonschema py-jsonschema py3-jsonschema CMAKE_FIND_ROOT_PATH_BOTH) + +if(JSONSCHEMA_BIN) + set(JSON_FILES updatable-files/supported-providers.json updatable-files/supported-readers.json) + + foreach(jsonfile ${JSON_FILES}) + set(file ${RESOURCES_DIR}/${jsonfile}) + if(NOT EXISTS "${file}") + message(FATAL_ERROR "File does not exist: ${file}") + endif() + + get_filename_component(filename ${file} NAME) + set(schema ${CMAKE_CURRENT_SOURCE_DIR}/${filename}) + + if(JSONSCHEMA_BIN MATCHES "check-jsonschema") + add_test(NAME ${filename} COMMAND ${JSONSCHEMA_BIN} --schemafile ${schema} ${file}) + else() + add_test(NAME ${filename} COMMAND ${JSONSCHEMA_BIN} -i ${file} ${schema}) + endif() + set_tests_properties(${filename} PROPERTIES LABELS "json" TIMEOUT 30) + endforeach() +endif() + + +if(TARGET ${Qt}::Qml AND QT_VERSION VERSION_GREATER_EQUAL 6.5) + add_test(NAME qmldir + COMMAND ${CMAKE_COMMAND} -DCMD=CHECK_QMLDIR -P ${CMAKE_DIR}/cmd.cmake + WORKING_DIRECTORY $) + set_tests_properties(qmldir PROPERTIES LABELS "qml") + + add_test(NAME qmltypes + COMMAND ${CMAKE_COMMAND} -DCMD=CHECK_QMLTYPES -P ${CMAKE_DIR}/cmd.cmake + WORKING_DIRECTORY $) + set_tests_properties(qmltypes PROPERTIES LABELS "qml") + + add_test(NAME qmllint + COMMAND ${CMAKE_COMMAND} --build . --target all_qmllint + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties(qmllint PROPERTIES LABELS "qml") +endif() diff --git a/test/json/supported-providers.json b/test/tools/supported-providers.json similarity index 98% rename from test/json/supported-providers.json rename to test/tools/supported-providers.json index dc1604b65..138cf78c5 100644 --- a/test/json/supported-providers.json +++ b/test/tools/supported-providers.json @@ -96,7 +96,7 @@ }, "phone": { "type": "string", - "pattern": "^\\+49 [0-9 ]{6,}$" + "pattern": "^\\+49 ([\\d]{3}|[\\d ]{6,})$" }, "mobileDesign": { "type": "boolean" diff --git a/test/json/supported-readers.json b/test/tools/supported-readers.json similarity index 97% rename from test/json/supported-readers.json rename to test/tools/supported-readers.json index d4255a70a..b8777e2fd 100644 --- a/test/json/supported-readers.json +++ b/test/tools/supported-readers.json @@ -5,10 +5,6 @@ "win_versions": { "type": "string", "enum": [ - "6.1", - "6.2", - "6.3", - "10", "10.0.19999", "10.0.20000" ] @@ -16,13 +12,9 @@ "mac_versions": { "type": "string", "enum": [ - "10.12", - "10.13", - "10.14", - "10.15", - "11", "12", - "13" + "13", + "14" ] }, "operating_system_drivers": {