diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 136a6c6a..75b0ca62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,8 @@ name: Build -on: push +on: + push: + workflow_dispatch: jobs: build-windows-msi: @@ -15,6 +17,8 @@ jobs: cache: true - name: Checkout Repo uses: actions/checkout@v4 + with: + submodules: recursive - name: Download Tools run: python scripts\download.py - name: Download OpenSSL @@ -52,6 +56,8 @@ jobs: cache: true - name: Checkout Repo uses: actions/checkout@v4 + with: + submodules: recursive - name: Download Tools run: python scripts\download.py - name: Download OpenSSL @@ -76,8 +82,8 @@ jobs: prerelease: true tag: development token: ${{ secrets.GITHUB_TOKEN }} - build-linux-appimage: - name: Linux Build (AppImage) + build-linux: + name: Linux Build (AppImage and source archive) runs-on: ubuntu-20.04 steps: - name: Install Dependencies @@ -87,6 +93,12 @@ jobs: sudo apt-get install qt515base qt515imageformats qt515svg qt515tools libgl1-mesa-dev libsecret-1-dev adb zipalign - name: Checkout Repo uses: actions/checkout@v4 + with: + submodules: recursive + - name: Create Source Archives + run: | + scripts/git-archive-all.sh --format tar.gz apk-editor-studio_source_${{ env.VERSION }}.tar.gz + scripts/git-archive-all.sh --format zip apk-editor-studio_source_${{ env.VERSION }}.zip - name: Download Tools run: python3 scripts/download.py - name: Build AppImage Package @@ -98,7 +110,9 @@ jobs: - name: Upload Assets uses: ncipollo/release-action@v1 with: - artifacts: scripts/linux/packages/appimage/apk-editor-studio_linux_${{ env.VERSION }}.AppImage + artifacts: "scripts/linux/packages/appimage/apk-editor-studio_linux_${{ env.VERSION }}.AppImage,\ + apk-editor-studio_source_${{ env.VERSION }}.tar.gz,\ + apk-editor-studio_source_${{ env.VERSION }}.zip" artifactErrorsFailBuild: true allowUpdates: true omitName: true @@ -117,6 +131,8 @@ jobs: cache: true - name: Checkout Repo uses: actions/checkout@v4 + with: + submodules: recursive - name: Download Tools run: python3 scripts/download.py - name: Build APP/DMG Package diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..93946e71 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/QtKeychain"] + path = lib/QtKeychain + url = https://github.com/frankosterfeld/qtkeychain diff --git a/COMPILATION.md b/COMPILATION.md index 1bb1d3ed..dee0e779 100644 --- a/COMPILATION.md +++ b/COMPILATION.md @@ -19,6 +19,16 @@ During the run-time, APK Editor Studio uses these third-party tools which are no Running the `scripts/download.py` script will automatically download the needed tools. +## Clone and get submodules + +If initially cloning: + +- Run `git clone --recurse-submodules https://github.com/kefir500/apk-editor-studio` + +If in an existing repo: + +- Run `git submodule update --init --recursive` + ## Building - Run `cmake -B your/build/path -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="path/to/qt"` diff --git a/lib/QtKeychain b/lib/QtKeychain new file mode 160000 index 00000000..f6705f33 --- /dev/null +++ b/lib/QtKeychain @@ -0,0 +1 @@ +Subproject commit f6705f3320eccab324ddf6a00ec71b17d1d5fcfb diff --git a/lib/QtKeychain/.gitignore b/lib/QtKeychain/.gitignore deleted file mode 100644 index 8fcb5ea4..00000000 --- a/lib/QtKeychain/.gitignore +++ /dev/null @@ -1,50 +0,0 @@ -#CMake files -CMakeCache.txt -CMakeFiles -CMakeScripts -cmake_install.cmake - -#Keychain temporary files -Qt5KeychainBuildTreeSettings.cmake -Qt5KeychainConfig.cmake -Qt5KeychainConfigVersion.cmake -QtKeychainBuildTreeSettings.cmake -QtKeychainConfig.cmake -QtKeychainConfigVersion.cmake -kwallet_interface.cpp -kwallet_interface.h -kwallet_interface.moc -moc_keychain.* -moc_keychain_p.* -moc_gnomekeyring_p.* -qkeychain_export.h -qt_Qt5Keychain.pri - -#Qt files -*_parameters -*.qm - -#General build files -Debug -Release -Makefile - -#Linux build files -libqt5keychain.* -testclient - -#Windows build files -install_manifest.txt -*.manifest -*.lib -*.exe - -#Mac build files -qtkeychain.xcodeproj -qtkeychain.build - -#Temporary files -*.sw? -*~ - - diff --git a/lib/QtKeychain/CMakeLists.txt b/lib/QtKeychain/CMakeLists.txt deleted file mode 100644 index 31ad8d16..00000000 --- a/lib/QtKeychain/CMakeLists.txt +++ /dev/null @@ -1,302 +0,0 @@ -cmake_minimum_required(VERSION 3.3) - -set(QTKEYCHAIN_VERSION 0.12.90) -set(QTKEYCHAIN_SOVERSION 1) - -project(qtkeychain VERSION ${QTKEYCHAIN_VERSION} LANGUAGES CXX) - -# Enable C++11 -SET(CMAKE_CXX_STANDARD 11) - -include(FindPkgConfig) - -### - -set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules") -include(GNUInstallDirs) -include(GenerateExportHeader) -include(CMakePackageConfigHelpers) -include(ECMSetupVersion) -include(ECMGeneratePriFile) - -option(BUILD_WITH_QT6 "Build qtkeychain with Qt 6" OFF) -option(BUILD_TEST_APPLICATION "Build test application" OFF) -option(BUILD_TRANSLATIONS "Build translations" ON) -option(QTKEYCHAIN_STATIC "Build static library" OFF) - -if(CMAKE_SYSTEM_NAME STREQUAL Android) - set(ANDROID 1) -endif() - -if(CMAKE_SYSTEM_NAME STREQUAL Haiku) - set(HAIKU 1) -endif() - -if (WIN32) - option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) - - if (USE_CREDENTIAL_STORE) - add_definitions(-DUSE_CREDENTIAL_STORE=1) - endif() -endif() - -if( NOT BUILD_WITH_QT6 ) - find_package(Qt5 COMPONENTS Core REQUIRED) -endif() - -if (Qt5Core_FOUND AND NOT BUILD_WITH_QT6) - set(QTKEYCHAIN_VERSION_INFIX 5) - - if(ANDROID) - if(Qt5Core_VERSION VERSION_LESS 5.7) - find_package(Qt5 COMPONENTS Core REQUIRED Private) - include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS}) - endif() - - find_package(Qt5 COMPONENTS AndroidExtras REQUIRED) - include_directories(${Qt5AndroidExtras_INCLUDE_DIRS}) - set(QTANDROIDEXTRAS_LIBRARIES ${Qt5AndroidExtras_LIBRARIES}) - endif() - - if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) - find_package(Qt5 COMPONENTS DBus REQUIRED) - include_directories(${Qt5DBus_INCLUDE_DIRS}) - set(QTDBUS_LIBRARIES ${Qt5DBus_LIBRARIES}) - macro(qt_add_dbus_interface) - qt5_add_dbus_interface(${ARGN}) - endmacro() - endif() - - if(BUILD_TRANSLATIONS) - find_package(Qt5 COMPONENTS LinguistTools REQUIRED) - macro(qt_add_translation) - qt5_add_translation(${ARGN}) - endmacro(qt_add_translation) - macro(qt_create_translation) - qt5_create_translation(${ARGN}) - endmacro(qt_create_translation) - endif() - - macro(qt_wrap_cpp) - qt5_wrap_cpp(${ARGN}) - endmacro() - - set(QTCORE_LIBRARIES ${Qt5Core_LIBRARIES}) - include_directories(${Qt5Core_INCLUDE_DIRS}) -else() - find_package(Qt6 COMPONENTS Core REQUIRED) - set(QTKEYCHAIN_VERSION_INFIX 6) - - if(ANDROID) - find_package(Qt6 COMPONENTS AndroidExtras REQUIRED) - include_directories(${Qt6AndroidExtras_INCLUDE_DIRS}) - set(QTANDROIDEXTRAS_LIBRARIES ${Qt6AndroidExtras_LIBRARIES}) - endif() - - if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) - find_package(Qt6 COMPONENTS DBus REQUIRED) - include_directories(${Qt6DBus_INCLUDE_DIRS}) - set(QTDBUS_LIBRARIES ${Qt6DBus_LIBRARIES}) - macro(qt_add_dbus_interface) - qt6_add_dbus_interface(${ARGN}) - endmacro() - endif() - - if(BUILD_TRANSLATIONS) - find_package(Qt6 COMPONENTS LinguistTools REQUIRED) - macro(qt_add_translation) - qt6_add_translation(${ARGN}) - endmacro(qt_add_translation) - macro(qt_create_translation) - qt6_create_translation(${ARGN}) - endmacro(qt_create_translation) - endif() - - macro(qt_wrap_cpp) - qt6_wrap_cpp(${ARGN}) - endmacro() - - set(QTCORE_LIBRARIES ${Qt6Core_LIBRARIES}) -endif() - - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -list(APPEND qtkeychain_LIBRARIES ${QTCORE_LIBRARIES}) -set(qtkeychain_SOURCES - keychain.cpp - qkeychain_export.h - keychain.h -) - -if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - # CMake < 3.15 sneaks in /W# flags for us, so we need a replacement, - # or we'll get a warning (cf. CMP0092) - if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") - string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") - endif() -else() - # MSVC's STL / Qt headers are not MSVC -Wall clean, so don't enable it there - add_definitions( -Wall ) -endif() - -if(WIN32) - list(APPEND qtkeychain_SOURCES keychain_win.cpp) - if (NOT USE_CREDENTIAL_STORE) - list(APPEND qtkeychain_LIBRARIES crypt32) - list(APPEND qtkeychain_SOURCES plaintextstore.cpp) - endif() - #FIXME: mingw bug; otherwise getting undefined refs to RtlSecureZeroMemory there - if(MINGW) - add_definitions( -O2 ) - endif() -endif() - -if(APPLE) - list(APPEND qtkeychain_SOURCES keychain_apple.mm) - list(APPEND qtkeychain_LIBRARIES "-framework Foundation" "-framework Security") -endif() - -if(HAIKU) - list(APPEND qtkeychain_SOURCES keychain_haiku.cpp) - - find_library(BE_LIBRARY be REQUIRED) - list(APPEND qtkeychain_LIBRARIES ${BE_LIBRARY}) -endif() - -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) - option(LIBSECRET_SUPPORT "Build with libsecret support" ON) - - if(LIBSECRET_SUPPORT) - pkg_check_modules(LIBSECRET REQUIRED libsecret-1) - add_definitions(-DHAVE_LIBSECRET=1) - INCLUDE_DIRECTORIES(${LIBSECRET_INCLUDE_DIRS}) - LINK_DIRECTORIES(${LIBSECRET_LIBRARY_DIRS}) - list(APPEND qtkeychain_LIBRARIES_PRIVATE ${LIBSECRET_LIBRARIES}) - endif() - - add_definitions(-DKEYCHAIN_DBUS=1) - list(APPEND qtkeychain_SOURCES keychain_unix.cpp gnomekeyring.cpp libsecret.cpp plaintextstore.cpp) - qt_add_dbus_interface(qtkeychain_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface) - list(APPEND qtkeychain_LIBRARIES ${QTDBUS_LIBRARIES} ) -endif() - -if(ANDROID) - list(APPEND qtkeychain_SOURCES keychain_android.cpp androidkeystore.cpp plaintextstore.cpp) - list(APPEND qtkeychain_LIBRARIES_PRIVATE ${QTANDROIDEXTRAS_LIBRARIES} ) -endif() - -QT_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h gnomekeyring_p.h) - -set(qtkeychain_TR_FILES - translations/qtkeychain_de.ts - translations/qtkeychain_fr.ts - translations/qtkeychain_ro.ts - translations/qtkeychain_ru.ts - translations/qtkeychain_zh.ts -) - -set(QTKEYCHAIN_TARGET_NAME qt${QTKEYCHAIN_VERSION_INFIX}keychain) -if(NOT QTKEYCHAIN_STATIC) - add_library(${QTKEYCHAIN_TARGET_NAME} SHARED ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) -else() - add_library(${QTKEYCHAIN_TARGET_NAME} STATIC ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) -endif() -if(WIN32) - set_target_properties( ${QTKEYCHAIN_TARGET_NAME} PROPERTIES DEBUG_POSTFIX "d" ) -endif() - -file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui) -if ( BUILD_TRANSLATIONS ) - qt_create_translation(qtkeychain_MESSAGES ${qtkeychain_TR_SOURCES} ${qtkeychain_TR_FILES}) - qt_add_translation(qtkeychain_QM_FILES ${qtkeychain_TR_FILES}) - add_custom_target(messages DEPENDS ${qtkeychain_MESSAGES}) - add_custom_target(translations DEPENDS ${qtkeychain_QM_FILES} messages) - # https://github.com/frankosterfeld/qtkeychain/issues/185 - add_dependencies(${QTKEYCHAIN_TARGET_NAME} translations) - - if(QTKEYCHAIN_VERSION_INFIX EQUAL 5 AND QT_TRANSLATIONS_DIR AND NOT QTKEYCHAIN_TRANSLATIONS_DIR) - # Back compatibility with pre-0.11 versions - message (WARNING "QT_TRANSLATIONS_DIR is deprecated, use QTKEYCHAIN_TRANSLATIONS_DIR instead") - set(QTKEYCHAIN_TRANSLATIONS_DIR ${QT_TRANSLATIONS_DIR} - CACHE PATH "The location of the QtKeychain translations" FORCE) - else() - set(QTKEYCHAIN_TRANSLATIONS_DIR - ${CMAKE_INSTALL_DATADIR}/qt${QTKEYCHAIN_VERSION_INFIX}keychain/translations - CACHE PATH "The location of the QtKeychain translations" ) - endif() - - install(FILES ${qtkeychain_QM_FILES} DESTINATION ${QTKEYCHAIN_TRANSLATIONS_DIR}) -endif( BUILD_TRANSLATIONS ) - -target_link_libraries(${QTKEYCHAIN_TARGET_NAME} PUBLIC ${qtkeychain_LIBRARIES} PRIVATE ${qtkeychain_LIBRARIES_PRIVATE}) -if(NOT INTERFACE_INCLUDE_SUFFIX) - set(INTERFACE_INCLUDE_SUFFIX include) -endif() -target_include_directories(${QTKEYCHAIN_TARGET_NAME} PUBLIC $) - -generate_export_header(${QTKEYCHAIN_TARGET_NAME} - EXPORT_FILE_NAME qkeychain_export.h - EXPORT_MACRO_NAME QKEYCHAIN_EXPORT -) - -set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES - VERSION ${QTKEYCHAIN_VERSION} - SOVERSION ${QTKEYCHAIN_SOVERSION} - MACOSX_RPATH 1 - INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" - INSTALL_RPATH_USE_LINK_PATH TRUE -) - -install(FILES keychain.h ${CMAKE_CURRENT_BINARY_DIR}/qkeychain_export.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qt${QTKEYCHAIN_VERSION_INFIX}keychain/ -) - -install(TARGETS ${QTKEYCHAIN_TARGET_NAME} - EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) - -if(BUILD_TEST_APPLICATION) - add_executable( testclient testclient.cpp ) - target_link_libraries( testclient ${QTKEYCHAIN_TARGET_NAME}) -endif() - - -### -### CMake config file -### - -configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/QtKeychainConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake" - INSTALL_DESTINATION Qt${QTKEYCHAIN_VERSION_INFIX}Keychain) - -ecm_setup_version("${QTKEYCHAIN_VERSION}" VARIABLE_PREFIX SNORE - PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" - SOVERSION ${QTKEYCHAIN_VERSION}) - -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) - set(PRI_EXTRA_DEPS "dbus") -endif() -ecm_generate_pri_file(BASE_NAME Qt${QTKEYCHAIN_VERSION_INFIX}Keychain - LIB_NAME ${QTKEYCHAIN_TARGET_NAME} - DEPS "core ${PRI_EXTRA_DEPS}" - INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} - FILENAME_VAR pri_filename) - -install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) - - -install(EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain" -) - -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain -) - diff --git a/lib/QtKeychain/COPYING b/lib/QtKeychain/COPYING deleted file mode 100644 index 69f70fff..00000000 --- a/lib/QtKeychain/COPYING +++ /dev/null @@ -1,23 +0,0 @@ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/QtKeychain/QtKeychainConfig.cmake.in b/lib/QtKeychain/QtKeychainConfig.cmake.in deleted file mode 100644 index d849dedd..00000000 --- a/lib/QtKeychain/QtKeychainConfig.cmake.in +++ /dev/null @@ -1,24 +0,0 @@ -# - Config file for the QtKeychain package -# It defines the following variables -# QTKEYCHAIN_INCLUDE_DIRS - include directories for QtKeychain -# QTKEYCHAIN_LIBRARIES - libraries to link against -# as well as the following imported targets -# qt5keychain / qt6keychain -# Qt5Keychain::Qt5Keychain / Qt6Keychain::Qt6Keychain - -@PACKAGE_INIT@ - -include("${CMAKE_CURRENT_LIST_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainLibraryDepends.cmake") - -include(CMakeFindDependencyMacro) - -find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@Core) - -if(UNIX AND NOT APPLE AND NOT ANDROID) - find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@DBus) -endif() - -set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@") -get_target_property(QTKEYCHAIN_INCLUDE_DIRS "@QTKEYCHAIN_TARGET_NAME@" INTERFACE_INCLUDE_DIRECTORIES) - -add_library(Qt@QTKEYCHAIN_VERSION_INFIX@Keychain::Qt@QTKEYCHAIN_VERSION_INFIX@Keychain ALIAS qt@QTKEYCHAIN_VERSION_INFIX@keychain) diff --git a/lib/QtKeychain/ReadMe.md b/lib/QtKeychain/ReadMe.md deleted file mode 100644 index cf0a2e13..00000000 --- a/lib/QtKeychain/ReadMe.md +++ /dev/null @@ -1,29 +0,0 @@ -QtKeychain -========== - -QtKeychain is a Qt API to store passwords and other secret data securely. How the data is stored depends on the platform: - - * **macOS:** Passwords are stored in the macOS Keychain. - - * **Linux/Unix:** If running, GNOME Keyring is used, otherwise QtKeychain tries to use KWallet (via D-Bus), if available. Libsecret (common API for desktop-specific solutions) - is also supported. - - * **Windows:** By default, the Windows Credential Store is used (requires Windows 7 or newer). -Pass `-DUSE_CREDENTIAL_STORE=OFF` to cmake to disable it. If disabled, QtKeychain uses the Windows API function -[CryptProtectData](http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261%28v=vs.85%29.aspx "CryptProtectData function") -to encrypt the password with the user's logon credentials. The encrypted data is then persisted via QSettings. - - * **Android and iOS:** Passwords are stored in the Android keystore system and iOS keychain, respectively. - -In unsupported environments QtKeychain will report an error. It will not store any data unencrypted unless explicitly requested (`setInsecureFallback( true )`). - - -Requirements ------------- - -QtKeychain 0.12 and newer supports Qt 5 and Qt 6 and requires a compiler with C++11 support. Older versions support Qt 4 and Qt 5. - -License -------- - -QtKeychain is available under the [Modified BSD License](http://www.gnu.org/licenses/license-list.html#ModifiedBSD). See the file COPYING for details. diff --git a/lib/QtKeychain/cmake/Modules/ECMGeneratePriFile.cmake b/lib/QtKeychain/cmake/Modules/ECMGeneratePriFile.cmake deleted file mode 100644 index f63a0ce2..00000000 --- a/lib/QtKeychain/cmake/Modules/ECMGeneratePriFile.cmake +++ /dev/null @@ -1,199 +0,0 @@ -#.rst: -# ECMGeneratePriFile -# ------------------ -# -# Generate a ``.pri`` file for the benefit of qmake-based projects. -# -# As well as the function below, this module creates the cache variable -# ``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``. -# This assumes Qt and the current project are both installed to the same -# non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will -# certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like -# ``share/qt5/mkspecs/modules``. -# -# The main thing is that this should be the ``modules`` subdirectory of either -# the default qmake ``mkspecs`` directory or of a directory that will be in the -# ``$QMAKEPATH`` environment variable when qmake is run. -# -# :: -# -# ecm_generate_pri_file(BASE_NAME -# LIB_NAME -# [DEPS " [ [...]]"] -# [FILENAME_VAR ] -# [INCLUDE_INSTALL_DIR ] -# [LIB_INSTALL_DIR ]) -# -# If your CMake project produces a Qt-based library, you may expect there to be -# applications that wish to use it that use a qmake-based build system, rather -# than a CMake-based one. Creating a ``.pri`` file will make use of your -# library convenient for them, in much the same way that CMake config files make -# things convenient for CMake-based applications. -# -# ecm_generate_pri_file() generates just such a file. It requires the -# ``PROJECT_VERSION_STRING`` variable to be set. This is typically set by -# :module:`ECMSetupVersion`, although the project() command in CMake 3.0.0 and -# later can also set this. -# -# BASE_NAME specifies the name qmake project (.pro) files should use to refer to -# the library (eg: KArchive). LIB_NAME is the name of the actual library to -# link to (ie: the first argument to add_library()). DEPS is a space-separated -# list of the base names of other libraries (for Qt libraries, use the same -# names you use with the ``QT`` variable in a qmake project file, such as "core" -# for QtCore). FILENAME_VAR specifies the name of a variable to store the path -# to the generated file in. -# -# INCLUDE_INSTALL_DIR is the path (relative to ``CMAKE_INSTALL_PREFIX``) that -# include files will be installed to. It defaults to -# ``${INCLUDE_INSTALL_DIR}/`` if the ``INCLUDE_INSTALL_DIR`` variable -# is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable -# is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR -# operates similarly for the installation location for libraries; it defaults to -# ``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order. -# -# Example usage: -# -# .. code-block:: cmake -# -# ecm_generate_pri_file( -# BASE_NAME KArchive -# LIB_NAME KF5KArchive -# DEPS "core" -# FILENAME_VAR pri_filename -# ) -# install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) -# -# A qmake-based project that wished to use this would then do:: -# -# QT += KArchive -# -# in their ``.pro`` file. -# -# Since pre-1.0.0. - -#============================================================================= -# SPDX-FileCopyrightText: 2014 David Faure -# -# SPDX-License-Identifier: BSD-3-Clause - -# Replicate the logic from KDEInstallDirs.cmake as we can't depend on it -# Ask qmake if we're using the same prefix as Qt -set(_askqmake OFF) -if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS) - include(ECMQueryQmake) - query_qmake(qt_install_prefix_dir QT_INSTALL_PREFIX TRY) - if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}") - set(_askqmake ON) - endif() -endif() - -if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake) - include(ECMQueryQmake) - query_qmake(qt_host_data_dir QT_HOST_DATA) - set(ECM_MKSPECS_INSTALL_DIR ${qt_host_data_dir}/mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") -else() - set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") -endif() - -function(ECM_GENERATE_PRI_FILE) - set(options ) - set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) - set(multiValueArgs ) - - cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if(EGPF_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"") - endif() - - if(NOT EGPF_BASE_NAME) - message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call") - endif() - if(NOT EGPF_LIB_NAME) - message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call") - endif() - if(NOT PROJECT_VERSION_STRING) - message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING not set before ECM_GENERATE_PRI_FILE() call. Did you call ecm_setup_version?") - endif() - if(NOT EGPF_INCLUDE_INSTALL_DIR) - if(INCLUDE_INSTALL_DIR) - set(EGPF_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/${EGPF_BASE_NAME}") - elseif(CMAKE_INSTALL_INCLUDEDIR) - set(EGPF_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${EGPF_BASE_NAME}") - else() - set(EGPF_INCLUDE_INSTALL_DIR "include/${EGPF_BASE_NAME}") - endif() - endif() - if(NOT EGPF_LIB_INSTALL_DIR) - if(LIB_INSTALL_DIR) - set(EGPF_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") - elseif(CMAKE_INSTALL_LIBDIR) - set(EGPF_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") - else() - set(EGPF_LIB_INSTALL_DIR "lib") - endif() - endif() - - string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_STRING}") - string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PROJECT_VERSION_MINOR "${PROJECT_VERSION_STRING}") - string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PROJECT_VERSION_PATCH "${PROJECT_VERSION_STRING}") - - # Prepare the right number of "../.." to go from ECM_MKSPECS_INSTALL_DIR to the install prefix - # This allows to make the generated pri files relocatable (no absolute paths) - if (IS_ABSOLUTE ${ECM_MKSPECS_INSTALL_DIR}) - set(BASEPATH ${CMAKE_INSTALL_PREFIX}) - else() - string(REGEX REPLACE "[^/]+" ".." PRI_ROOT_RELATIVE_TO_MKSPECS ${ECM_MKSPECS_INSTALL_DIR}) - set(BASEPATH "$$PWD/${PRI_ROOT_RELATIVE_TO_MKSPECS}") - endif() - - set(PRI_TARGET_BASENAME ${EGPF_BASE_NAME}) - set(PRI_TARGET_LIBNAME ${EGPF_LIB_NAME}) - set(PRI_TARGET_QTDEPS ${EGPF_DEPS}) - if(IS_ABSOLUTE "${EGPF_INCLUDE_INSTALL_DIR}") - set(PRI_TARGET_INCLUDES "${EGPF_INCLUDE_INSTALL_DIR}") - else() - set(PRI_TARGET_INCLUDES "${BASEPATH}/${EGPF_INCLUDE_INSTALL_DIR}") - endif() - if(IS_ABSOLUTE "${EGPF_LIB_INSTALL_DIR}") - set(PRI_TARGET_LIBS "${EGPF_LIB_INSTALL_DIR}") - else() - set(PRI_TARGET_LIBS "${BASEPATH}/${EGPF_LIB_INSTALL_DIR}") - endif() - set(PRI_TARGET_DEFINES "") - - set(PRI_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/qt_${PRI_TARGET_BASENAME}.pri) - if (EGPF_FILENAME_VAR) - set(${EGPF_FILENAME_VAR} ${PRI_FILENAME} PARENT_SCOPE) - endif() - - set(PRI_TARGET_MODULE_CONFIG "") - # backward compat: it was not obvious LIB_NAME needs to be a target name, - # and some projects where the target name was not the actual library output name - # passed the output name for LIB_NAME, so .name & .module prperties are correctly set. - # TODO: improve API dox, allow control over module name if target name != output name - if(TARGET ${EGPF_LIB_NAME}) - get_target_property(target_type ${EGPF_LIB_NAME} TYPE) - if (target_type STREQUAL "STATIC_LIBRARY") - set(PRI_TARGET_MODULE_CONFIG "staticlib") - endif() - endif() - - file(GENERATE - OUTPUT ${PRI_FILENAME} - CONTENT - "QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING} -QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR} -QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR} -QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH} -QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME} -QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME} -QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES} -QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES} -QT.${PRI_TARGET_BASENAME}.private_includes = -QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS} -QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS} -QT.${PRI_TARGET_BASENAME}.module_config = ${PRI_TARGET_MODULE_CONFIG} -" - ) -endfunction() diff --git a/lib/QtKeychain/cmake/Modules/ECMPackageConfigHelpers.cmake b/lib/QtKeychain/cmake/Modules/ECMPackageConfigHelpers.cmake deleted file mode 100644 index 8d48772b..00000000 --- a/lib/QtKeychain/cmake/Modules/ECMPackageConfigHelpers.cmake +++ /dev/null @@ -1,202 +0,0 @@ -#.rst: -# ECMPackageConfigHelpers -# ----------------------- -# -# Helper macros for generating CMake package config files. -# -# ``write_basic_package_version_file()`` is the same as the one provided by the -# `CMakePackageConfigHelpers -# `_ -# module in CMake; see that module's documentation for -# more information. -# -# :: -# -# ecm_configure_package_config_file( -# INSTALL_DESTINATION -# [PATH_VARS [ [...]] -# [NO_SET_AND_CHECK_MACRO] -# [NO_CHECK_REQUIRED_COMPONENTS_MACRO]) -# -# -# This behaves in the same way as configure_package_config_file() from CMake -# 2.8.12, except that it adds an extra helper macro: find_dependency(). It is -# highly recommended that you read the `documentation for -# CMakePackageConfigHelpers -# `_ -# for more information, particularly with regard to the PATH_VARS argument. -# -# Note that there is no argument that will disable the find_dependency() macro; -# if you do not require this macro, you should use -# ``configure_package_config_file`` from the CMakePackageConfigHelpers module. -# -# CMake 3.0 includes a CMakeFindDependencyMacro module that provides the -# find_dependency() macro (which you can ``include()`` in your package config -# file), so this file is only useful for projects wishing to provide config -# files that will work with CMake 2.8.12. -# -# Additional Config File Macros -# ============================= -# -# :: -# -# find_dependency( [ [EXACT]]) -# -# find_dependency() should be used instead of find_package() to find package -# dependencies. It forwards the correct parameters for EXACT, QUIET and -# REQUIRED which were passed to the original find_package() call. It also sets -# an informative diagnostic message if the dependency could not be found. -# -# Since pre-1.0.0. - -#============================================================================= -# SPDX-FileCopyrightText: 2014 Alex Merry -# SPDX-FileCopyrightText: 2013 Stephen Kelly -# -# SPDX-License-Identifier: BSD-3-Clause - -include(${CMAKE_ROOT}/Modules/CMakePackageConfigHelpers.cmake) - -set(_ecm_package_config_helpers_included TRUE) - -if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.13) - message(AUTHOR_WARNING "Your project already requires a version of CMake that includes the find_dependency macro via the CMakeFindDependencyMacro module. You should use CMakePackageConfigHelpers instead of ECMPackageConfigHelpers.") -endif() - -function(ECM_CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile) - set(options NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO) - set(oneValueArgs INSTALL_DESTINATION ) - set(multiValueArgs PATH_VARS ) - - cmake_parse_arguments(CCF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if(CCF_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to CONFIGURE_PACKAGE_CONFIG_FILE(): \"${CCF_UNPARSED_ARGUMENTS}\"") - endif() - - if(NOT CCF_INSTALL_DESTINATION) - message(FATAL_ERROR "No INSTALL_DESTINATION given to CONFIGURE_PACKAGE_CONFIG_FILE()") - endif() - - if(IS_ABSOLUTE "${CCF_INSTALL_DESTINATION}") - set(absInstallDir "${CCF_INSTALL_DESTINATION}") - else() - set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}") - endif() - - file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" ) - - foreach(var ${CCF_PATH_VARS}) - if(NOT DEFINED ${var}) - message(FATAL_ERROR "Variable ${var} does not exist") - else() - if(IS_ABSOLUTE "${${var}}") - string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}" - PACKAGE_${var} "${${var}}") - else() - set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}") - endif() - endif() - endforeach() - - get_filename_component(inputFileName "${_inputFile}" NAME) - - set(PACKAGE_INIT " -####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() (ECM variant) ####### -####### Any changes to this file will be overwritten by the next CMake run ####### -####### The input file was ${inputFileName} ####### - -get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE) -") - - if("${absInstallDir}" MATCHES "^(/usr)?/lib(64)?/.+") - # Handle "/usr move" symlinks created by some Linux distros. - set(PACKAGE_INIT "${PACKAGE_INIT} -# Use original install prefix when loaded through a \"/usr move\" -# cross-prefix symbolic link such as /lib -> /usr/lib. -get_filename_component(_realCurr \"\${CMAKE_CURRENT_LIST_DIR}\" REALPATH) -get_filename_component(_realOrig \"${absInstallDir}\" REALPATH) -if(_realCurr STREQUAL _realOrig) - set(PACKAGE_PREFIX_DIR \"${CMAKE_INSTALL_PREFIX}\") -endif() -unset(_realOrig) -unset(_realCurr) -") - endif() - - if(NOT CCF_NO_SET_AND_CHECK_MACRO) - set(PACKAGE_INIT "${PACKAGE_INIT} -macro(set_and_check _var _file) - set(\${_var} \"\${_file}\") - if(NOT EXISTS \"\${_file}\") - message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\") - endif() -endmacro() - -include(CMakeFindDependencyMacro OPTIONAL RESULT_VARIABLE _CMakeFindDependencyMacro_FOUND) - -if (NOT _CMakeFindDependencyMacro_FOUND) - macro(find_dependency dep) - if (NOT \${dep}_FOUND) - - set(ecm_fd_version) - if (\${ARGC} GREATER 1) - set(ecm_fd_version \${ARGV1}) - endif() - set(ecm_fd_exact_arg) - if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION_EXACT) - set(ecm_fd_exact_arg EXACT) - endif() - set(ecm_fd_quiet_arg) - if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) - set(ecm_fd_quiet_arg QUIET) - endif() - set(ecm_fd_required_arg) - if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) - set(ecm_fd_required_arg REQUIRED) - endif() - - find_package(\${dep} \${ecm_fd_version} - \${ecm_fd_exact_arg} - \${ecm_fd_quiet_arg} - \${ecm_fd_required_arg} - ) - - if (NOT \${dep}_FOUND) - set(\${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE \"\${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency \${dep} could not be found.\") - set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND False) - return() - endif() - - set(ecm_fd_version) - set(ecm_fd_required_arg) - set(ecm_fd_quiet_arg) - set(ecm_fd_exact_arg) - endif() - endmacro() -endif() - -") - endif() - - - if(NOT CCF_NO_CHECK_REQUIRED_COMPONENTS_MACRO) - set(PACKAGE_INIT "${PACKAGE_INIT} -macro(check_required_components _NAME) - foreach(comp \${\${_NAME}_FIND_COMPONENTS}) - if(NOT \${_NAME}_\${comp}_FOUND) - if(\${_NAME}_FIND_REQUIRED_\${comp}) - set(\${_NAME}_FOUND FALSE) - endif() - endif() - endforeach() -endmacro() -") - endif() - - set(PACKAGE_INIT "${PACKAGE_INIT} -####################################################################################") - - configure_file("${_inputFile}" "${_outputFile}" @ONLY) - -endfunction() diff --git a/lib/QtKeychain/cmake/Modules/ECMQueryQmake.cmake b/lib/QtKeychain/cmake/Modules/ECMQueryQmake.cmake deleted file mode 100644 index 74a6df87..00000000 --- a/lib/QtKeychain/cmake/Modules/ECMQueryQmake.cmake +++ /dev/null @@ -1,46 +0,0 @@ -find_package(Qt5Core QUIET) - -if (Qt5Core_FOUND) - set(_qmake_executable_default "qmake-qt5") -endif () -if (TARGET Qt5::qmake) - get_target_property(_qmake_executable_default Qt5::qmake LOCATION) -endif() -set(QMAKE_EXECUTABLE ${_qmake_executable_default} - CACHE FILEPATH "Location of the Qt5 qmake executable") - -# Helper method -# This is not public API (yet)! -# Usage: query_qmake( [TRY]) -# Passing TRY will result in the method not failing fatal if no qmake executable -# has been found, but instead simply returning an empty string -function(query_qmake result_variable qt_variable) - set(options TRY) - set(oneValueArgs ) - set(multiValueArgs ) - - cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if(NOT QMAKE_EXECUTABLE) - if(ARGS_TRY) - set(${result_variable} "" PARENT_SCOPE) - message(STATUS "No qmake Qt5 binary found. Can't check ${qt_variable}") - return() - else() - message(FATAL_ERROR "No qmake Qt5 binary found. Can't check ${qt_variable} as required") - endif() - endif() - execute_process( - COMMAND ${QMAKE_EXECUTABLE} -query "${qt_variable}" - RESULT_VARIABLE return_code - OUTPUT_VARIABLE output - ) - if(return_code EQUAL 0) - string(STRIP "${output}" output) - file(TO_CMAKE_PATH "${output}" output_path) - set(${result_variable} "${output_path}" PARENT_SCOPE) - else() - message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query \"${qt_variable}\"") - message(FATAL_ERROR "QMake call failed: ${return_code}") - endif() -endfunction() diff --git a/lib/QtKeychain/cmake/Modules/ECMSetupVersion.cmake b/lib/QtKeychain/cmake/Modules/ECMSetupVersion.cmake deleted file mode 100644 index 65c1688a..00000000 --- a/lib/QtKeychain/cmake/Modules/ECMSetupVersion.cmake +++ /dev/null @@ -1,202 +0,0 @@ -#.rst: -# ECMSetupVersion -# --------------- -# -# Handle library version information. -# -# :: -# -# ecm_setup_version( -# VARIABLE_PREFIX -# [SOVERSION ] -# [VERSION_HEADER ] -# [PACKAGE_VERSION_FILE [COMPATIBILITY ]] ) -# -# This parses a version string and sets up a standard set of version variables. -# It can optionally also create a C version header file and a CMake package -# version file to install along with the library. -# -# If the ```` argument is of the form ``..`` -# (or ``...``), The following CMake variables are -# set:: -# -# _VERSION_MAJOR - -# _VERSION_MINOR - -# _VERSION_PATCH - -# _VERSION - -# _VERSION_STRING - (for compatibility: use _VERSION instead) -# _SOVERSION - , or if SOVERSION was not given -# -# If CMake policy CMP0048 is not NEW, the following CMake variables will also -# be set:: -# -# PROJECT_VERSION_MAJOR - -# PROJECT_VERSION_MINOR - -# PROJECT_VERSION_PATCH - -# PROJECT_VERSION - -# PROJECT_VERSION_STRING - (for compatibility: use PROJECT_VERSION instead) -# -# If the VERSION_HEADER option is used, a simple C header is generated with the -# given filename. If filename is a relative path, it is interpreted as relative -# to CMAKE_CURRENT_BINARY_DIR. The generated header contains the following -# macros:: -# -# _VERSION_MAJOR - as an integer -# _VERSION_MINOR - as an integer -# _VERSION_PATCH - as an integer -# _VERSION_STRING - as a C string -# _VERSION - the version as an integer -# -# ``_VERSION`` has ```` in the bottom 8 bits, ```` in the -# next 8 bits and ```` in the remaining bits. Note that ```` and -# ```` must be less than 256. -# -# If the PACKAGE_VERSION_FILE option is used, a simple CMake package version -# file is created using the write_basic_package_version_file() macro provided by -# CMake. It should be installed in the same location as the Config.cmake file of -# the library so that it can be found by find_package(). If the filename is a -# relative path, it is interpreted as relative to CMAKE_CURRENT_BINARY_DIR. The -# optional COMPATIBILITY option is forwarded to -# write_basic_package_version_file(), and defaults to AnyNewerVersion. -# -# If CMake policy CMP0048 is NEW, an alternative form of the command is -# available:: -# -# ecm_setup_version(PROJECT -# [VARIABLE_PREFIX ] -# [SOVERSION ] -# [VERSION_HEADER ] -# [PACKAGE_VERSION_FILE ] ) -# -# This will use the version information set by the project() command. -# VARIABLE_PREFIX defaults to the project name. Note that PROJECT must be the -# first argument. In all other respects, it behaves like the other form of the -# command. -# -# Since pre-1.0.0. -# -# COMPATIBILITY option available since 1.6.0. - -#============================================================================= -# SPDX-FileCopyrightText: 2014 Alex Merry -# SPDX-FileCopyrightText: 2012 Alexander Neundorf -# -# SPDX-License-Identifier: BSD-3-Clause - -include(CMakePackageConfigHelpers) - -# save the location of the header template while CMAKE_CURRENT_LIST_DIR -# has the value we want -set(_ECM_SETUP_VERSION_HEADER_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/ECMVersionHeader.h.in") - -function(ecm_setup_version _version) - set(options ) - set(oneValueArgs VARIABLE_PREFIX SOVERSION VERSION_HEADER PACKAGE_VERSION_FILE COMPATIBILITY) - set(multiValueArgs ) - - cmake_parse_arguments(ESV "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - if(ESV_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to ECM_SETUP_VERSION(): \"${ESV_UNPARSED_ARGUMENTS}\"") - endif() - - set(project_manages_version FALSE) - set(use_project_version FALSE) - # CMP0048 only exists in CMake 3.0.0 and later - if(CMAKE_VERSION VERSION_LESS 3.0.0) - set(project_version_policy "OLD") - else() - cmake_policy(GET CMP0048 project_version_policy) - endif() - if(project_version_policy STREQUAL "NEW") - set(project_manages_version TRUE) - if(_version STREQUAL "PROJECT") - set(use_project_version TRUE) - endif() - elseif(_version STREQUAL "PROJECT") - message(FATAL_ERROR "ecm_setup_version given PROJECT argument, but CMP0048 is not NEW") - endif() - - set(should_set_prefixed_vars TRUE) - if(NOT ESV_VARIABLE_PREFIX) - if(use_project_version) - set(ESV_VARIABLE_PREFIX "${PROJECT_NAME}") - set(should_set_prefixed_vars FALSE) - else() - message(FATAL_ERROR "Required argument PREFIX missing in ECM_SETUP_VERSION() call") - endif() - endif() - - if(use_project_version) - set(_version "${PROJECT_VERSION}") - set(_major "${PROJECT_VERSION_MAJOR}") - set(_minor "${PROJECT_VERSION_MINOR}") - set(_patch "${PROJECT_VERSION_PATCH}") - else() - string(REGEX REPLACE "^0*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major "${_version}") - string(REGEX REPLACE "^[0-9]+\\.0*([0-9]+)\\.[0-9]+.*" "\\1" _minor "${_version}") - string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.0*([0-9]+).*" "\\1" _patch "${_version}") - endif() - - if(NOT ESV_SOVERSION) - set(ESV_SOVERSION ${_major}) - endif() - - if(should_set_prefixed_vars) - set(${ESV_VARIABLE_PREFIX}_VERSION "${_version}") - set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR ${_major}) - set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR ${_minor}) - set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH ${_patch}) - endif() - - set(${ESV_VARIABLE_PREFIX}_SOVERSION ${ESV_SOVERSION}) - - if(NOT project_manages_version) - set(PROJECT_VERSION "${_version}") - set(PROJECT_VERSION_MAJOR "${_major}") - set(PROJECT_VERSION_MINOR "${_minor}") - set(PROJECT_VERSION_PATCH "${_patch}") - endif() - - # compat - set(PROJECT_VERSION_STRING "${PROJECT_VERSION}") - set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}") - - if(ESV_VERSION_HEADER) - set(HEADER_PREFIX "${ESV_VARIABLE_PREFIX}") - set(HEADER_VERSION "${_version}") - set(HEADER_VERSION_MAJOR "${_major}") - set(HEADER_VERSION_MINOR "${_minor}") - set(HEADER_VERSION_PATCH "${_patch}") - configure_file("${_ECM_SETUP_VERSION_HEADER_TEMPLATE}" "${ESV_VERSION_HEADER}") - endif() - - if(ESV_PACKAGE_VERSION_FILE) - if(NOT ESV_COMPATIBILITY) - set(ESV_COMPATIBILITY AnyNewerVersion) - endif() - write_basic_package_version_file("${ESV_PACKAGE_VERSION_FILE}" VERSION ${_version} COMPATIBILITY ${ESV_COMPATIBILITY}) - endif() - - if(should_set_prefixed_vars) - set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR "${${ESV_VARIABLE_PREFIX}_VERSION_MAJOR}" PARENT_SCOPE) - set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR "${${ESV_VARIABLE_PREFIX}_VERSION_MINOR}" PARENT_SCOPE) - set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH "${${ESV_VARIABLE_PREFIX}_VERSION_PATCH}" PARENT_SCOPE) - set(${ESV_VARIABLE_PREFIX}_VERSION "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE) - endif() - - # always set the soversion - set(${ESV_VARIABLE_PREFIX}_SOVERSION "${${ESV_VARIABLE_PREFIX}_SOVERSION}" PARENT_SCOPE) - - if(NOT project_manages_version) - set(PROJECT_VERSION "${PROJECT_VERSION}" PARENT_SCOPE) - set(PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}" PARENT_SCOPE) - set(PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR}" PARENT_SCOPE) - set(PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}" PARENT_SCOPE) - endif() - - # always set the compatibility variables - set(PROJECT_VERSION_STRING "${PROJECT_VERSION_STRING}" PARENT_SCOPE) - set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE) - -endfunction() diff --git a/lib/QtKeychain/cmake/Modules/GNUInstallDirs.cmake b/lib/QtKeychain/cmake/Modules/GNUInstallDirs.cmake deleted file mode 100644 index 0302e4be..00000000 --- a/lib/QtKeychain/cmake/Modules/GNUInstallDirs.cmake +++ /dev/null @@ -1,188 +0,0 @@ -# - Define GNU standard installation directories -# Provides install directory variables as defined for GNU software: -# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html -# Inclusion of this module defines the following variables: -# CMAKE_INSTALL_ - destination for files of a given type -# CMAKE_INSTALL_FULL_ - corresponding absolute path -# where is one of: -# BINDIR - user executables (bin) -# SBINDIR - system admin executables (sbin) -# LIBEXECDIR - program executables (libexec) -# SYSCONFDIR - read-only single-machine data (etc) -# SHAREDSTATEDIR - modifiable architecture-independent data (com) -# LOCALSTATEDIR - modifiable single-machine data (var) -# LIBDIR - object code libraries (lib or lib64 or lib/ on Debian) -# INCLUDEDIR - C header files (include) -# OLDINCLUDEDIR - C header files for non-gcc (/usr/include) -# DATAROOTDIR - read-only architecture-independent data root (share) -# DATADIR - read-only architecture-independent data (DATAROOTDIR) -# INFODIR - info documentation (DATAROOTDIR/info) -# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale) -# MANDIR - man documentation (DATAROOTDIR/man) -# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME) -# Each CMAKE_INSTALL_ value may be passed to the DESTINATION options of -# install() commands for the corresponding file type. If the includer does -# not define a value the above-shown default will be used and the value will -# appear in the cache for editing by the user. -# Each CMAKE_INSTALL_FULL_ value contains an absolute path constructed -# from the corresponding destination by prepending (if necessary) the value -# of CMAKE_INSTALL_PREFIX. - -#============================================================================= -# Copyright 2011 Nikita Krupen'ko -# Copyright 2011 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -# Installation directories -# -if(NOT DEFINED CMAKE_INSTALL_BINDIR) - set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_SBINDIR) - set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR) - set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR) - set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR) - set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR) - set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_LIBDIR) - set(_LIBDIR_DEFAULT "lib") - # Override this default 'lib' with 'lib64' iff: - # - we are on Linux system but NOT cross-compiling - # - we are NOT on debian - # - we are on a 64 bits system - # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf - # For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if - # CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu" - # See http://wiki.debian.org/Multiarch - if(CMAKE_SYSTEM_NAME MATCHES "Linux" - AND NOT CMAKE_CROSSCOMPILING) - if (EXISTS "/etc/debian_version") # is this a debian system ? - if(CMAKE_LIBRARY_ARCHITECTURE) - set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}") - endif() - else() # not debian, rely on CMAKE_SIZEOF_VOID_P: - if(NOT DEFINED CMAKE_SIZEOF_VOID_P) - message(AUTHOR_WARNING - "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. " - "Please enable at least one language before including GNUInstallDirs.") - else() - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(_LIBDIR_DEFAULT "lib64") - endif() - endif() - endif() - endif() - set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})") -endif() - -if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR) - set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR) - set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)") -endif() - -if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR) - set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)") -endif() - -#----------------------------------------------------------------------------- -# Values whose defaults are relative to DATAROOTDIR. Store empty values in -# the cache and store the defaults in local variables if the cache values are -# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes. - -if(NOT CMAKE_INSTALL_DATADIR) - set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)") - set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}") -endif() - -if(NOT CMAKE_INSTALL_INFODIR) - set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)") - set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info") -endif() - -if(NOT CMAKE_INSTALL_LOCALEDIR) - set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)") - set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale") -endif() - -if(NOT CMAKE_INSTALL_MANDIR) - set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)") - set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man") -endif() - -if(NOT CMAKE_INSTALL_DOCDIR) - set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)") - set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}") -endif() - -#----------------------------------------------------------------------------- - -mark_as_advanced( - CMAKE_INSTALL_BINDIR - CMAKE_INSTALL_SBINDIR - CMAKE_INSTALL_LIBEXECDIR - CMAKE_INSTALL_SYSCONFDIR - CMAKE_INSTALL_SHAREDSTATEDIR - CMAKE_INSTALL_LOCALSTATEDIR - CMAKE_INSTALL_LIBDIR - CMAKE_INSTALL_INCLUDEDIR - CMAKE_INSTALL_OLDINCLUDEDIR - CMAKE_INSTALL_DATAROOTDIR - CMAKE_INSTALL_DATADIR - CMAKE_INSTALL_INFODIR - CMAKE_INSTALL_LOCALEDIR - CMAKE_INSTALL_MANDIR - CMAKE_INSTALL_DOCDIR - ) - -# Result directories -# -foreach(dir - BINDIR - SBINDIR - LIBEXECDIR - SYSCONFDIR - SHAREDSTATEDIR - LOCALSTATEDIR - LIBDIR - INCLUDEDIR - OLDINCLUDEDIR - DATAROOTDIR - DATADIR - INFODIR - LOCALEDIR - MANDIR - DOCDIR - ) - if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}}) - set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}") - else() - set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}") - endif() -endforeach() diff --git a/lib/QtKeychain/gnomekeyring.cpp b/lib/QtKeychain/gnomekeyring.cpp deleted file mode 100644 index 6347052d..00000000 --- a/lib/QtKeychain/gnomekeyring.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "gnomekeyring_p.h" - -const char* GnomeKeyring::GNOME_KEYRING_DEFAULT = nullptr; - -bool GnomeKeyring::isAvailable() -{ - const GnomeKeyring& keyring = instance(); - return keyring.isLoaded() && - keyring.NETWORK_PASSWORD && - keyring.is_available && - keyring.find_password && - keyring.store_password && - keyring.delete_password && - keyring.is_available(); -} - -GnomeKeyring::gpointer GnomeKeyring::store_network_password( - const gchar* keyring, - const gchar* display_name, - const gchar* user, - const gchar* server, - const gchar* type, - const gchar* password, - OperationDoneCallback callback, - gpointer data, - GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - return instance().store_password( instance().NETWORK_PASSWORD, - keyring, display_name, password, callback, - data, destroy_data, - "user", user, - "server", server, - "type", type, - static_cast(0) ); -} - -GnomeKeyring::gpointer GnomeKeyring::find_network_password( - const gchar* user, const gchar* server, const gchar* type, - OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - - return instance().find_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, "type", type, - static_cast(0) ); -} - -GnomeKeyring::gpointer GnomeKeyring::delete_network_password( const gchar* user, - const gchar* server, - OperationDoneCallback callback, - gpointer data, - GDestroyNotify destroy_data ) -{ - if ( !isAvailable() ) - return 0; - return instance().delete_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, static_cast(0) ); -} - -GnomeKeyring::GnomeKeyring() - : QLibrary(QLatin1String("gnome-keyring"), 0) -{ - static const PasswordSchema schema = { - ITEM_NETWORK_PASSWORD, - {{ "user", ATTRIBUTE_TYPE_STRING }, - { "server", ATTRIBUTE_TYPE_STRING }, - { "type", ATTRIBUTE_TYPE_STRING }, - { 0, static_cast( 0 ) }} - }; - - NETWORK_PASSWORD = &schema; - is_available = reinterpret_cast( resolve( "gnome_keyring_is_available" ) ); - find_password = reinterpret_cast( resolve( "gnome_keyring_find_password" ) ); - store_password = reinterpret_cast( resolve( "gnome_keyring_store_password" ) ); - delete_password = reinterpret_cast( resolve( "gnome_keyring_delete_password" ) ); -} - -GnomeKeyring& GnomeKeyring::instance() { - static GnomeKeyring keyring; - return keyring; -} diff --git a/lib/QtKeychain/gnomekeyring_p.h b/lib/QtKeychain/gnomekeyring_p.h deleted file mode 100644 index 87c062c3..00000000 --- a/lib/QtKeychain/gnomekeyring_p.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QTKEYCHAIN_GNOME_P_H -#define QTKEYCHAIN_GNOME_P_H - -#include - -class GnomeKeyring : private QLibrary { - Q_OBJECT - -public: - enum Result { - RESULT_OK, - RESULT_DENIED, - RESULT_NO_KEYRING_DAEMON, - RESULT_ALREADY_UNLOCKED, - RESULT_NO_SUCH_KEYRING, - RESULT_BAD_ARGUMENTS, - RESULT_IO_ERROR, - RESULT_CANCELLED, - RESULT_KEYRING_ALREADY_EXISTS, - RESULT_NO_MATCH - }; - - enum ItemType { - ITEM_GENERIC_SECRET = 0, - ITEM_NETWORK_PASSWORD, - ITEM_NOTE, - ITEM_CHAINED_KEYRING_PASSWORD, - ITEM_ENCRYPTION_KEY_PASSWORD, - ITEM_PK_STORAGE = 0x100 - }; - - enum AttributeType { - ATTRIBUTE_TYPE_STRING, - ATTRIBUTE_TYPE_UINT32 - }; - - typedef char gchar; - typedef void* gpointer; - typedef bool gboolean; - typedef struct { - ItemType item_type; - struct { - const gchar* name; - AttributeType type; - } attributes[32]; - } PasswordSchema; - - typedef void ( *OperationGetStringCallback )( Result result, bool binary, - const char* string, gpointer data ); - typedef void ( *OperationDoneCallback )( Result result, gpointer data ); - typedef void ( *GDestroyNotify )( gpointer data ); - - static const char* GNOME_KEYRING_DEFAULT; - - static bool isAvailable(); - - static gpointer store_network_password( const gchar* keyring, const gchar* display_name, - const gchar* user, const gchar* server, - const gchar* type, const gchar* password, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); - - static gpointer find_network_password( const gchar* user, const gchar* server, - const gchar* type, - OperationGetStringCallback callback, - gpointer data, GDestroyNotify destroy_data ); - - static gpointer delete_network_password( const gchar* user, const gchar* server, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); -private: - GnomeKeyring(); - - static GnomeKeyring& instance(); - - const PasswordSchema* NETWORK_PASSWORD; - typedef gboolean ( is_available_fn )( void ); - typedef gpointer ( store_password_fn )( const PasswordSchema* schema, const gchar* keyring, - const gchar* display_name, const gchar* password, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - typedef gpointer ( find_password_fn )( const PasswordSchema* schema, - OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - typedef gpointer ( delete_password_fn )( const PasswordSchema* schema, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, - ... ); - - is_available_fn* is_available; - find_password_fn* find_password; - store_password_fn* store_password; - delete_password_fn* delete_password; -}; - - -#endif diff --git a/lib/QtKeychain/keychain.cpp b/lib/QtKeychain/keychain.cpp deleted file mode 100644 index 90ee4eb5..00000000 --- a/lib/QtKeychain/keychain.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ -#include "keychain.h" -#include "keychain_p.h" - -using namespace QKeychain; - -Job::Job( JobPrivate *q, QObject *parent ) - : QObject( parent ) - , d ( q ) { -} - -Job::~Job() { - delete d; -} - -QString Job::service() const { - return d->service; -} - -QSettings* Job::settings() const { - return d->settings; -} - -void Job::setSettings( QSettings* settings ) { - d->settings = settings; -} - -void Job::start() { - QMetaObject::invokeMethod( this, "doStart", Qt::QueuedConnection ); -} - -bool Job::autoDelete() const { - return d->autoDelete; -} - -void Job::setAutoDelete( bool autoDelete ) { - d->autoDelete = autoDelete; -} - -bool Job::insecureFallback() const { - return d->insecureFallback; -} - -void Job::setInsecureFallback( bool insecureFallback ) { - d->insecureFallback = insecureFallback; -} - -void Job::doStart() { - JobExecutor::instance()->enqueue( this ); -} - -void Job::emitFinished() { - emit finished( this ); - if ( d->autoDelete ) - deleteLater(); -} - -void Job::emitFinishedWithError( Error error, const QString& errorString ) { - d->error = error; - d->errorString = errorString; - emitFinished(); -} - -void Job::scheduledStart() { - d->scheduledStart(); -} - -Error Job::error() const { - return d->error; -} - -QString Job::errorString() const { - return d->errorString; -} - -void Job::setError( Error error ) { - d->error = error; -} - -void Job::setErrorString( const QString& errorString ) { - d->errorString = errorString; -} - -ReadPasswordJob::ReadPasswordJob( const QString& service, QObject* parent ) - : Job( new ReadPasswordJobPrivate( service, this ), parent ) { - -} - -ReadPasswordJob::~ReadPasswordJob() { -} - -QString ReadPasswordJob::textData() const { - return QString::fromUtf8( d->data ); -} - -QByteArray ReadPasswordJob::binaryData() const { - return d->data; -} - -QString Job::key() const { - return d->key; -} - -void Job::setKey( const QString& key_ ) { - d->key = key_; -} - -WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent ) - : Job( new WritePasswordJobPrivate( service, this ), parent ) { -} - -WritePasswordJob::~WritePasswordJob() { -} - -void WritePasswordJob::setBinaryData( const QByteArray& data ) { - d->data = data; - d->mode = JobPrivate::Binary; -} - -void WritePasswordJob::setTextData( const QString& data ) { - d->data = data.toUtf8(); - d->mode = JobPrivate::Text; -} - -DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent ) - : Job( new DeletePasswordJobPrivate( service, this ), parent ) { -} - -DeletePasswordJob::~DeletePasswordJob() { -} - -DeletePasswordJobPrivate::DeletePasswordJobPrivate(const QString &service_, DeletePasswordJob *qq) : - JobPrivate(service_, qq) { - -} - -JobExecutor::JobExecutor() - : QObject( 0 ) - , m_jobRunning( false ) { -} - -void JobExecutor::enqueue( Job* job ) { - m_queue.enqueue( job ); - startNextIfNoneRunning(); -} - -void JobExecutor::startNextIfNoneRunning() { - if ( m_queue.isEmpty() || m_jobRunning ) - return; - QPointer next; - while ( !next && !m_queue.isEmpty() ) { - next = m_queue.dequeue(); - } - if ( next ) { - connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) ); - connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) ); - m_jobRunning = true; - next->scheduledStart(); - } -} - -void JobExecutor::jobDestroyed( QObject* object ) { - Job* job = static_cast(object); - Q_UNUSED( object ) // for release mode - job->disconnect( this ); - m_jobRunning = false; - startNextIfNoneRunning(); -} - -void JobExecutor::jobFinished( Job* job ) { - Q_UNUSED( job ) // for release mode - job->disconnect( this ); - m_jobRunning = false; - startNextIfNoneRunning(); -} - -JobExecutor* JobExecutor::s_instance = 0; - -JobExecutor* JobExecutor::instance() { - if ( !s_instance ) - s_instance = new JobExecutor; - return s_instance; -} - -ReadPasswordJobPrivate::ReadPasswordJobPrivate(const QString &service_, ReadPasswordJob *qq) : - JobPrivate(service_, qq) { - -} - -JobPrivate::JobPrivate(const QString &service_, Job *qq) - : q(qq) - , mode( Text ) - , error( NoError ) - , service( service_ ) - , autoDelete( true ) - , insecureFallback( false ) -{ -} - -QString JobPrivate::modeToString(Mode m) -{ - switch (m) { - case Text: - return QLatin1String("Text"); - case Binary: - return QLatin1String("Binary"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value"); - return QString(); -} - -JobPrivate::Mode JobPrivate::stringToMode(const QString& s) -{ - if (s == QLatin1String("Text") || s == QLatin1String("1")) - return Text; - if (s == QLatin1String("Binary") || s == QLatin1String("2")) - return Binary; - - qCritical("Unexpected mode string '%s'", qPrintable(s)); - - return Text; -} - -WritePasswordJobPrivate::WritePasswordJobPrivate(const QString &service_, WritePasswordJob *qq) : - JobPrivate(service_, qq) { - -} diff --git a/lib/QtKeychain/keychain.h b/lib/QtKeychain/keychain.h deleted file mode 100644 index 45337c6c..00000000 --- a/lib/QtKeychain/keychain.h +++ /dev/null @@ -1,271 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ -#ifndef KEYCHAIN_H -#define KEYCHAIN_H - -#if !defined(QTKEYCHAIN_NO_EXPORT) -#include "qkeychain_export.h" -#else -#define QKEYCHAIN_EXPORT -#endif - -#include -#include - -class QSettings; - -#define QTKEYCHAIN_VERSION 0x000100 - -namespace QKeychain { - -/** - * Error codes - */ -enum Error { - NoError=0, /**< No error occurred, operation was successful */ - EntryNotFound, /**< For the given key no data was found */ - CouldNotDeleteEntry, /**< Could not delete existing secret data */ - AccessDeniedByUser, /**< User denied access to keychain */ - AccessDenied, /**< Access denied for other reasons */ - NoBackendAvailable, /**< No platform-specific keychain service available */ - NotImplemented, /**< Not implemented on platform */ - OtherError /**< Something else went wrong (errorString() might provide details) */ -}; - -class JobExecutor; -class JobPrivate; - -/** - * @brief Abstract base class for all QKeychain jobs. - */ -class QKEYCHAIN_EXPORT Job : public QObject { - Q_OBJECT -public: - ~Job() override; - - /** - * @return The QSettings instance used as plaintext storage if insecureFallback() is true. - * @see setSettings() - * @see insecureFallback() - */ - QSettings* settings() const; - - /** - * @return Set the QSettings instance that will be used as plaintext storage if insecureFallback() is true. - * @see settings() - * @see insecureFallback() - */ - void setSettings( QSettings* settings ); - - /** - * Call this method to start the job. - * Typically you want to connect some slot to the finished() signal first: - * - * \code - * SomeClass::startJob() - * { - * connect(job, &Job::finished, this, &SomeClass::slotJobFinished); - * job->start(); - * } - * - * SomeClass::slotJobFinished(Job *job) - * { - * if (job->error()) { - * // handle error - * } else { - * // do job-specific stuff - * } - * } - * \endcode - * - * @see finished() - */ - void start(); - - QString service() const; - - /** - * @note Call this method only after finished() has been emitted. - * @return The error code of the job (0 if no error). - */ - Error error() const; - - /** - * @return An error message that might provide details if error() returns OtherError. - */ - QString errorString() const; - - /** - * @return Whether this job autodeletes itself once finished() has been emitted. Default is true. - * @see setAutoDelete() - */ - bool autoDelete() const; - - /** - * Set whether this job should autodelete itself once finished() has been emitted. - * @see autoDelete() - */ - void setAutoDelete( bool autoDelete ); - - /** - * @return Whether this job will use plaintext storage on unsupported platforms. Default is false. - * @see setInsecureFallback() - */ - bool insecureFallback() const; - - /** - * Set whether this job should use plaintext storage on unsupported platforms. - * @see insecureFallback() - */ - void setInsecureFallback( bool insecureFallback ); - - /** - * @return The string used as key by this job. - * @see setKey() - */ - QString key() const; - - /** - * Set the @p key that this job will use to read or write data from/to the keychain. - * The key can be an empty string. - * @see key() - */ - void setKey( const QString& key ); - - void emitFinished(); - void emitFinishedWithError(Error, const QString& errorString); - -Q_SIGNALS: - /** - * Emitted when this job is finished. - * You can connect to this signal to be notified about the job's completion. - * @see start() - */ - void finished( QKeychain::Job* ); - -protected: - explicit Job( JobPrivate *q, QObject* parent=nullptr ); - Q_INVOKABLE void doStart(); - -private: - void setError( Error error ); - void setErrorString( const QString& errorString ); - - void scheduledStart(); - -protected: - JobPrivate* const d; - -friend class JobExecutor; -friend class JobPrivate; -friend class ReadPasswordJobPrivate; -friend class WritePasswordJobPrivate; -friend class DeletePasswordJobPrivate; -}; - -class ReadPasswordJobPrivate; - -/** - * @brief Job for reading secrets from the keychain. - * You can use a ReadPasswordJob to read passwords or binary data from the keychain. - * This job requires a "service" string, which is basically a namespace of keys within the keychain. - * This means that you can read all the pairs stored in the same service string. - */ -class QKEYCHAIN_EXPORT ReadPasswordJob : public Job { - Q_OBJECT -public: - /** - * Create a new ReadPasswordJob. - * @param service The service string used by this job (can be empty). - * @param parent The parent of this job. - */ - explicit ReadPasswordJob( const QString& service, QObject* parent=nullptr ); - ~ReadPasswordJob() override; - - /** - * @return The binary data stored as value of this job's key(). - * @see Job::key() - */ - QByteArray binaryData() const; - - /** - * @return The string stored as value of this job's key(). - * @see Job::key() - * @warning Returns meaningless data if the data was stored as binary data. - * @see WritePasswordJob::setTextData() - */ - QString textData() const; - -private: - friend class QKeychain::ReadPasswordJobPrivate; -}; - -class WritePasswordJobPrivate; - -/** - * @brief Job for writing secrets to the keychain. - * You can use a WritePasswordJob to store passwords or binary data in the keychain. - * This job requires a "service" string, which is basically a namespace of keys within the keychain. - * This means that you can store different pairs under the same service string. - */ -class QKEYCHAIN_EXPORT WritePasswordJob : public Job { - Q_OBJECT -public: - /** - * Create a new WritePasswordJob. - * @param service The service string used by this job (can be empty). - * @param parent The parent of this job. - */ - explicit WritePasswordJob( const QString& service, QObject* parent=nullptr ); - ~WritePasswordJob() override; - - /** - * Set the @p data that the job will store in the keychain as binary data. - * @warning setBinaryData() and setTextData() are mutually exclusive. - */ - void setBinaryData( const QByteArray& data ); - - /** - * Set the @p data that the job will store in the keychain as string. - * Typically @p data is a password. - * @warning setBinaryData() and setTextData() are mutually exclusive. - */ - void setTextData( const QString& data ); - -private: - - friend class QKeychain::WritePasswordJobPrivate; -}; - -class DeletePasswordJobPrivate; - -/** - * @brief Job for deleting secrets from the keychain. - * You can use a DeletePasswordJob to delete passwords or binary data from the keychain. - * This job requires a "service" string, which is basically a namespace of keys within the keychain. - * This means that you can delete all the pairs stored in the same service string. - */ -class QKEYCHAIN_EXPORT DeletePasswordJob : public Job { - Q_OBJECT -public: - /** - * Create a new DeletePasswordJob. - * @param service The service string used by this job (can be empty). - * @param parent The parent of this job. - */ - explicit DeletePasswordJob( const QString& service, QObject* parent=nullptr ); - ~DeletePasswordJob() override; - -private: - friend class QKeychain::DeletePasswordJobPrivate; -}; - -} // namespace QtKeychain - -#endif diff --git a/lib/QtKeychain/keychain_apple.mm b/lib/QtKeychain/keychain_apple.mm deleted file mode 100644 index 4662e40e..00000000 --- a/lib/QtKeychain/keychain_apple.mm +++ /dev/null @@ -1,146 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2016 Mathias Hasselmann * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ - -#include "keychain_p.h" - -#import -#import - -using namespace QKeychain; - -struct ErrorDescription -{ - QKeychain::Error code; - QString message; - - ErrorDescription(QKeychain::Error code, const QString &message) - : code(code), message(message) {} - - static ErrorDescription fromStatus(OSStatus status) - { - switch(status) { - case errSecSuccess: - return ErrorDescription(QKeychain::NoError, Job::tr("No error")); - case errSecItemNotFound: - return ErrorDescription(QKeychain::EntryNotFound, Job::tr("The specified item could not be found in the keychain")); - case errSecUserCanceled: - return ErrorDescription(QKeychain::AccessDeniedByUser, Job::tr("User canceled the operation")); - case errSecInteractionNotAllowed: - return ErrorDescription(QKeychain::AccessDenied, Job::tr("User interaction is not allowed")); - case errSecNotAvailable: - return ErrorDescription(QKeychain::AccessDenied, Job::tr("No keychain is available. You may need to restart your computer")); - case errSecAuthFailed: - return ErrorDescription(QKeychain::AccessDenied, Job::tr("The user name or passphrase you entered is not correct")); - case errSecVerifyFailed: - return ErrorDescription(QKeychain::AccessDenied, Job::tr("A cryptographic verification failure has occurred")); - case errSecUnimplemented: - return ErrorDescription(QKeychain::NotImplemented, Job::tr("Function or operation not implemented")); - case errSecIO: - return ErrorDescription(QKeychain::OtherError, Job::tr("I/O error")); - case errSecOpWr: - return ErrorDescription(QKeychain::OtherError, Job::tr("Already open with with write permission")); - case errSecParam: - return ErrorDescription(QKeychain::OtherError, Job::tr("Invalid parameters passed to a function")); - case errSecAllocate: - return ErrorDescription(QKeychain::OtherError, Job::tr("Failed to allocate memory")); - case errSecBadReq: - return ErrorDescription(QKeychain::OtherError, Job::tr("Bad parameter or invalid state for operation")); - case errSecInternalComponent: - return ErrorDescription(QKeychain::OtherError, Job::tr("An internal component failed")); - case errSecDuplicateItem: - return ErrorDescription(QKeychain::OtherError, Job::tr("The specified item already exists in the keychain")); - case errSecDecode: - return ErrorDescription(QKeychain::OtherError, Job::tr("Unable to decode the provided data")); - } - - return ErrorDescription(QKeychain::OtherError, Job::tr("Unknown error")); - } -}; - -void ReadPasswordJobPrivate::scheduledStart() -{ - NSDictionary *const query = @{ - (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, - (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), - (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), - (__bridge id) kSecReturnData: @YES, - }; - - CFTypeRef dataRef = nil; - const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef); - - data.clear(); - mode = Binary; - - if (status == errSecSuccess) { - if (dataRef) - data = QByteArray::fromCFData((CFDataRef) dataRef); - - q->emitFinished(); - } else { - const ErrorDescription error = ErrorDescription::fromStatus(status); - q->emitFinishedWithError(error.code, Job::tr("Could not retrieve private key from keystore: %1").arg(error.message)); - } - - if (dataRef) - [dataRef release]; -} - -void WritePasswordJobPrivate::scheduledStart() -{ - NSDictionary *const query = @{ - (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, - (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), - (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), - }; - - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, nil); - - if (status == errSecSuccess) { - NSDictionary *const update = @{ - (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(), - }; - - status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) update); - } else { - NSDictionary *const insert = @{ - (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, - (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), - (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), - (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(), - }; - - status = SecItemAdd((__bridge CFDictionaryRef) insert, nil); - } - - if (status == errSecSuccess) { - q->emitFinished(); - } else { - const ErrorDescription error = ErrorDescription::fromStatus(status); - q->emitFinishedWithError(error.code, tr("Could not store data in settings: %1").arg(error.message)); - } -} - -void DeletePasswordJobPrivate::scheduledStart() -{ - const NSDictionary *const query = @{ - (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, - (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), - (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), - }; - - const OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query); - - if (status == errSecSuccess) { - q->emitFinished(); - } else { - const ErrorDescription error = ErrorDescription::fromStatus(status); - q->emitFinishedWithError(error.code, Job::tr("Could not remove private key from keystore: %1").arg(error.message)); - } -} diff --git a/lib/QtKeychain/keychain_p.h b/lib/QtKeychain/keychain_p.h deleted file mode 100644 index d4794a58..00000000 --- a/lib/QtKeychain/keychain_p.h +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ -#ifndef KEYCHAIN_P_H -#define KEYCHAIN_P_H - -#include -#include -#include -#include -#include - -#if defined(KEYCHAIN_DBUS) - -#include - -#include "kwallet_interface.h" -#else - -class QDBusPendingCallWatcher; - -#endif - -#include "keychain.h" - -namespace QKeychain { - -class JobExecutor; - -class JobPrivate : public QObject { - Q_OBJECT -public: - enum Mode { - Text, - Binary - }; - - virtual void scheduledStart() = 0; - - static QString modeToString(Mode m); - static Mode stringToMode(const QString& s); - - Job* const q; - Mode mode; - QByteArray data; - -#if defined(KEYCHAIN_DBUS) - org::kde::KWallet* iface; - int walletHandle; - - static void gnomeKeyring_readCb( int result, const char* string, JobPrivate* data ); - static void gnomeKeyring_writeCb( int result, JobPrivate* self ); - - virtual void fallbackOnError(const QDBusError& err) = 0; - -protected Q_SLOTS: - void kwalletWalletFound( QDBusPendingCallWatcher* watcher ); - virtual void kwalletFinished( QDBusPendingCallWatcher* watcher ); - virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ); -#else - void kwalletWalletFound( QDBusPendingCallWatcher* ) {} - virtual void kwalletFinished( QDBusPendingCallWatcher* ) {} - virtual void kwalletOpenFinished( QDBusPendingCallWatcher* ) {} -#endif - -protected: - JobPrivate( const QString& service_, Job *q ); - -protected: - QKeychain::Error error; - QString errorString; - QString service; - bool autoDelete; - bool insecureFallback; - QPointer settings; - QString key; - -friend class Job; -friend class JobExecutor; -friend class ReadPasswordJob; -friend class WritePasswordJob; -friend class PlainTextStore; -}; - -class ReadPasswordJobPrivate : public JobPrivate { - Q_OBJECT -public: - explicit ReadPasswordJobPrivate( const QString &service_, ReadPasswordJob* qq ); - void scheduledStart() override; - -#if defined(KEYCHAIN_DBUS) - void fallbackOnError(const QDBusError& err) override; - -private Q_SLOTS: - void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) override; - void kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ); - void kwalletFinished( QDBusPendingCallWatcher* watcher ) override; -#else //moc's too dumb to respect above macros, so just define empty slot implementations -private Q_SLOTS: - void kwalletOpenFinished( QDBusPendingCallWatcher* ) {} - void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {} - void kwalletFinished( QDBusPendingCallWatcher* ) {} -#endif - - friend class ReadPasswordJob; -}; - -class WritePasswordJobPrivate : public JobPrivate { - Q_OBJECT -public: - explicit WritePasswordJobPrivate( const QString &service_, WritePasswordJob* qq ); - void scheduledStart() override; - -#if defined(KEYCHAIN_DBUS) - void fallbackOnError(const QDBusError& err) override; -#endif - - friend class WritePasswordJob; -}; - -class DeletePasswordJobPrivate : public JobPrivate { - Q_OBJECT -public: - explicit DeletePasswordJobPrivate( const QString &service_, DeletePasswordJob* qq ); - - void scheduledStart() override; - -#if defined(KEYCHAIN_DBUS) - void fallbackOnError(const QDBusError& err) override; -#endif - -protected: - void doStart(); - - friend class DeletePasswordJob; -}; - -class JobExecutor : public QObject { - Q_OBJECT -public: - - static JobExecutor* instance(); - - void enqueue( Job* job ); - -private: - explicit JobExecutor(); - void startNextIfNoneRunning(); - -private Q_SLOTS: - void jobFinished( QKeychain::Job* ); - void jobDestroyed( QObject* object ); - -private: - static JobExecutor* s_instance; - QQueue > m_queue; - bool m_jobRunning; -}; - -} - -#endif // KEYCHAIN_P_H diff --git a/lib/QtKeychain/keychain_unix.cpp b/lib/QtKeychain/keychain_unix.cpp deleted file mode 100644 index b9a8e9d1..00000000 --- a/lib/QtKeychain/keychain_unix.cpp +++ /dev/null @@ -1,586 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ -#include "keychain_p.h" -#include "gnomekeyring_p.h" -#include "libsecret_p.h" -#include "plaintextstore_p.h" - -#include - -using namespace QKeychain; - -enum KeyringBackend { - Backend_LibSecretKeyring, - Backend_GnomeKeyring, - Backend_Kwallet4, - Backend_Kwallet5 -}; - -enum DesktopEnvironment { - DesktopEnv_Gnome, - DesktopEnv_Kde4, - DesktopEnv_Plasma5, - DesktopEnv_Unity, - DesktopEnv_Xfce, - DesktopEnv_Other -}; - -// the following detection algorithm is derived from chromium, -// licensed under BSD, see base/nix/xdg_util.cc - -static DesktopEnvironment getKdeVersion() { - QByteArray value = qgetenv("KDE_SESSION_VERSION"); - if ( value == "5" ) { - return DesktopEnv_Plasma5; - } else if (value == "4" ) { - return DesktopEnv_Kde4; - } else { - // most likely KDE3 - return DesktopEnv_Other; - } -} - -static DesktopEnvironment detectDesktopEnvironment() { - QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); - if ( xdgCurrentDesktop == "GNOME" ) { - return DesktopEnv_Gnome; - } else if ( xdgCurrentDesktop == "Unity" ) { - return DesktopEnv_Unity; - } else if ( xdgCurrentDesktop == "KDE" ) { - return getKdeVersion(); - } else if ( xdgCurrentDesktop == "XFCE" ) { - return DesktopEnv_Xfce; - } - - QByteArray desktopSession = qgetenv("DESKTOP_SESSION"); - if ( desktopSession == "gnome" ) { - return DesktopEnv_Gnome; - } else if ( desktopSession == "kde" ) { - return getKdeVersion(); - } else if ( desktopSession == "kde4" ) { - return DesktopEnv_Kde4; - } else if ( desktopSession.contains("xfce") || desktopSession == "xubuntu" ) { - return DesktopEnv_Xfce; - } - - if ( !qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ) { - return DesktopEnv_Gnome; - } else if ( !qgetenv("KDE_FULL_SESSION").isEmpty() ) { - return getKdeVersion(); - } - - return DesktopEnv_Other; -} - -static bool isKwallet5Available() -{ - if (!QDBusConnection::sessionBus().isConnected()) - return false; - - org::kde::KWallet iface( - QLatin1String("org.kde.kwalletd5"), - QLatin1String("/modules/kwalletd5"), - QDBusConnection::sessionBus()); - - // At this point iface.isValid() can return false even though the - // interface is activatable by making a call. Hence we check whether - // a wallet can be opened. - - iface.setTimeout(500); - QDBusMessage reply = iface.call(QLatin1String("networkWallet")); - return reply.type() == QDBusMessage::ReplyMessage; -} - -static KeyringBackend detectKeyringBackend() -{ - /* The secret service dbus api, accessible through libsecret, is supposed - * to unify password services. - * - * Unfortunately at the time of Kubuntu 18.04 the secret service backend - * in KDE is gnome-keyring-daemon - using it has several complications: - * - the default collection isn't opened on session start, so users need - * to manually unlock it when the first application uses it - * - it's separate from the kwallet5 keyring, so switching to it means the - * existing keyring data can't be accessed anymore - * - * Thus we still prefer kwallet backends on KDE even if libsecret is - * available. - */ - - switch (detectDesktopEnvironment()) { - case DesktopEnv_Kde4: - return Backend_Kwallet4; - - case DesktopEnv_Plasma5: - if (isKwallet5Available()) { - return Backend_Kwallet5; - } - if (LibSecretKeyring::isAvailable()) { - return Backend_LibSecretKeyring; - } - if (GnomeKeyring::isAvailable()) { - return Backend_GnomeKeyring; - } - // During startup the keychain backend might just not have started yet - return Backend_Kwallet5; - - case DesktopEnv_Gnome: - case DesktopEnv_Unity: - case DesktopEnv_Xfce: - case DesktopEnv_Other: - default: - if (LibSecretKeyring::isAvailable()) { - return Backend_LibSecretKeyring; - } - if (GnomeKeyring::isAvailable()) { - return Backend_GnomeKeyring; - } - if (isKwallet5Available()) { - return Backend_Kwallet5; - } - // During startup the keychain backend might just not have started yet - // - // This doesn't need to be libsecret because LibSecretKeyring::isAvailable() - // only fails if the libsecret shared library couldn't be loaded. In contrast - // to that GnomeKeyring::isAvailable() can return false if the shared library - // *was* loaded but its libgnome_keyring::is_available() returned false. - // - // In the future there should be a difference between "API available" and - // "keychain available". - return Backend_GnomeKeyring; - } - -} - -static KeyringBackend getKeyringBackend() -{ - static KeyringBackend backend = detectKeyringBackend(); - return backend; -} - -static void kwalletReadPasswordScheduledStartImpl(const char * service, const char * path, ReadPasswordJobPrivate * priv) { - if ( QDBusConnection::sessionBus().isConnected() ) - { - priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv ); - const QDBusPendingReply reply = priv->iface->networkWallet(); - QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv ); - priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) ); - } - else - { - // D-Bus is not reachable so none can tell us something about KWalletd - QDBusError err( QDBusError::NoServer, ReadPasswordJobPrivate::tr("D-Bus is not running") ); - priv->fallbackOnError( err ); - } -} - -void ReadPasswordJobPrivate::scheduledStart() { - switch ( getKeyringBackend() ) { - case Backend_LibSecretKeyring: { - if ( !LibSecretKeyring::findPassword(key, q->service(), this) ) { - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - } break; - case Backend_GnomeKeyring: - this->mode = JobPrivate::Text; - if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), - q->service().toUtf8().constData(), - "plaintext", - reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - break; - - case Backend_Kwallet4: - kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd", "/modules/kwalletd", this); - break; - case Backend_Kwallet5: - kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd5", "/modules/kwalletd5", this); - break; - } -} - -void JobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher) -{ - watcher->deleteLater(); - const QDBusPendingReply reply = *watcher; - const QDBusPendingReply pendingReply = iface->open( reply.value(), 0, q->service() ); - QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this ); - connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) ); -} - -static QPair mapGnomeKeyringError( int result ) -{ - Q_ASSERT( result != GnomeKeyring::RESULT_OK ); - - switch ( result ) { - case GnomeKeyring::RESULT_DENIED: - return qMakePair( AccessDenied, QObject::tr("Access to keychain denied") ); - case GnomeKeyring::RESULT_NO_KEYRING_DAEMON: - return qMakePair( NoBackendAvailable, QObject::tr("No keyring daemon") ); - case GnomeKeyring::RESULT_ALREADY_UNLOCKED: - return qMakePair( OtherError, QObject::tr("Already unlocked") ); - case GnomeKeyring::RESULT_NO_SUCH_KEYRING: - return qMakePair( OtherError, QObject::tr("No such keyring") ); - case GnomeKeyring::RESULT_BAD_ARGUMENTS: - return qMakePair( OtherError, QObject::tr("Bad arguments") ); - case GnomeKeyring::RESULT_IO_ERROR: - return qMakePair( OtherError, QObject::tr("I/O error") ); - case GnomeKeyring::RESULT_CANCELLED: - return qMakePair( OtherError, QObject::tr("Cancelled") ); - case GnomeKeyring::RESULT_KEYRING_ALREADY_EXISTS: - return qMakePair( OtherError, QObject::tr("Keyring already exists") ); - case GnomeKeyring::RESULT_NO_MATCH: - return qMakePair( EntryNotFound, QObject::tr("No match") ); - default: - break; - } - - return qMakePair( OtherError, QObject::tr("Unknown error") ); -} - -void JobPrivate::gnomeKeyring_readCb( int result, const char* string, JobPrivate* self ) -{ - if ( result == GnomeKeyring::RESULT_OK ) { - if (self->mode == JobPrivate::Text) - self->data = QByteArray(string); - else - self->data = QByteArray::fromBase64(string); - - self->q->emitFinished(); - } else if (self->mode == JobPrivate::Text) { - self->mode = JobPrivate::Binary; - if ( !GnomeKeyring::find_network_password( self->key.toUtf8().constData(), - self->q->service().toUtf8().constData(), - "base64", - reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), - self, 0 ) ) - self->q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } else { - const QPair errorResult = mapGnomeKeyringError( result ); - self->q->emitFinishedWithError( errorResult.first, errorResult.second ); - } -} - -void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err ) -{ - PlainTextStore plainTextStore( q->service(), q->settings() ); - - if ( q->insecureFallback() && plainTextStore.contains( key ) ) { - mode = plainTextStore.readMode( key ); - data = plainTextStore.readData( key ); - - if ( plainTextStore.error() != NoError ) - q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); - else - q->emitFinished(); - } else { - if ( err.type() == QDBusError::ServiceUnknown ) //KWalletd not running - q->emitFinishedWithError( NoBackendAvailable, tr("No keychain service available") ); - else - q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); - } -} - -void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { - watcher->deleteLater(); - const QDBusPendingReply reply = *watcher; - - if ( reply.isError() ) { - fallbackOnError( reply.error() ); - return; - } - - PlainTextStore plainTextStore( q->service(), q->settings() ); - - if ( plainTextStore.contains( key ) ) { - // We previously stored data in the insecure QSettings, but now have KWallet available. - // Do the migration - - data = plainTextStore.readData( key ); - const WritePasswordJobPrivate::Mode mode = plainTextStore.readMode( key ); - plainTextStore.remove( key ); - - q->emitFinished(); - - - WritePasswordJob* j = new WritePasswordJob( q->service(), 0 ); - j->setSettings( q->settings() ); - j->setKey( key ); - j->setAutoDelete( true ); - if ( mode == WritePasswordJobPrivate::Binary ) - j->setBinaryData( data ); - else if ( mode == WritePasswordJobPrivate::Text ) - j->setTextData( QString::fromUtf8( data ) ); - else - Q_ASSERT( false ); - - j->start(); - - return; - } - - walletHandle = reply.value(); - - if ( walletHandle < 0 ) { - q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") ); - return; - } - - const QDBusPendingReply nextReply = iface->entryType( walletHandle, q->service(), key, q->service() ); - QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); - connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletEntryTypeFinished(QDBusPendingCallWatcher*)) ); -} - -//Must be in sync with KWallet::EntryType (kwallet.h) -enum KWalletEntryType { - Unknown=0, - Password, - Stream, - Map -}; - -void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) { - watcher->deleteLater(); - if ( watcher->isError() ) { - const QDBusError err = watcher->error(); - q->emitFinishedWithError( OtherError, tr("Could not determine data type: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); - return; - } - - const QDBusPendingReply reply = *watcher; - const int value = reply.value(); - - switch ( value ) { - case Unknown: - q->emitFinishedWithError( EntryNotFound, tr("Entry not found") ); - return; - case Password: - mode = Text; - break; - case Stream: - mode = Binary; - break; - case Map: - q->emitFinishedWithError( EntryNotFound, tr("Unsupported entry type 'Map'") ); - return; - default: - q->emitFinishedWithError( OtherError, tr("Unknown kwallet entry type '%1'").arg( value ) ); - return; - } - - const QDBusPendingCall nextReply = (mode == Text) - ? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) ) - : QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) ); - QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); - connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletFinished(QDBusPendingCallWatcher*)) ); -} - -void ReadPasswordJobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) { - if ( !watcher->isError() ) { - if ( mode == Binary ) { - QDBusPendingReply reply = *watcher; - if (reply.isValid()) { - data = reply.value(); - } - } else { - QDBusPendingReply reply = *watcher; - if (reply.isValid()) { - data = reply.value().toUtf8(); - } - } - } - - JobPrivate::kwalletFinished(watcher); -} - -static void kwalletWritePasswordScheduledStart( const char * service, const char * path, JobPrivate * priv ) { - if ( QDBusConnection::sessionBus().isConnected() ) - { - priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv ); - const QDBusPendingReply reply = priv->iface->networkWallet(); - QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv ); - priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) ); - } - else - { - // D-Bus is not reachable so none can tell us something about KWalletd - QDBusError err( QDBusError::NoServer, WritePasswordJobPrivate::tr("D-Bus is not running") ); - priv->fallbackOnError( err ); - } -} - -void WritePasswordJobPrivate::scheduledStart() { - switch ( getKeyringBackend() ) { - case Backend_LibSecretKeyring: { - if ( !LibSecretKeyring::writePassword(service, key, service, mode, - data, this) ) { - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - } break; - case Backend_GnomeKeyring: { - QString type; - QByteArray password; - - switch(mode) { - case JobPrivate::Text: - type = QLatin1String("plaintext"); - password = data; - break; - default: - type = QLatin1String("base64"); - password = data.toBase64(); - break; - } - - QByteArray service = q->service().toUtf8(); - if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, - service.constData(), - key.toUtf8().constData(), - service.constData(), - type.toUtf8().constData(), - password.constData(), - reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - break; - - case Backend_Kwallet4: - kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this); - break; - case Backend_Kwallet5: - kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this); - break; - } -} - -void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err) -{ - if ( !q->insecureFallback() ) { - q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); - return; - } - - PlainTextStore plainTextStore( q->service(), q->settings() ); - plainTextStore.write( key, data, mode ); - - if ( plainTextStore.error() != NoError ) - q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); - else - q->emitFinished(); -} - -void JobPrivate::gnomeKeyring_writeCb(int result, JobPrivate* self ) -{ - if ( result == GnomeKeyring::RESULT_OK ) { - self->q->emitFinished(); - } else { - const QPair errorResult = mapGnomeKeyringError( result ); - self->q->emitFinishedWithError( errorResult.first, errorResult.second ); - } -} - -void JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { - watcher->deleteLater(); - QDBusPendingReply reply = *watcher; - - if ( reply.isError() ) { - fallbackOnError( reply.error() ); - return; - } - - PlainTextStore plainTextStore( q->service(), q->settings() ); - if ( plainTextStore.contains( key ) ) { - // If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data - plainTextStore.remove( key ); - } - - const int handle = reply.value(); - - if ( handle < 0 ) { - q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") ); - return; - } - - QDBusPendingReply nextReply; - - if ( mode == Text ) - nextReply = iface->writePassword( handle, q->service(), key, QString::fromUtf8(data), q->service() ); - else if ( mode == Binary ) - nextReply = iface->writeEntry( handle, q->service(), key, data, q->service() ); - else - nextReply = iface->removeEntry( handle, q->service(), key, q->service() ); - - QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); - connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletFinished(QDBusPendingCallWatcher*)) ); -} - -void JobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) { - if ( !watcher->isError() ) { - if ( mode == Binary ) { - QDBusPendingReply reply = *watcher; - if (reply.isValid()) { - data = reply.value(); - } - } else { - QDBusPendingReply reply = *watcher; - if (reply.isValid()) { - data = reply.value().toUtf8(); - } - } - } - - q->emitFinished(); -} - -void DeletePasswordJobPrivate::scheduledStart() { - switch ( getKeyringBackend() ) { - case Backend_LibSecretKeyring: { - if ( !LibSecretKeyring::deletePassword(key, q->service(), this) ) { - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - } break; - case Backend_GnomeKeyring: { - if ( !GnomeKeyring::delete_network_password( - key.toUtf8().constData(), q->service().toUtf8().constData(), - reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), - this, 0 ) ) - q->emitFinishedWithError( OtherError, tr("Unknown error") ); - } - break; - - case Backend_Kwallet4: - kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this); - break; - case Backend_Kwallet5: - kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this); - break; - } -} - -void DeletePasswordJobPrivate::fallbackOnError(const QDBusError &err) { - QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); - QSettings* actual = q->settings() ? q->settings() : local.data(); - - if ( !q->insecureFallback() ) { - q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2") - .arg( QDBusError::errorString( err.type() ), err.message() ) ); - return; - } - - actual->remove( key ); - actual->sync(); - - q->emitFinished(); - - - q->emitFinished(); -} diff --git a/lib/QtKeychain/keychain_win.cpp b/lib/QtKeychain/keychain_win.cpp deleted file mode 100644 index e888967f..00000000 --- a/lib/QtKeychain/keychain_win.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ -#include "keychain_p.h" -#include "plaintextstore_p.h" - -#include -#include - -#include - -using namespace QKeychain; - -#if defined(USE_CREDENTIAL_STORE) -#include - -void ReadPasswordJobPrivate::scheduledStart() { - LPCWSTR name = (LPCWSTR)key.utf16(); - PCREDENTIALW cred; - - if (!CredReadW(name, CRED_TYPE_GENERIC, 0, &cred)) { - Error err; - QString msg; - switch(GetLastError()) { - case ERROR_NOT_FOUND: - err = EntryNotFound; - msg = tr("Password entry not found"); - break; - default: - err = OtherError; - msg = tr("Could not decrypt data"); - break; - } - - q->emitFinishedWithError( err, msg ); - return; - } - - data = QByteArray((char*)cred->CredentialBlob, cred->CredentialBlobSize); - CredFree(cred); - - q->emitFinished(); -} - -void WritePasswordJobPrivate::scheduledStart() { - CREDENTIALW cred; - char *pwd = data.data(); - LPWSTR name = (LPWSTR)key.utf16(); - - memset(&cred, 0, sizeof(cred)); - cred.Comment = const_cast(L"QtKeychain"); - cred.Type = CRED_TYPE_GENERIC; - cred.TargetName = name; - cred.CredentialBlobSize = data.size(); - cred.CredentialBlob = (LPBYTE)pwd; - cred.Persist = CRED_PERSIST_ENTERPRISE; - - if (CredWriteW(&cred, 0)) { - q->emitFinished(); - return; - } - - DWORD err = GetLastError(); - - // Detect size-exceeded errors and provide nicer messages. - // Unfortunately these error codes aren't documented. - // Found empirically on Win10 1803 build 17134.523. - if (err == RPC_X_BAD_STUB_DATA) { - const size_t maxBlob = CRED_MAX_CREDENTIAL_BLOB_SIZE; - if (cred.CredentialBlobSize > maxBlob) { - q->emitFinishedWithError( - OtherError, - tr("Credential size exceeds maximum size of %1").arg(maxBlob)); - return; - } - } - if (err == RPC_S_INVALID_BOUND) { - const size_t maxTargetName = CRED_MAX_GENERIC_TARGET_NAME_LENGTH; - if (key.size() > maxTargetName) { - q->emitFinishedWithError( - OtherError, - tr("Credential key exceeds maximum size of %1").arg(maxTargetName)); - return; - } - } - - q->emitFinishedWithError( OtherError, tr("Writing credentials failed: Win32 error code %1").arg(err) ); -} - -void DeletePasswordJobPrivate::scheduledStart() { - LPCWSTR name = (LPCWSTR)key.utf16(); - - if (!CredDeleteW(name, CRED_TYPE_GENERIC, 0)) { - Error err; - QString msg; - switch(GetLastError()) { - case ERROR_NOT_FOUND: - err = EntryNotFound; - msg = tr("Password entry not found"); - break; - default: - err = OtherError; - msg = tr("Could not decrypt data"); - break; - } - - q->emitFinishedWithError( err, msg ); - } else { - q->emitFinished(); - } -} -#else -void ReadPasswordJobPrivate::scheduledStart() { - PlainTextStore plainTextStore( q->service(), q->settings() ); - QByteArray encrypted = plainTextStore.readData( key ); - if ( plainTextStore.error() != NoError ) { - q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); - return; - } - - DATA_BLOB blob_in, blob_out; - - blob_in.pbData = reinterpret_cast( encrypted.data() ); - blob_in.cbData = encrypted.size(); - - const BOOL ret = CryptUnprotectData( &blob_in, - nullptr, - nullptr, - nullptr, - nullptr, - 0, - &blob_out ); - if ( !ret ) { - q->emitFinishedWithError( OtherError, tr("Could not decrypt data") ); - return; - } - - data = QByteArray( reinterpret_cast( blob_out.pbData ), blob_out.cbData ); - SecureZeroMemory( blob_out.pbData, blob_out.cbData ); - LocalFree( blob_out.pbData ); - - q->emitFinished(); -} - -void WritePasswordJobPrivate::scheduledStart() { - DATA_BLOB blob_in, blob_out; - blob_in.pbData = reinterpret_cast( data.data() ); - blob_in.cbData = data.size(); - const BOOL res = CryptProtectData( &blob_in, - L"QKeychain-encrypted data", - nullptr, - nullptr, - nullptr, - 0, - &blob_out ); - if ( !res ) { - q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available? - return; - } - - const QByteArray encrypted( reinterpret_cast( blob_out.pbData ), blob_out.cbData ); - LocalFree( blob_out.pbData ); - - PlainTextStore plainTextStore( q->service(), q->settings() ); - plainTextStore.write( key, encrypted, Binary ); - if ( plainTextStore.error() != NoError ) { - q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); - return; - } - - q->emitFinished(); -} - -void DeletePasswordJobPrivate::scheduledStart() { - PlainTextStore plainTextStore( q->service(), q->settings() ); - plainTextStore.remove( key ); - if ( plainTextStore.error() != NoError ) { - q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); - } else { - q->emitFinished(); - } -} -#endif diff --git a/lib/QtKeychain/libsecret.cpp b/lib/QtKeychain/libsecret.cpp deleted file mode 100644 index 9e22a2dd..00000000 --- a/lib/QtKeychain/libsecret.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#if defined(HAVE_LIBSECRET) -#include -#endif - -#include "libsecret_p.h" - -#include - -#if defined(HAVE_LIBSECRET) -const SecretSchema* qtkeychainSchema(void) { - static const SecretSchema schema = { - "org.qt.keychain", SECRET_SCHEMA_DONT_MATCH_NAME, - { - { "user", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "server", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "type", SECRET_SCHEMA_ATTRIBUTE_STRING } - } - }; - - return &schema; -} - -typedef struct { - QKeychain::JobPrivate *self; - QString user; - QString server; -} callbackArg; - -typedef void (*secret_password_lookup_t) (const SecretSchema *schema, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data, - ...) G_GNUC_NULL_TERMINATED; -typedef gchar *(*secret_password_lookup_finish_t) (GAsyncResult *result, - GError **error); -typedef void (*secret_password_store_t) (const SecretSchema *schema, - const gchar *collection, - const gchar *label, - const gchar *password, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data, - ...) G_GNUC_NULL_TERMINATED; -typedef gboolean (*secret_password_store_finish_t) (GAsyncResult *result, - GError **error); -typedef void (*secret_password_clear_t) (const SecretSchema *schema, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data, - ...) G_GNUC_NULL_TERMINATED; -typedef gboolean (*secret_password_clear_finish_t) (GAsyncResult *result, - GError **error); -typedef void (*secret_password_free_t) (gchar *password); -typedef GQuark (*secret_error_get_quark_t) (void) G_GNUC_CONST; - -static secret_password_lookup_t secret_password_lookup_fn = nullptr; -static secret_password_lookup_finish_t secret_password_lookup_finish_fn = nullptr; -static secret_password_store_t secret_password_store_fn = nullptr; -static secret_password_store_finish_t secret_password_store_finish_fn = nullptr; -static secret_password_clear_t secret_password_clear_fn = nullptr; -static secret_password_clear_finish_t secret_password_clear_finish_fn = nullptr; -static secret_password_free_t secret_password_free_fn = nullptr; -static secret_error_get_quark_t secret_error_get_quark_fn = nullptr; - -static QKeychain::Error gerrorToCode(const GError *error) { - if (error->domain != secret_error_get_quark_fn()) { - return QKeychain::OtherError; - } - - switch(error->code) { - case SECRET_ERROR_NO_SUCH_OBJECT: - return QKeychain::EntryNotFound; - case SECRET_ERROR_IS_LOCKED: - return QKeychain::AccessDenied; - default: - return QKeychain::OtherError; - } -} - -static void -on_password_lookup (GObject *source, - GAsyncResult *result, - gpointer inst) -{ - GError *error = nullptr; - callbackArg *arg = (callbackArg*)inst; - gchar *password = secret_password_lookup_finish_fn (result, &error); - - Q_UNUSED(source); - - if (arg) { - if (error) { - QKeychain::Error code = gerrorToCode(error); - - arg->self->q->emitFinishedWithError( code, QString::fromUtf8(error->message) ); - } else { - if (password) { - QByteArray raw = QByteArray(password); - switch(arg->self->mode) { - case QKeychain::JobPrivate::Binary: - arg->self->data = QByteArray::fromBase64(raw); - break; - case QKeychain::JobPrivate::Text: - default: - arg->self->data = raw; - } - - arg->self->q->emitFinished(); - } else if (arg->self->mode == QKeychain::JobPrivate::Text) { - arg->self->mode = QKeychain::JobPrivate::Binary; - secret_password_lookup_fn (qtkeychainSchema(), nullptr, - on_password_lookup, arg, - "user", arg->user.toUtf8().constData(), - "server", arg->server.toUtf8().constData(), - "type", "base64", - nullptr); - return; - } else { - arg->self->q->emitFinishedWithError( QKeychain::EntryNotFound, QObject::tr("Entry not found") ); - } - } - } - if (error) { - g_error_free (error); - } - - if (password) { - secret_password_free_fn (password); - } - - if (arg) { - delete arg; - } -} - -static void -on_password_stored (GObject *source, - GAsyncResult *result, - gpointer inst) -{ - GError *error = nullptr; - QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst; - - Q_UNUSED(source); - - secret_password_store_finish_fn (result, &error); - - if (self) { - if (error) { - self->q->emitFinishedWithError( gerrorToCode(error), - QString::fromUtf8(error->message) ); - } else { - self->q->emitFinished(); - } - } - if (error) { - g_error_free (error); - } -} - -static void -on_password_cleared (GObject *source, - GAsyncResult *result, - gpointer inst) -{ - GError *error = nullptr; - QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst; - gboolean removed = secret_password_clear_finish_fn (result, &error); - - Q_UNUSED(source); - if (self) { - if ( error ) { - self->q->emitFinishedWithError( gerrorToCode(error), - QString::fromUtf8(error->message) ); - } else { - Q_UNUSED(removed); - self->q->emitFinished(); - } - } - if (error) { - g_error_free (error); - } -} - -static QString modeToString(QKeychain::JobPrivate::Mode mode) { - switch(mode) { - case QKeychain::JobPrivate::Binary: - return "base64"; - default: - return "plaintext"; - } -} -#endif - -bool LibSecretKeyring::isAvailable() { -#if defined(HAVE_LIBSECRET) - const LibSecretKeyring& keyring = instance(); - if (!keyring.isLoaded()) - return false; - if (secret_password_lookup_fn == nullptr) - return false; - if (secret_password_lookup_finish_fn == nullptr) - return false; - if (secret_password_store_fn == nullptr) - return false; - if (secret_password_store_finish_fn == nullptr) - return false; - if (secret_password_clear_fn == nullptr) - return false; - if (secret_password_clear_finish_fn == nullptr) - return false; - if (secret_password_free_fn == nullptr) - return false; - if (secret_error_get_quark_fn == nullptr) - return false; - return true; -#else - return false; -#endif -} - -bool LibSecretKeyring::findPassword(const QString &user, const QString &server, - QKeychain::JobPrivate *self) -{ -#if defined(HAVE_LIBSECRET) - if (!isAvailable()) { - return false; - } - - self->mode = QKeychain::JobPrivate::Text; - self->data = QByteArray(); - - callbackArg *arg = new callbackArg; - arg->self = self; - arg->user = user; - arg->server = server; - - secret_password_lookup_fn (qtkeychainSchema(), nullptr, on_password_lookup, arg, - "user", user.toUtf8().constData(), - "server", server.toUtf8().constData(), - "type", "plaintext", - nullptr); - return true; -#else - Q_UNUSED(user) - Q_UNUSED(server) - Q_UNUSED(self) - return false; -#endif -} - -bool LibSecretKeyring::writePassword(const QString &display_name, - const QString &user, - const QString &server, - const QKeychain::JobPrivate::Mode mode, - const QByteArray &password, - QKeychain::JobPrivate *self) -{ -#if defined(HAVE_LIBSECRET) - if (!isAvailable()) { - return false; - } - - QString type = modeToString(mode); - QByteArray pwd; - switch(mode) { - case QKeychain::JobPrivate::Binary: - pwd = password.toBase64(); - break; - default: - pwd = password; - break; - } - - secret_password_store_fn (qtkeychainSchema(), SECRET_COLLECTION_DEFAULT, - display_name.toUtf8().constData(), - pwd.constData(), nullptr, on_password_stored, self, - "user", user.toUtf8().constData(), - "server", server.toUtf8().constData(), - "type", type.toUtf8().constData(), - nullptr); - return true; -#else - Q_UNUSED(display_name) - Q_UNUSED(user) - Q_UNUSED(server) - Q_UNUSED(mode) - Q_UNUSED(password) - Q_UNUSED(self) - return false; -#endif -} - -bool LibSecretKeyring::deletePassword(const QString &key, const QString &service, - QKeychain::JobPrivate* self) -{ -#if defined(HAVE_LIBSECRET) - if (!isAvailable()) { - return false; - } - - secret_password_clear_fn (qtkeychainSchema(), nullptr, on_password_cleared, self, - "user", key.toUtf8().constData(), - "server", service.toUtf8().constData(), - nullptr); -#else - Q_UNUSED(key) - Q_UNUSED(service) - Q_UNUSED(self) - return false; -#endif -} - -LibSecretKeyring::LibSecretKeyring() - : QLibrary(QLatin1String("secret-1"), 0) -{ -#ifdef HAVE_LIBSECRET - if (load()) { - secret_password_lookup_fn = - (secret_password_lookup_t)resolve("secret_password_lookup"); - secret_password_lookup_finish_fn = - (secret_password_lookup_finish_t)resolve("secret_password_lookup_finish"); - secret_password_store_fn = - (secret_password_store_t)resolve("secret_password_store"); - secret_password_store_finish_fn = - (secret_password_store_finish_t)resolve("secret_password_store_finish"); - secret_password_clear_fn = - (secret_password_clear_t)resolve("secret_password_clear"); - secret_password_clear_finish_fn = - (secret_password_clear_finish_t)resolve("secret_password_clear_finish"); - secret_password_free_fn = - (secret_password_free_t)resolve("secret_password_free"); - secret_error_get_quark_fn = - (secret_error_get_quark_t)resolve("secret_error_get_quark"); - } -#endif -} - -LibSecretKeyring &LibSecretKeyring::instance() { - static LibSecretKeyring instance; - - return instance; -} diff --git a/lib/QtKeychain/libsecret_p.h b/lib/QtKeychain/libsecret_p.h deleted file mode 100644 index bd966fe0..00000000 --- a/lib/QtKeychain/libsecret_p.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef QTKEYCHAIN_LIBSECRET_P_H -#define QTKEYCHAIN_LIBSECRET_P_H - -#include - -#include "keychain_p.h" - -class LibSecretKeyring : public QLibrary { -public: - static bool isAvailable(); - - static bool findPassword(const QString& user, - const QString& server, - QKeychain::JobPrivate* self); - - static bool writePassword(const QString& display_name, - const QString& user, - const QString& server, - const QKeychain::JobPrivate::Mode type, - const QByteArray& password, - QKeychain::JobPrivate* self); - - static bool deletePassword(const QString &key, const QString &service, - QKeychain::JobPrivate* self); - -private: - LibSecretKeyring(); - - static LibSecretKeyring &instance(); -}; - - -#endif diff --git a/lib/QtKeychain/org.kde.KWallet.xml b/lib/QtKeychain/org.kde.KWallet.xml deleted file mode 100644 index 548c2f82..00000000 --- a/lib/QtKeychain/org.kde.KWallet.xml +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/QtKeychain/plaintextstore.cpp b/lib/QtKeychain/plaintextstore.cpp deleted file mode 100644 index b9d02726..00000000 --- a/lib/QtKeychain/plaintextstore.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * Copyright (C) 2016 Mathias Hasselmann * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ - -#include "plaintextstore_p.h" - -using namespace QKeychain; - -namespace { -#ifdef Q_OS_WIN -inline QString dataKey(const QString &key) { return key; } -#else // Q_OS_WIN -inline QString dataKey(const QString &key) { return key + QLatin1String("/data"); } -inline QString typeKey(const QString &key) { return key + QLatin1String("/type"); } -#endif // Q_OS_WIN -} - - -PlainTextStore::PlainTextStore(const QString &service, QSettings *settings) - : m_localSettings(settings ? 0 : new QSettings(service)) - , m_actualSettings(settings ? settings : m_localSettings.data()) - , m_error(NoError) -{ -} - -bool PlainTextStore::contains(const QString &key) const -{ - return m_actualSettings->contains(dataKey(key)); -} - -QByteArray PlainTextStore::readData(const QString &key) -{ - return read(dataKey(key)).toByteArray(); -} - -#ifndef Q_OS_WIN - -JobPrivate::Mode PlainTextStore::readMode(const QString &key) -{ - return JobPrivate::stringToMode(read(typeKey(key)).toString()); -} - -#endif // Q_OS_WIN - -void PlainTextStore::write(const QString &key, const QByteArray &data, JobPrivate::Mode mode) -{ - if (m_actualSettings->status() != QSettings::NoError) - return; - -#ifndef Q_OS_WIN - m_actualSettings->setValue(typeKey(key), JobPrivate::modeToString(mode)); -#else // Q_OS_WIN - Q_UNUSED(mode); -#endif // Q_OS_WIN - m_actualSettings->setValue(dataKey(key), data); - m_actualSettings->sync(); - - if (m_actualSettings->status() == QSettings::AccessError) { - setError(AccessDenied, tr("Could not store data in settings: access error")); - } else if (m_actualSettings->status() != QSettings::NoError) { - setError(OtherError, tr("Could not store data in settings: format error")); - } else { - setError(NoError, QString()); - } -} - -void PlainTextStore::remove(const QString &key) -{ - if (m_actualSettings->status() != QSettings::NoError) - return; - -#ifndef Q_OS_WIN - m_actualSettings->remove(typeKey(key)); -#endif // Q_OS_WIN - m_actualSettings->remove(dataKey(key)); - m_actualSettings->sync(); - - if (m_actualSettings->status() == QSettings::AccessError) { - setError(AccessDenied, tr("Could not delete data from settings: access error")); - } else if (m_actualSettings->status() != QSettings::NoError) { - setError(OtherError, tr("Could not delete data from settings: format error")); - } else { - setError(NoError, QString()); - } -} - -void PlainTextStore::setError(Error error, const QString &errorString) -{ - m_error = error; - m_errorString = errorString; -} - -QVariant PlainTextStore::read(const QString &key) -{ - const QVariant value = m_actualSettings->value(key); - - if (value.isNull()) { - setError(EntryNotFound, tr("Entry not found")); - } else { - setError(NoError, QString()); - } - - return value; -} diff --git a/lib/QtKeychain/plaintextstore_p.h b/lib/QtKeychain/plaintextstore_p.h deleted file mode 100644 index 7ec05aac..00000000 --- a/lib/QtKeychain/plaintextstore_p.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2011-2015 Frank Osterfeld * - * Copyright (C) 2016 Mathias Hasselmann * - * * - * This program is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * - * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * - * details, check the accompanying file 'COPYING'. * - *****************************************************************************/ - -#ifndef QTKEYCHAIN_PLAINTEXTSTORE_P_H -#define QTKEYCHAIN_PLAINTEXTSTORE_P_H - -#include "keychain_p.h" - -namespace QKeychain { - -class PlainTextStore { - Q_DECLARE_TR_FUNCTIONS(QKeychain::PlainTextStore) - -public: - explicit PlainTextStore(const QString &service, QSettings *settings); - - Error error() const { return m_error; } - QString errorString() const { return m_errorString; } - - bool contains(const QString &key) const; - - QByteArray readData(const QString &key); - JobPrivate::Mode readMode(const QString &key); - - void write(const QString &key, const QByteArray &data, JobPrivate::Mode mode); - void remove(const QString &key); - -private: - void setError(Error error, const QString &errorString); - QVariant read(const QString &key); - - const QScopedPointer m_localSettings; - QSettings *const m_actualSettings; - QString m_errorString; - Error m_error; -}; - -} - -#endif // QTKEYCHAIN_PLAINTEXTSTORE_P_H diff --git a/scripts/git-archive-all.sh b/scripts/git-archive-all.sh new file mode 100755 index 00000000..28d914c6 --- /dev/null +++ b/scripts/git-archive-all.sh @@ -0,0 +1,318 @@ +#!/bin/bash - +# +# From https://github.com/fabacab/git-archive-all.sh +# --- +# +# File: git-archive-all.sh +# +# Description: A utility script that builds an archive file(s) of all +# git repositories and submodules in the current path. +# Useful for creating a single tarfile of a git super- +# project that contains other submodules. +# +# Examples: Use git-archive-all.sh to create archive distributions +# from git repositories. To use, simply do: +# +# cd $GIT_DIR; git-archive-all.sh +# +# where $GIT_DIR is the root of your git superproject. +# +# License: GPL3+ +# +############################################################################### +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +############################################################################### + +# DEBUGGING +set -e # Exit on error (i.e., "be strict"). +set -C # noclobber + +# TRAP SIGNALS +trap 'cleanup' QUIT EXIT + +# For security reasons, explicitly set the internal field separator +# to newline, space, tab +OLD_IFS=$IFS +IFS="$(printf '\n \t')" + +function cleanup () { + rm -f $TMPFILE + rm -f $TMPLIST + rm -f $TOARCHIVE + IFS="$OLD_IFS" +} + +function usage () { + echo "Usage is as follows:" + echo + echo "$PROGRAM <--version>" + echo " Prints the program version number on a line by itself and exits." + echo + echo "$PROGRAM <--usage|--help|-?>" + echo " Prints this usage output and exits." + echo + echo "$PROGRAM [--format ] [--prefix ] [--verbose|-v] [--separate|-s]" + echo " [--worktree-attributes] [--tree-ish|-t ] [output_file]" + echo " Creates an archive for the entire git superproject, and its submodules" + echo " using the passed parameters, described below." + echo + echo " If '--format' is specified, the archive is created with the named" + echo " git archiver backend. Obviously, this must be a backend that git archive" + echo " understands. The format defaults to 'tar' if not specified." + echo + echo " If '--prefix' is specified, the archive's superproject and all submodules" + echo " are created with the prefix named. The default is to not use one." + echo + echo " If '--worktree-attributes' is specified, the invidual archive commands will" + echo " look for attributes in .gitattributes in the working directory too." + echo + echo " If '--separate' or '-s' is specified, individual archives will be created" + echo " for each of the superproject itself and its submodules. The default is to" + echo " concatenate individual archives into one larger archive." + echo + echo " If '--tree-ish' is specified, the archive will be created based on whatever" + echo " you define the tree-ish to be. Branch names, commit hash, etc. are acceptable." + echo " Defaults to HEAD if not specified. See git archive's documentation for more" + echo " information on what a tree-ish is." + echo + echo " If 'output_file' is specified, the resulting archive is created as the" + echo " file named. This parameter is essentially a path that must be writeable." + echo " When combined with '--separate' ('-s') this path must refer to a directory." + echo " Without this parameter or when combined with '--separate' the resulting" + echo " archive(s) are named with a dot-separated path of the archived directory and" + echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')." + echo + echo " The special value '-' (single dash) is treated as STDOUT and, when used, the" + echo " --separate option is ignored. Use a double-dash to separate the outfile from" + echo " the value of previous options. For example, to write a .zip file to STDOUT:" + echo + echo " ./$PROGRAM --format zip -- -" + echo + echo " If '--verbose' or '-v' is specified, progress will be printed." +} + +function version () { + echo "$PROGRAM version $VERSION" +} + +# Internal variables and initializations. +readonly PROGRAM=`basename "$0"` +readonly VERSION=0.3 + +SEPARATE=0 +VERBOSE=0 + +TARCMD=`command -v gtar || command -v gnutar || command -v tar` +FORMAT=tar +PREFIX= +TREEISH=HEAD +ARCHIVE_OPTS= + +# RETURN VALUES/EXIT STATUS CODES +readonly E_BAD_OPTION=254 +readonly E_UNKNOWN=255 + +# Process command-line arguments. +while test $# -gt 0; do + if [ x"$1" == x"--" ]; then + # detect argument termination + shift + break + fi + case $1 in + --format ) + shift + FORMAT="$1" + shift + ;; + + --prefix ) + shift + PREFIX="$1" + shift + ;; + + --worktree-attributes ) + ARCHIVE_OPTS+=" $1" + shift + ;; + + --separate | -s ) + shift + SEPARATE=1 + ;; + + --tree-ish | -t ) + shift + TREEISH="$1" + shift + ;; + + --version ) + version + exit + ;; + + --verbose | -v ) + shift + VERBOSE=1 + ;; + + -? | --usage | --help ) + usage + exit + ;; + + -* ) + echo "Unrecognized option: $1" >&2 + usage + exit $E_BAD_OPTION + ;; + + * ) + break + ;; + esac +done + +OLD_PWD="`pwd`" +TMPDIR=${TMPDIR:-/tmp} +TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress +TMPLIST=`mktemp "$TMPDIR/$PROGRAM.submodules.XXXXXX"` +TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"` +OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default + +if [ ! -z "$1" ]; then + OUT_FILE="$1" + if [ "-" == "$OUT_FILE" ]; then + SEPARATE=0 + fi + shift +fi + +# Validate parameters; error early, error often. +if [ "-" == "$OUT_FILE" -o $SEPARATE -ne 1 ] && [ "$FORMAT" == "tar" -a `$TARCMD --help | grep -q -- "--concatenate"; echo $?` -ne 0 ]; then + echo "Your 'tar' does not support the '--concatenate' option, which we need" + echo "to produce a single tarfile. Either install a compatible tar (such as" + echo "gnutar), or invoke $PROGRAM with the '--separate' option." + exit +elif [ $SEPARATE -eq 1 -a ! -d "$OUT_FILE" ]; then + echo "When creating multiple archives, your destination must be a directory." + echo "If it's not, you risk being surprised when your files are overwritten." + exit +elif [ `git config -l | grep -q '^core\.bare=true'; echo $?` -eq 0 ]; then + echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)." + exit +fi + +# Create the superproject's git-archive +if [ $VERBOSE -eq 1 ]; then + echo -n "creating superproject archive..." +fi +rm -f $TMPDIR/$(basename "$(pwd)").$FORMAT +git archive --format=$FORMAT --prefix="$PREFIX" $ARCHIVE_OPTS $TREEISH > $TMPDIR/$(basename "$(pwd)").$FORMAT +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi +echo $TMPDIR/$(basename "$(pwd)").$FORMAT >| $TMPFILE # clobber on purpose +superfile=`head -n 1 $TMPFILE` + +if [ $VERBOSE -eq 1 ]; then + echo -n "looking for subprojects..." +fi +# find all '.git' dirs, these show us the remaining to-be-archived dirs +# we only want directories that are below the current directory +find . -mindepth 2 -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE +# as of version 1.7.8, git places the submodule .git directories under the superprojects .git dir +# the submodules get a .git file that points to their .git dir. we need to find all of these too +find . -mindepth 2 -name '.git' -type f -print | xargs grep -l "gitdir" | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE +if [ $VERBOSE -eq 1 ]; then + echo "done" + echo " found:" + cat $TOARCHIVE | while read arch + do + echo " $arch" + done +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "archiving submodules..." +fi +git submodule >>"$TMPLIST" +while read path; do + TREEISH=$(grep "^ .*${path%/} " "$TMPLIST" | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path + cd "$path" + rm -f "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT + git archive --format=$FORMAT --prefix="${PREFIX}$path" $ARCHIVE_OPTS ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT + if [ $FORMAT == 'zip' ]; then + # delete the empty directory entry; zipped submodules won't unzip if we don't do this + zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null 2>&1 || true # remove trailing '/' + fi + echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE + cd "$OLD_PWD" +done < $TOARCHIVE +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "concatenating archives into single archive..." +fi +# Concatenate archives into a super-archive. +if [ $SEPARATE -eq 0 -o "-" == "$OUT_FILE" ]; then + if [ $FORMAT == 'tar.gz' ]; then + gunzip $superfile + superfile=${superfile:0: -3} # Remove '.gz' + sed -e '1d' $TMPFILE | while read file; do + gunzip $file + file=${file:0: -3} + $TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file" + done + gzip $superfile + superfile=$superfile.gz + elif [ $FORMAT == 'tar' ]; then + sed -e '1d' $TMPFILE | while read file; do + $TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file" + done + elif [ $FORMAT == 'zip' ]; then + sed -e '1d' $TMPFILE | while read file; do + # zip incorrectly stores the full path, so cd and then grow + cd `dirname "$file"` + zip -g "$superfile" `basename "$file"` && rm -f "$file" + done + cd "$OLD_PWD" + fi + + echo "$superfile" >| $TMPFILE # clobber on purpose +fi +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi + +if [ $VERBOSE -eq 1 ]; then + echo -n "moving archive to $OUT_FILE..." +fi +while read file; do + if [ "-" == "$OUT_FILE" ]; then + cat "$file" && rm -f "$file" + else + mv "$file" "$OUT_FILE" + fi +done < $TMPFILE +if [ $VERBOSE -eq 1 ]; then + echo "done" +fi