diff options
author | Mehdi Salem <mehdi.salem@qt.io> | 2023-09-29 18:10:44 +0200 |
---|---|---|
committer | Mohammad Mehdi Salem Naraghi <mehdi.salem@qt.io> | 2023-10-02 14:32:02 +0000 |
commit | 4c746e79f0efb650b7616bcc4876228eeb4ffe59 (patch) | |
tree | accc0a6adbd933db67f4dce7431395c11d624485 /src/libs/3rdparty/qtkeychain | |
parent | c74ed31d67671db0eac9c989a03c7605240a608e (diff) |
integrate qtkeychain as 3rdparty lib
Change-Id: I1efe32cf4964d2c4de5205462aa4ade74eb0e3b8
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Diffstat (limited to 'src/libs/3rdparty/qtkeychain')
31 files changed, 5260 insertions, 0 deletions
diff --git a/src/libs/3rdparty/qtkeychain/CMakeLists.txt b/src/libs/3rdparty/qtkeychain/CMakeLists.txt new file mode 100644 index 0000000000..d8ba7e3178 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/CMakeLists.txt @@ -0,0 +1,66 @@ +add_qtc_library(qtkeychain + DEPENDS Qt::Core + SOURCES + keychain.cpp keychain.h + qkeychain_export.h + PROPERTIES + QT_COMPILE_OPTIONS_DISABLE_WARNINGS ON +) + +if (WIN32) + option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) + + extend_qtc_library(qtkeychain SOURCES keychain_win.cpp) + + extend_qtc_library(qtkeychain + CONDITION USE_CREDENTIAL_STORE + FEATURE_INFO "CredentialStore keychain support" + DEFINES USE_CREDENTIAL_STORE=1 + ) + extend_qtc_library(qtkeychain + CONDITION NOT USE_CREDENTIAL_STORE + SOURCES plaintextstore.cpp + DEPENDS crypt32 + ) + endif() +endif() + +extend_qtc_library(qtkeychain + CONDITION APPLE + SOURCES keychain_apple.mm + DEPENDS ${FWFoundation} ${FWSecurity} +) + +if (UNIX AND NOT APPLE) + find_package(Qt6 COMPONENTS DBus REQUIRED) + + option(LIBSECRET_SUPPORT "Build with libsecret support if available" ON) + if (LIBSECRET_SUPPORT) + find_package(PkgConfig REQUIRED) + + include(FindPkgConfig) + pkg_check_modules(LIBSECRET libsecret-1) + + extend_qtc_library(qtkeychain + CONDITION LIBSECRET_FOUND + FEATURE_INFO "libsecret keychain support" + DEFINES HAVE_LIBSECRET=1 + INCLUDES ${LIBSECRET_INCLUDE_DIRS} + DEPENDS ${LIBSECRET_LIBRARIES} + ) + endif() + + qt6_add_dbus_interface(dbus_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface) + + extend_qtc_library(qtkeychain + DEFINES KEYCHAIN_DBUS=1 + DEPENDS Qt::DBus + SOURCES + gnomekeyring.cpp + keychain_unix.cpp + libsecret.cpp + plaintextstore.cpp + ${dbus_SOURCES} + ) +endif() diff --git a/src/libs/3rdparty/qtkeychain/CMakeLists.txt.upstream b/src/libs/3rdparty/qtkeychain/CMakeLists.txt.upstream new file mode 100644 index 0000000000..3b4e30d129 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/CMakeLists.txt.upstream @@ -0,0 +1,198 @@ +set(QTKEYCHAIN_VERSION 0.14.99) +set(QTKEYCHAIN_SOVERSION 1) + +project(qtkeychain VERSION ${QTKEYCHAIN_VERSION} LANGUAGES CXX) + +include(FindPkgConfig) + +### + +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules") +include(GNUInstallDirs) +include(GenerateExportHeader) +include(CMakePackageConfigHelpers) +include(ECMSetupVersion) +include(CMakeDependentOption) + +option(BUILD_TRANSLATIONS "Build translations" ON) +option(BUILD_SHARED_LIBS "Build dynamic library" OFF) + +CMAKE_DEPENDENT_OPTION(BUILD_TRANSLATIONS_AS_RESOURCES "Bundle translations with the library" OFF + "BUILD_TRANSLATIONS" OFF) + +if (WIN32) + option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) + + if (USE_CREDENTIAL_STORE) + add_definitions(-DUSE_CREDENTIAL_STORE=1) + endif() +endif() + + +find_package(Qt6 COMPONENTS Core REQUIRED) + +if(UNIX AND NOT APPLE) + find_package(Qt6 COMPONENTS DBus REQUIRED) + include_directories(${Qt6DBus_INCLUDE_DIRS}) + set(QTDBUS_LIBRARIES ${Qt6DBus_LIBRARIES}) +endif() + +if(BUILD_TRANSLATIONS) + find_package(Qt6 COMPONENTS LinguistTools REQUIRED) +endif() + +set(QTCORE_LIBRARIES ${Qt6Core_LIBRARIES}) + +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 -Werror=return-type ) +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(UNIX AND NOT APPLE) + option(LIBSECRET_SUPPORT "Build with libsecret support if available" ON) + find_package(PkgConfig REQUIRED) + pkg_check_modules(LIBSECRET libsecret-1) + + if(LIBSECRET_SUPPORT AND LIBSECRET_FOUND) + 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) + qt6_add_dbus_interface(qtkeychain_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface) + list(APPEND qtkeychain_LIBRARIES ${QTDBUS_LIBRARIES} ) +endif() + +qt6_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 qtkeychain) +add_library(${QTKEYCHAIN_TARGET_NAME} ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) +if(WIN32) + set_target_properties( ${QTKEYCHAIN_TARGET_NAME} PROPERTIES DEBUG_POSTFIX "d" ) +endif() + +file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui) +if ( BUILD_TRANSLATIONS ) + qt6_create_translation(qtkeychain_MESSAGES ${qtkeychain_TR_SOURCES} ${qtkeychain_TR_FILES}) + qt6_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 (BUILD_TRANSLATIONS_AS_RESOURCES) + set(QM_FILE_LIST "") + foreach(FILE ${qtkeychain_QM_FILES}) + list(APPEND QM_FILE_LIST "<file>${FILE}</file>") + endforeach() + string(REPLACE ";" "" QM_FILE_LIST ${QM_FILE_LIST}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/translations/translations.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) + target_sources(${QTKEYCHAIN_TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) + else() + set(QTKEYCHAIN_TRANSLATIONS_DIR + ${CMAKE_INSTALL_DATADIR}/qtkeychain/translations + CACHE PATH "The location of the QtKeychain translations" ) + install(FILES ${qtkeychain_QM_FILES} DESTINATION ${QTKEYCHAIN_TRANSLATIONS_DIR}) + endif() +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 $<INSTALL_INTERFACE:${INTERFACE_INCLUDE_SUFFIX}/>) + +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} + INSTALL_RPATH_USE_LINK_PATH TRUE +) + +if (NOT APPLE) + set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES + INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" + ) +endif() + +install(FILES keychain.h ${CMAKE_CURRENT_BINARY_DIR}/qkeychain_export.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtkeychain/ +) + +install(TARGETS ${QTKEYCHAIN_TARGET_NAME} + EXPORT QtKeychainLibraryDepends + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +### +### CMake config file +### + +configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/QtKeychainConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/QtKeychainConfig.cmake" + INSTALL_DESTINATION QtKeychain) + +ecm_setup_version("${QTKEYCHAIN_VERSION}" VARIABLE_PREFIX SNORE + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/QtKeychainConfigVersion.cmake" + SOVERSION ${QTKEYCHAIN_VERSION}) + +install(EXPORT QtKeychainLibraryDepends + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QtKeychain" +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/QtKeychainConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/QtKeychainConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/QtKeychain +) + diff --git a/src/libs/3rdparty/qtkeychain/COPYING b/src/libs/3rdparty/qtkeychain/COPYING new file mode 100644 index 0000000000..69f70fff71 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/COPYING @@ -0,0 +1,23 @@ +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/src/libs/3rdparty/qtkeychain/ChangeLog b/src/libs/3rdparty/qtkeychain/ChangeLog new file mode 100644 index 0000000000..cb383c5296 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/ChangeLog @@ -0,0 +1,109 @@ +ChangeLog +========= + +version 0.14.1 (release 2023-06-01) + + - Export QKeychain::isAvailable() to make it usable in a shared build (Volker Krause <vkrause@kde.org>) + - Protect against creating the QtKeychain::QtKeychain alias target twice (Volker Krause <vkrause@kde.org>) + +version 0.14.0 (release 2023-05-12) + + - Add Qt 6 Android support (Igor Bugaev <freedbrt@gmail.com>) + - Add QtQuick client example ((Igor Bugaev <freedbrt@gmail.com>) + - Added Dutch translation (Heimen Stoffels <vistausss@fastmail.com>) + - Fix potential freezing with Apple keychain (Claudio Cambra <developer@claudiocambra.com>) + - Add API to check whether a secure backend is available at all (Volker Krause <vkrause@kde.org>) + +version 0.13.2 (release 2021-11-18) + + - CMake: Deprecate QTKEYCHAIN_STATIC in favor of BUILD_SHARED_LIBS (be@mixxx.org) + +version 0.13.1 (release 2021-11-08) + + - KWallet: Fix deletion of entries (Issue #199) + +version 0.13.0 (release 2021-11-07) + + - Linux: Require libsecret if not explicitly disabled + - Unify implementations for macOS and iOS + - CMake: lots of fixes + +version 0.12.0 (release 2020-12-16) + + * Add Qt 6 support, drop Qt 4 support + * Require C++11 + * Add Android support (Mathias Hasselmann) + +version 0.11.1 (release 2020-09-08) + + * Build system fixes + +version 0.11.0 (release 2020-09-08) + + * Important: Debug builds on Windows now get the "d" suffix + * Various build system fixes + * Add Haiku support (François Revol <revol@free.fr>) + * Translation: Russian (Alexander Gorishnyak <kefir500@gmail.com>) + * Translation: Update French (David Geiger <david.david@mageialinux-online.org>) + +version 0.10.0 (release 2019-12-17) + + * Detect XFCE desktop correctly. (Sandro Knauß <hefee@debian.org>) + * Windows Use CRED_PERSIST_ENTERPRISE (Olivier Goffart <ogoffart@woboq.com>) + * Windows: Improve CredWrite() error handling (Christian Kamm <mail@ckamm.de>) + * Fix build with Qt 5.12.x (Sergey Ilinykh <rion4ik@gmail.com>) + * Fix Qt 4 build (Robert-André Mauchin <zebob.m@gmail.com>) + * Translation: Mandarin (Taiwan) (Poren Chiang <ren.chiang@gmail.com>) + * Translation: French (François Revol <revol@free.fr>) + +version 0.9.1 (release 2018-08-20) + * Windows Credential Store: Use CRED_PERSIST_ENTERPRISE (Olivier Goffart <ogoffart@woboq.com>) + * Secret: Don't match the schema name #114 (Christian Kamm <mail@ckamm.de>) + * Fix qmake build on Windows (Alexander Gorishnyak <kefir500@gmail.com>) + +version 0.9.0 (release 2018-07-13) + * Fall back on libsecret if kwallet is not available (Christian Kamm <mail@ckamm.de>) + * Only require QtLinguist if building translations (Victor Kropp <victor.kropp@jetbrains.com>) + * Fix building on Windows without credential store (Dmitry Ivanov <dm.vl.ivanov@gmail.com>) + * Fix Qt 4 build (Sandro Knauß <hefee@debian.org>) + * Make build of test application optional (Boris Pek <tehnick-8@yandex.ru>) + +version 0.8.0 (release 2017-04-19) + * Buildsystem improvements (Kristofer Tingdahl <kristofer.tingdahl@dgbes.com>, Hannah von Reth <hannah.vonreth@kdab.com>, Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>) + * Enable C++11 support for Qt >= 5.7 (Dmitry Ivanov <dm.vl.ivanov@gmail.com>) + * Doxygen documentation ( Elvis Angelaccio <elvis.angelaccio@kdemail.net>) + * Libsecret support (Armin Novak <armin.novak@thincast.com>) + * iOS support (Mathias Hasselmann <mathias.hasselmann@kdab.com>) + +version 0.7.0 (release 2016-05-23) + * Bump SO version due to 0.6 being binary-incompatible to previous releases + +version 0.6.2 (release 2016-04-04) + * KWallet: Fixes a crash when storing passwords, seen on Debian/KDE4 + +version 0.6.1 (release 2016-03-31) + * Fix KWallet not working (regressions in 0.6.0) + +version 0.6.0 (release 2016-03-18) + * Added support for the Windows Credential Store + +version 0.5.0 (release 2015-05-04) + * Added support for KWallet5 (KDE5/KF) + +version 0.4.0 (release 2014-09-01) + * KWallet: Handle case where no wallet exists yet (Liviu Cristian Mirea Ghiban <contact@liviucmg.com>) + * Improved desktop environment detection at runtime (Daniel Molkentin <daniel@molkentin.de>) + +version 0.3.0 (release 2014-03-13) + * Gnome Keyring supported added (Francois Ferrand <thetypz@gmail.com>) + * Improved Qt 5 support + * KWallet: Distinguish empty passwords from non-existing entries + * KWallet: Do not use hardcoded wallet name + * German translation (Daniel Molkentin <daniel@molkentin.de>) + * Romanian translation (Arthur Țițeică <arthur@psw.ro>) + +version 0.2.0: no official release + +version 0.1.0 (release 2013-01-16) + * Initial release + diff --git a/src/libs/3rdparty/qtkeychain/QtKeychainConfig.cmake.in b/src/libs/3rdparty/qtkeychain/QtKeychainConfig.cmake.in new file mode 100644 index 0000000000..084d45e57f --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/QtKeychainConfig.cmake.in @@ -0,0 +1,28 @@ +# - 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}/QtKeychainLibraryDepends.cmake") + +include(CMakeFindDependencyMacro) + +find_dependency(Qt6Core) + +if(UNIX AND NOT APPLE AND NOT ANDROID) + find_dependency(Qt6DBus) +endif() + +set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@") +get_target_property(QTKEYCHAIN_INCLUDE_DIRS "@QTKEYCHAIN_TARGET_NAME@" INTERFACE_INCLUDE_DIRECTORIES) + +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18.0 AND NOT TARGET QtKeychain::QtKeychain) + add_library(QtKeychain::QtKeychain ALIAS qtkeychain) +endif() + +check_required_components(QtKeychain) diff --git a/src/libs/3rdparty/qtkeychain/ReadMe.md b/src/libs/3rdparty/qtkeychain/ReadMe.md new file mode 100644 index 0000000000..cf0a2e1311 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/ReadMe.md @@ -0,0 +1,29 @@ +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/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMPackageConfigHelpers.cmake b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMPackageConfigHelpers.cmake new file mode 100644 index 0000000000..8d48772b70 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMPackageConfigHelpers.cmake @@ -0,0 +1,202 @@ +#.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 +# <https://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:CMakePackageConfigHelpers>`_ +# module in CMake; see that module's documentation for +# more information. +# +# :: +# +# ecm_configure_package_config_file(<input> <output> +# INSTALL_DESTINATION <path> +# [PATH_VARS <var1> [<var2> [...]] +# [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 +# <https://www.cmake.org/cmake/help/v2.8.12/cmake.html#module: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(<dep> [<version> [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 <alex.merry@kdemail.net> +# SPDX-FileCopyrightText: 2013 Stephen Kelly <steveire@gmail.com> +# +# 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/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMQueryQt.cmake b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMQueryQt.cmake new file mode 100644 index 0000000000..98eb50089e --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMQueryQt.cmake @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: 2014 Rohan Garg <rohan16garg@gmail.com> +# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org> +# SPDX-FileCopyrightText: 2014-2016 Aleix Pol <aleixpol@kde.org> +# SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org> +# SPDX-FileCopyrightText: 2022 Ahmad Samir <a.samir78@gmail.com> +# +# SPDX-License-Identifier: BSD-3-Clause +#[=======================================================================[.rst: +ECMQueryQt +--------------- +This module can be used to query the installation paths used by Qt. + +For Qt5 this uses ``qmake``, and for Qt6 this used ``qtpaths`` (the latter has built-in +support to query the paths of a target platform when cross-compiling). + +This module defines the following function: +:: + + ecm_query_qt(<result_variable> <qt_variable> [TRY]) + +Passing ``TRY`` will result in the method not making the build fail if the executable +used for querying has not been found, but instead simply print a warning message and +return an empty string. + +Example usage: + +.. code-block:: cmake + + include(ECMQueryQt) + ecm_query_qt(bin_dir QT_INSTALL_BINS) + +If the call succeeds ``${bin_dir}`` will be set to ``<prefix>/path/to/bin/dir`` (e.g. +``/usr/lib64/qt/bin/``). + +Since: 5.93 +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/QtVersionOption.cmake) +include(CheckLanguage) +check_language(CXX) +if (CMAKE_CXX_COMPILER) + # Enable the CXX language to let CMake look for config files in library dirs. + # See: https://gitlab.kitware.com/cmake/cmake/-/issues/23266 + enable_language(CXX) +endif() + +if (QT_MAJOR_VERSION STREQUAL "5") + # QUIET to accommodate the TRY option + find_package(Qt${QT_MAJOR_VERSION}Core QUIET) + if(TARGET Qt5::qmake) + get_target_property(_qmake_executable_default Qt5::qmake LOCATION) + + set(QUERY_EXECUTABLE ${_qmake_executable_default} + CACHE FILEPATH "Location of the Qt5 qmake executable") + set(_exec_name_text "Qt5 qmake") + set(_cli_option "-query") + endif() +elseif(QT_MAJOR_VERSION STREQUAL "6") + # QUIET to accommodate the TRY option + find_package(Qt6 COMPONENTS CoreTools QUIET CONFIG) + if (TARGET Qt6::qtpaths) + get_target_property(_qtpaths_executable Qt6::qtpaths LOCATION) + + set(QUERY_EXECUTABLE ${_qtpaths_executable} + CACHE FILEPATH "Location of the Qt6 qtpaths executable") + set(_exec_name_text "Qt6 qtpaths") + set(_cli_option "--query") + endif() +endif() + +function(ecm_query_qt result_variable qt_variable) + set(options TRY) + set(oneValueArgs) + set(multiValueArgs) + + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT QUERY_EXECUTABLE) + if(ARGS_TRY) + set(${result_variable} "" PARENT_SCOPE) + message(STATUS "No ${_exec_name_text} executable found. Can't check ${qt_variable}") + return() + else() + message(FATAL_ERROR "No ${_exec_name_text} executable found. Can't check ${qt_variable} as required") + endif() + endif() + execute_process( + COMMAND ${QUERY_EXECUTABLE} ${_cli_option} "${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: ${_command} \"${qt_variable}\"") + message(FATAL_ERROR "${_exec_name_text} call failed: ${return_code}") + endif() +endfunction() diff --git a/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMSetupVersion.cmake b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMSetupVersion.cmake new file mode 100644 index 0000000000..65c1688ab0 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/cmake/Modules/ECMSetupVersion.cmake @@ -0,0 +1,202 @@ +#.rst: +# ECMSetupVersion +# --------------- +# +# Handle library version information. +# +# :: +# +# ecm_setup_version(<version> +# VARIABLE_PREFIX <prefix> +# [SOVERSION <soversion>] +# [VERSION_HEADER <filename>] +# [PACKAGE_VERSION_FILE <filename> [COMPATIBILITY <compat>]] ) +# +# 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 ``<version>`` argument is of the form ``<major>.<minor>.<patch>`` +# (or ``<major>.<minor>.<patch>.<tweak>``), The following CMake variables are +# set:: +# +# <prefix>_VERSION_MAJOR - <major> +# <prefix>_VERSION_MINOR - <minor> +# <prefix>_VERSION_PATCH - <patch> +# <prefix>_VERSION - <version> +# <prefix>_VERSION_STRING - <version> (for compatibility: use <prefix>_VERSION instead) +# <prefix>_SOVERSION - <soversion>, or <major> if SOVERSION was not given +# +# If CMake policy CMP0048 is not NEW, the following CMake variables will also +# be set:: +# +# PROJECT_VERSION_MAJOR - <major> +# PROJECT_VERSION_MINOR - <minor> +# PROJECT_VERSION_PATCH - <patch> +# PROJECT_VERSION - <version> +# PROJECT_VERSION_STRING - <version> (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:: +# +# <prefix>_VERSION_MAJOR - <major> as an integer +# <prefix>_VERSION_MINOR - <minor> as an integer +# <prefix>_VERSION_PATCH - <patch> as an integer +# <prefix>_VERSION_STRING - <version> as a C string +# <prefix>_VERSION - the version as an integer +# +# ``<prefix>_VERSION`` has ``<patch>`` in the bottom 8 bits, ``<minor>`` in the +# next 8 bits and ``<major>`` in the remaining bits. Note that ``<patch>`` and +# ``<minor>`` 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 <prefix>] +# [SOVERSION <soversion>] +# [VERSION_HEADER <filename>] +# [PACKAGE_VERSION_FILE <filename>] ) +# +# 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 <alex.merry@kde.org> +# SPDX-FileCopyrightText: 2012 Alexander Neundorf <neundorf@kde.org> +# +# 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/src/libs/3rdparty/qtkeychain/cmake/Modules/QtVersionOption.cmake b/src/libs/3rdparty/qtkeychain/cmake/Modules/QtVersionOption.cmake new file mode 100644 index 0000000000..ea37da22de --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/cmake/Modules/QtVersionOption.cmake @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> +# +# SPDX-License-Identifier: BSD-3-Clause + +#[=======================================================================[.rst: +QtVersionOption +--------------- + +Adds a build option to select the major Qt version if necessary, +that is, if the major Qt version has not yet been determined otherwise +(e.g. by a corresponding ``find_package()`` call). +This module is typically included by other modules requiring knowledge +about the major Qt version. + +``QT_MAJOR_VERSION`` is defined to either be "5" or "6". + +Since 5.82.0. +#]=======================================================================] + +if (DEFINED QT_MAJOR_VERSION) + return() +endif() + +if (TARGET Qt5::Core) + set(QT_MAJOR_VERSION 5) +elseif (TARGET Qt6::Core) + set(QT_MAJOR_VERSION 6) +else() + option(BUILD_WITH_QT6 "Build against Qt 6" OFF) + + if (BUILD_WITH_QT6) + set(QT_MAJOR_VERSION 6) + else() + set(QT_MAJOR_VERSION 5) + endif() +endif() diff --git a/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp b/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp new file mode 100644 index 0000000000..6347052dcb --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/gnomekeyring.cpp @@ -0,0 +1,86 @@ +#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<char*>(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<char*>(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<char*>(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<AttributeType>( 0 ) }} + }; + + NETWORK_PASSWORD = &schema; + is_available = reinterpret_cast<is_available_fn*>( resolve( "gnome_keyring_is_available" ) ); + find_password = reinterpret_cast<find_password_fn*>( resolve( "gnome_keyring_find_password" ) ); + store_password = reinterpret_cast<store_password_fn*>( resolve( "gnome_keyring_store_password" ) ); + delete_password = reinterpret_cast<delete_password_fn*>( resolve( "gnome_keyring_delete_password" ) ); +} + +GnomeKeyring& GnomeKeyring::instance() { + static GnomeKeyring keyring; + return keyring; +} diff --git a/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h b/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h new file mode 100644 index 0000000000..87c062c375 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/gnomekeyring_p.h @@ -0,0 +1,94 @@ +#ifndef QTKEYCHAIN_GNOME_P_H +#define QTKEYCHAIN_GNOME_P_H + +#include <QLibrary> + +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/src/libs/3rdparty/qtkeychain/keychain.cpp b/src/libs/3rdparty/qtkeychain/keychain.cpp new file mode 100644 index 0000000000..90ee4eb502 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain.cpp @@ -0,0 +1,235 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * * + * 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<Job> 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<Job*>(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/src/libs/3rdparty/qtkeychain/keychain.h b/src/libs/3rdparty/qtkeychain/keychain.h new file mode 100644 index 0000000000..8c006cbcdd --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain.h @@ -0,0 +1,282 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * * + * 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 <QtCore/QObject> +#include <QtCore/QString> + +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 <key, secret> 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 <key, secret> 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 <key, secret> 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; +}; + +/** + * Checks whether there is a viable secure backend available. + * This particularly matters on UNIX platforms where multiple different backends + * exist and none might be available. + * + * Note that using the insecure fallback will work even if no secure backend is available. + * + * @since 0.14.0 + */ +QKEYCHAIN_EXPORT bool isAvailable(); + +} // namespace QtKeychain + +#endif diff --git a/src/libs/3rdparty/qtkeychain/keychain_apple.mm b/src/libs/3rdparty/qtkeychain/keychain_apple.mm new file mode 100644 index 0000000000..f9a8266be0 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain_apple.mm @@ -0,0 +1,263 @@ +/****************************************************************************** + * Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.com> * + * * + * 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 <Foundation/Foundation.h> +#import <Security/Security.h> + +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")); + } +}; + +@interface AppleKeychainInterface : NSObject + +- (instancetype)initWithJob:(Job *)job andPrivateJob:(JobPrivate *)privateJob; +- (void)keychainTaskFinished; +- (void)keychainReadTaskFinished:(NSData *)retrievedData; +- (void)keychainTaskFinishedWithError:(OSStatus)status descriptiveMessage:(NSString *)descriptiveMessage; + +@end + +@interface AppleKeychainInterface() +{ + QPointer<Job> _job; + QPointer<JobPrivate> _privateJob; +} +@end + +@implementation AppleKeychainInterface + +- (instancetype)initWithJob:(Job *)job andPrivateJob:(JobPrivate *)privateJob +{ + self = [super init]; + if (self) { + _job = job; + _privateJob = privateJob; + } + return self; +} + +- (void)dealloc +{ + [NSNotificationCenter.defaultCenter removeObserver:self]; + [super dealloc]; +} + +- (void)keychainTaskFinished +{ + if (_job) { + _job->emitFinished(); + } +} + +- (void)keychainReadTaskFinished:(NSData *)retrievedData +{ + _privateJob->data.clear(); + _privateJob->mode = JobPrivate::Binary; + + if (retrievedData != nil) { + if (_privateJob) { + _privateJob->data = QByteArray::fromNSData(retrievedData); + } + } + + if (_job) { + _job->emitFinished(); + } +} + +- (void)keychainTaskFinishedWithError:(OSStatus)status descriptiveMessage:(NSString *)descriptiveMessage +{ + const auto localisedDescriptiveMessage = Job::tr([descriptiveMessage UTF8String]); + + const ErrorDescription error = ErrorDescription::fromStatus(status); + const auto fullMessage = localisedDescriptiveMessage.isEmpty() ? error.message : QStringLiteral("%1: %2").arg(localisedDescriptiveMessage, error.message); + + if (_job) { + _job->emitFinishedWithError(error.code, fullMessage); + } +} + +@end + + +static void StartReadPassword(const QString &service, const QString &key, AppleKeychainInterface * const interface) +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + NSDictionary * const query = @{ + (__bridge NSString *)kSecClass: (__bridge NSString *)kSecClassGenericPassword, + (__bridge NSString *)kSecAttrService: service.toNSString(), + (__bridge NSString *)kSecAttrAccount: key.toNSString(), + (__bridge NSString *)kSecReturnData: @YES, + }; + + CFTypeRef dataRef = nil; + const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef); + + if (status == errSecSuccess) { + const CFDataRef castedDataRef = (CFDataRef)dataRef; + NSData * const data = (__bridge NSData *)castedDataRef; + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainReadTaskFinished:data]; + [interface release]; + }); + } else { + NSString * const descriptiveErrorString = @"Could not retrieve private key from keystore"; + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainTaskFinishedWithError:status descriptiveMessage:descriptiveErrorString]; + [interface release]; + }); + } + + if (dataRef) { + CFRelease(dataRef); + } + }); +} + +static void StartWritePassword(const QString &service, const QString &key, const QByteArray &data, AppleKeychainInterface * const interface) +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + NSDictionary * const query = @{ + (__bridge NSString *)kSecClass: (__bridge NSString *)kSecClassGenericPassword, + (__bridge NSString *)kSecAttrService: service.toNSString(), + (__bridge NSString *)kSecAttrAccount: key.toNSString(), + }; + + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, nil); + + if (status == errSecSuccess) { + NSDictionary * const update = @{ + (__bridge NSString *)kSecValueData: data.toNSData(), + }; + + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); + } else { + NSDictionary * const insert = @{ + (__bridge NSString *)kSecClass: (__bridge NSString *)kSecClassGenericPassword, + (__bridge NSString *)kSecAttrService: service.toNSString(), + (__bridge NSString *)kSecAttrAccount: key.toNSString(), + (__bridge NSString *)kSecValueData: data.toNSData(), + }; + + status = SecItemAdd((__bridge const CFDictionaryRef)insert, nil); + } + + if (status == errSecSuccess) { + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainTaskFinished]; + [interface release]; + }); + } else { + NSString * const descriptiveErrorString = @"Could not store data in settings"; + + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainTaskFinishedWithError:status descriptiveMessage:descriptiveErrorString]; + [interface release]; + }); + } + }); +} + +static void StartDeletePassword(const QString &service, const QString &key, AppleKeychainInterface * const interface) +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + NSDictionary * const query = @{ + (__bridge NSString *)kSecClass: (__bridge NSString *)kSecClassGenericPassword, + (__bridge NSString *)kSecAttrService: service.toNSString(), + (__bridge NSString *)kSecAttrAccount: key.toNSString(), + }; + + const OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + + if (status == errSecSuccess) { + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainTaskFinished]; + [interface release]; + }); + } else { + NSString * const descriptiveErrorString = @"Could not remove private key from keystore"; + dispatch_async(dispatch_get_main_queue(), ^{ + [interface keychainTaskFinishedWithError:status descriptiveMessage:descriptiveErrorString]; + [interface release]; + }); + } + }); +} + +void ReadPasswordJobPrivate::scheduledStart() +{ + AppleKeychainInterface * const interface = [[AppleKeychainInterface alloc] initWithJob:q andPrivateJob:this]; + StartReadPassword(service, key, interface); +} + +void WritePasswordJobPrivate::scheduledStart() +{ + AppleKeychainInterface * const interface = [[AppleKeychainInterface alloc] initWithJob:q andPrivateJob:this]; + StartWritePassword(service, key, data, interface); +} + +void DeletePasswordJobPrivate::scheduledStart() +{ + AppleKeychainInterface * const interface = [[AppleKeychainInterface alloc] initWithJob:q andPrivateJob:this]; + StartDeletePassword(service, key, interface); +} + +bool QKeychain::isAvailable() +{ + return true; +} diff --git a/src/libs/3rdparty/qtkeychain/keychain_p.h b/src/libs/3rdparty/qtkeychain/keychain_p.h new file mode 100644 index 0000000000..a66cb423d1 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain_p.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * * + * 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 <QCoreApplication> +#include <QObject> +#include <QPointer> +#include <QSettings> +#include <QQueue> + +#if defined(KEYCHAIN_DBUS) + +#include <QDBusPendingCallWatcher> + +#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<QSettings> 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* ) override {} + void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {} + void kwalletFinished( QDBusPendingCallWatcher* ) override {} +#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<QPointer<Job> > m_queue; + bool m_jobRunning; +}; + +} + +#endif // KEYCHAIN_P_H diff --git a/src/libs/3rdparty/qtkeychain/keychain_unix.cpp b/src/libs/3rdparty/qtkeychain/keychain_unix.cpp new file mode 100644 index 0000000000..a3e83a9687 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain_unix.cpp @@ -0,0 +1,633 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * * + * 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 <QScopedPointer> + +using namespace QKeychain; + +enum KeyringBackend { + Backend_LibSecretKeyring, + Backend_GnomeKeyring, + Backend_Kwallet4, + Backend_Kwallet5, + Backend_Kwallet6, +}; + +enum DesktopEnvironment { + DesktopEnv_Gnome, + DesktopEnv_Kde4, + DesktopEnv_Plasma5, + DesktopEnv_Plasma6, + DesktopEnv_Unity, + DesktopEnv_Xfce, + DesktopEnv_Other +}; + +static constexpr const char KWALLET6_DBUS_IFACE[] = "org.kde.kwalletd6"; +static constexpr const char KWALLET6_DBUS_PATH[] = "/modules/kwalletd6"; +static constexpr const char KWALLET5_DBUS_IFACE[] = "org.kde.kwalletd5"; +static constexpr const char KWALLET5_DBUS_PATH[] = "/modules/kwalletd5"; +static constexpr const char KWALLET4_DBUS_IFACE[] = "org.kde.kwalletd"; +static constexpr const char KWALLET4_DBUS_PATH[] = "/modules/kwalletd"; + +// 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 == "6" ) { + return DesktopEnv_Plasma6; + } else 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 isKwalletAvailable(const char *dbusIface, const char *dbusPath) +{ + if (!QDBusConnection::sessionBus().isConnected()) + return false; + + org::kde::KWallet iface( + QLatin1String(dbusIface), + QLatin1String(dbusPath), + 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 (isKwalletAvailable(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH)) { + 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_Plasma6: + if (isKwalletAvailable(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH)) { + return Backend_Kwallet6; + } + 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_Kwallet6; + + 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 (isKwalletAvailable(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH)) { + return Backend_Kwallet6; + } + if (isKwalletAvailable(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH)) { + 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<QString> 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<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ), + this, 0 ) ) + q->emitFinishedWithError( OtherError, tr("Unknown error") ); + break; + + case Backend_Kwallet4: + kwalletReadPasswordScheduledStartImpl(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); + break; + case Backend_Kwallet5: + kwalletReadPasswordScheduledStartImpl(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH, this); + break; + case Backend_Kwallet6: + kwalletReadPasswordScheduledStartImpl(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH, this); + break; + } +} + +void JobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher) +{ + watcher->deleteLater(); + const QDBusPendingReply<QString> reply = *watcher; + const QDBusPendingReply<int> 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<Error, QString> 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<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ), + self, 0 ) ) + self->q->emitFinishedWithError( OtherError, tr("Unknown error") ); + } else { + const QPair<Error, QString> 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<int> 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<int> 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<int> 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<QByteArray> reply = *watcher; + if (reply.isValid()) { + data = reply.value(); + } + } else { + QDBusPendingReply<QString> 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<QString> 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<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ), + this, 0 ) ) + q->emitFinishedWithError( OtherError, tr("Unknown error") ); + } + break; + + case Backend_Kwallet4: + kwalletWritePasswordScheduledStart(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); + break; + case Backend_Kwallet5: + kwalletWritePasswordScheduledStart(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH, this); + break; + case Backend_Kwallet6: + kwalletWritePasswordScheduledStart(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH, 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<Error, QString> errorResult = mapGnomeKeyringError( result ); + self->q->emitFinishedWithError( errorResult.first, errorResult.second ); + } +} + +void JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { + watcher->deleteLater(); + QDBusPendingReply<int> 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<int> nextReply; + + if ( !data.isNull() ) { + if ( mode == Text ) { + nextReply = iface->writePassword( handle, q->service(), key, QString::fromUtf8(data), q->service() ); + } else { + Q_ASSERT( 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<QByteArray> reply = *watcher; + if (reply.isValid()) { + data = reply.value(); + } + } else { + QDBusPendingReply<QString> 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<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ), + this, 0 ) ) + q->emitFinishedWithError( OtherError, tr("Unknown error") ); + } + break; + + case Backend_Kwallet4: + kwalletWritePasswordScheduledStart(KWALLET4_DBUS_IFACE, KWALLET4_DBUS_PATH, this); + break; + case Backend_Kwallet5: + kwalletWritePasswordScheduledStart(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH, this); + break; + case Backend_Kwallet6: + kwalletWritePasswordScheduledStart(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH, this); + break; + } +} + +void DeletePasswordJobPrivate::fallbackOnError(const QDBusError &err) { + QScopedPointer<QSettings> 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(); +} + +bool QKeychain::isAvailable() +{ + return LibSecretKeyring::isAvailable() || GnomeKeyring::isAvailable() + || isKwalletAvailable(KWALLET6_DBUS_IFACE, KWALLET6_DBUS_PATH) + || isKwalletAvailable(KWALLET5_DBUS_IFACE, KWALLET5_DBUS_PATH); +} diff --git a/src/libs/3rdparty/qtkeychain/keychain_win.cpp b/src/libs/3rdparty/qtkeychain/keychain_win.cpp new file mode 100644 index 0000000000..98dd34cbab --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/keychain_win.cpp @@ -0,0 +1,193 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * * + * 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 <windows.h> +#include <wincrypt.h> + +#include <memory> + +using namespace QKeychain; + +#if defined(USE_CREDENTIAL_STORE) +#include <wincred.h> + +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<wchar_t*>(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<BYTE*>( 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<char*>( 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<BYTE*>( 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<char*>( 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 + +bool QKeychain::isAvailable() +{ + return true; +} diff --git a/src/libs/3rdparty/qtkeychain/libsecret.cpp b/src/libs/3rdparty/qtkeychain/libsecret.cpp new file mode 100644 index 0000000000..6ee024989e --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/libsecret.cpp @@ -0,0 +1,349 @@ +#if defined(HAVE_LIBSECRET) + +#undef signals +#include <libsecret/secret.h> +#define signals + +#endif + +#include "libsecret_p.h" + + +#include <QLibrary> + +#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); + return true; +#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/src/libs/3rdparty/qtkeychain/libsecret_p.h b/src/libs/3rdparty/qtkeychain/libsecret_p.h new file mode 100644 index 0000000000..bd966fe0f7 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/libsecret_p.h @@ -0,0 +1,33 @@ +#ifndef QTKEYCHAIN_LIBSECRET_P_H +#define QTKEYCHAIN_LIBSECRET_P_H + +#include <QLibrary> + +#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/src/libs/3rdparty/qtkeychain/org.kde.KWallet.xml b/src/libs/3rdparty/qtkeychain/org.kde.KWallet.xml new file mode 100644 index 0000000000..ec4bd6e9c3 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/org.kde.KWallet.xml @@ -0,0 +1,276 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.kde.KWallet"> + <signal name="walletListDirty"> + </signal> + <signal name="walletCreated"> + <arg name="wallet" type="s" direction="out"/> + </signal> + <signal name="walletOpened"> + <arg name="wallet" type="s" direction="out"/> + </signal> + <signal name="walletAsyncOpened"> + <arg name="tId" type="i" direction="out"/> + <arg name="handle" type="i" direction="out"/> + </signal> + <signal name="walletDeleted"> + <arg name="wallet" type="s" direction="out"/> + </signal> + <signal name="walletClosed"> + <arg name="wallet" type="s" direction="out"/> + </signal> + <signal name="walletClosed"> + <arg name="handle" type="i" direction="out"/> + </signal> + <signal name="allWalletsClosed"> + </signal> + <signal name="folderListUpdated"> + <arg name="wallet" type="s" direction="out"/> + </signal> + <signal name="folderUpdated"> + <arg type="s" direction="out"/> + <arg type="s" direction="out"/> + </signal> + <signal name="applicationDisconnected"> + <arg name="wallet" type="s" direction="out"/> + <arg name="application" type="s" direction="out"/> + </signal> + <method name="isEnabled"> + <arg type="b" direction="out"/> + </method> + <method name="open"> + <arg type="i" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="wId" type="x" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="openPath"> + <arg type="i" direction="out"/> + <arg name="path" type="s" direction="in"/> + <arg name="wId" type="x" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="openAsync"> + <arg type="i" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="wId" type="x" direction="in"/> + <arg name="appid" type="s" direction="in"/> + <arg name="handleSession" type="b" direction="in"/> + </method> + <method name="openPathAsync"> + <arg type="i" direction="out"/> + <arg name="path" type="s" direction="in"/> + <arg name="wId" type="x" direction="in"/> + <arg name="appid" type="s" direction="in"/> + <arg name="handleSession" type="b" direction="in"/> + </method> + <method name="close"> + <arg type="i" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="force" type="b" direction="in"/> + </method> + <method name="close"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="force" type="b" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="sync"> + <arg name="handle" type="i" direction="in"/> + <arg name="appid" type="s" direction="in"/> + <annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/> + </method> + <method name="deleteWallet"> + <arg type="i" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + </method> + <method name="isOpen"> + <arg type="b" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + </method> + <method name="isOpen"> + <arg type="b" direction="out"/> + <arg name="handle" type="i" direction="in"/> + </method> + <method name="users"> + <arg type="as" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + </method> + <method name="changePassword"> + <arg name="wallet" type="s" direction="in"/> + <arg name="wId" type="x" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="wallets"> + <arg type="as" direction="out"/> + </method> + <method name="folderList"> + <arg type="as" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="hasFolder"> + <arg type="b" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="createFolder"> + <arg type="b" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="removeFolder"> + <arg type="b" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="entryList"> + <arg type="as" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readEntry"> + <arg type="ay" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readMap"> + <arg type="ay" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readPassword"> + <arg type="s" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readEntryList"> + <arg type="a{sv}" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readMapList"> + <arg type="a{sv}" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="readPasswordList"> + <arg type="a{sv}" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="renameEntry"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="oldName" type="s" direction="in"/> + <arg name="newName" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="writeEntry"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="value" type="ay" direction="in"/> + <arg name="entryType" type="i" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="writeEntry"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="value" type="ay" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="writeMap"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="value" type="ay" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="writePassword"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="value" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="hasEntry"> + <arg type="b" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="entryType"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="removeEntry"> + <arg type="i" direction="out"/> + <arg name="handle" type="i" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + <arg name="appid" type="s" direction="in"/> + </method> + <method name="disconnectApplication"> + <arg type="b" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="application" type="s" direction="in"/> + </method> + <method name="reconfigure"> + </method> + <method name="folderDoesNotExist"> + <arg type="b" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="folder" type="s" direction="in"/> + </method> + <method name="keyDoesNotExist"> + <arg type="b" direction="out"/> + <arg name="wallet" type="s" direction="in"/> + <arg name="folder" type="s" direction="in"/> + <arg name="key" type="s" direction="in"/> + </method> + <method name="closeAllWallets"> + </method> + <method name="networkWallet"> + <arg type="s" direction="out"/> + </method> + <method name="localWallet"> + <arg type="s" direction="out"/> + </method> + <method name="pamOpen"> + <arg name="wallet" type="s" direction="in"/> + <arg name="passwordHash" type="ay" direction="in"/> + <arg name="sessionTimeout" type="i" direction="in"/> + <annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/> + </method> + </interface> +</node> diff --git a/src/libs/3rdparty/qtkeychain/plaintextstore.cpp b/src/libs/3rdparty/qtkeychain/plaintextstore.cpp new file mode 100644 index 0000000000..b9d027264d --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/plaintextstore.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.com> * + * * + * 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/src/libs/3rdparty/qtkeychain/plaintextstore_p.h b/src/libs/3rdparty/qtkeychain/plaintextstore_p.h new file mode 100644 index 0000000000..7ec05aaca1 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/plaintextstore_p.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> * + * Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.com> * + * * + * 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<QSettings> m_localSettings; + QSettings *const m_actualSettings; + QString m_errorString; + Error m_error; +}; + +} + +#endif // QTKEYCHAIN_PLAINTEXTSTORE_P_H diff --git a/src/libs/3rdparty/qtkeychain/qkeychain_export.h b/src/libs/3rdparty/qtkeychain/qkeychain_export.h new file mode 100644 index 0000000000..14dc72287f --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/qkeychain_export.h @@ -0,0 +1,11 @@ +#pragma once + +#include <qglobal.h> + +#if defined(QTKEYCHAIN_LIBRARY) +# define QKEYCHAIN_EXPORT Q_DECL_EXPORT +#elif defined(QTKEYCHAIN_STATIC_LIBRARY) +# define QKEYCHAIN_EXPORT +#else +# define QKEYCHAIN_EXPORT Q_DECL_IMPORT +#endif diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_de.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_de.ts new file mode 100644 index 0000000000..59ed992ed1 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_de.ts @@ -0,0 +1,234 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="de_DE"> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="../keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation type="unfinished">Kann Daten nicht entschlüsseln</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="585"/> + <location filename="../keychain_unix.cpp" line="593"/> + <source>Unknown error</source> + <translation type="unfinished">Unbekannter Fehler</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="614"/> + <source>Could not open wallet: %1; %2</source> + <translation type="unfinished">Konnte Brieftasche nicht öffnen: %1; %2</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Passwort nicht gefunden</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="295"/> + <source>Unknown error</source> + <translation type="unfinished">Unbekannter Fehler</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="542"/> + <source>Access to keychain denied</source> + <translation type="unfinished">Zugriff auf Schlüsselbund verweigert</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="../plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation type="unfinished">Eintrag nicht gefunden</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="214"/> + <location filename="../keychain_unix.cpp" line="224"/> + <source>Unknown error</source> + <translation>Unbekannter Fehler</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="205"/> + <source>D-Bus is not running</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="316"/> + <source>No keychain service available</source> + <translation>Kein Schlüsselbund-Dienst verfügbar</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="318"/> + <source>Could not open wallet: %1; %2</source> + <translation>Konnte Brieftasche nicht öffnen: %1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="363"/> + <source>Access to keychain denied</source> + <translation>Zugriff auf Schlüsselbund verweigert</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="384"/> + <source>Could not determine data type: %1; %2</source> + <translation>Datentyp kann nicht ermittelt werden: %1: %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="402"/> + <source>Unsupported entry type 'Map'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="405"/> + <source>Unknown kwallet entry type '%1'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="393"/> + <source>Entry not found</source> + <translation>Eintrag nicht gefunden</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="36"/> + <location filename="../keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>Kann Daten nicht entschlüsseln</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="455"/> + <location filename="../keychain_unix.cpp" line="482"/> + <source>Unknown error</source> + <translation>Unbekannter Fehler</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="445"/> + <source>D-Bus is not running</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="501"/> + <source>Could not open wallet: %1; %2</source> + <translation>Konnte Brieftasche nicht öffnen: %1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>Verschlüsselung fehlgeschlagen</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Passwort nicht gefunden</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../keychain_unix.cpp" line="255"/> + <source>Access to keychain denied</source> + <translation>Zugriff auf Schlüsselbund verweigert</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="257"/> + <source>No keyring daemon</source> + <translation>Kein Schlüsselbund-Dienst </translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="259"/> + <source>Already unlocked</source> + <translation>Bereits entsperrt</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="261"/> + <source>No such keyring</source> + <translation>Kein solcher Schlüsselbund</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="263"/> + <source>Bad arguments</source> + <translation>Ungültige Argumente</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="265"/> + <source>I/O error</source> + <translation>Ein-/Ausgabe-Fehler</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="267"/> + <source>Cancelled</source> + <translation>Abgebrochen</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="269"/> + <source>Keyring already exists</source> + <translation>Schlüsselbund existiert bereits</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="271"/> + <source>No match</source> + <translation>Kein Treffer</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="276"/> + <source>Unknown error</source> + <translation>Unbekannter Fehler</translation> + </message> + <message> + <location filename="../libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation type="unfinished">Eintrag nicht gefunden</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_fr.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_fr.ts new file mode 100644 index 0000000000..5eee2e34da --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_fr.ts @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="fr_FR"> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="../keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation>Mot de passe introuvable</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation>Impossible de déchiffrer les données</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="585"/> + <location filename="../keychain_unix.cpp" line="593"/> + <source>Unknown error</source> + <translation>Erreur inconnue</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="614"/> + <source>Could not open wallet: %1; %2</source> + <translation>Impossible d'ouvrir le portefeuille : %1; %2</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="295"/> + <source>Unknown error</source> + <translation>Erreur inconnue</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="542"/> + <source>Access to keychain denied</source> + <translation>Accès au trousseau refusé</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="../plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation>Impossible de stocker les données dans les paramètres : Erreur d'accès</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation>Impossible de stocker les données dans les paramètres : Erreur de format</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation>Impossible de supprimer les données depuis les paramètres : Erreur d'accès</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation>Impossible de supprimer les données depuis les paramètres : Erreur de format</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation>Entrée introuvable</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="214"/> + <location filename="../keychain_unix.cpp" line="224"/> + <source>Unknown error</source> + <translation>Erreur inconnue</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="205"/> + <source>D-Bus is not running</source> + <translation>D-Bus n'est pas en cours d'exécution</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="316"/> + <source>No keychain service available</source> + <translation>Aucun service de trousseau disponible</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="318"/> + <source>Could not open wallet: %1; %2</source> + <translation>Impossible d'ouvrir le trousseau : %1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="363"/> + <source>Access to keychain denied</source> + <translation>Accès au trousseau refusé</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="384"/> + <source>Could not determine data type: %1; %2</source> + <translation>Impossible de déterminer le type de données : %1: %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="402"/> + <source>Unsupported entry type 'Map'</source> + <translation>Type d'entrée non supporté 'Map'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="405"/> + <source>Unknown kwallet entry type '%1'</source> + <translation>Type de trousseau inconnu '%1'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="393"/> + <source>Entry not found</source> + <translation>Entrée introuvable</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation>Entrée de mot de passe introuvable</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="36"/> + <location filename="../keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>Impossible de déchiffrer les données</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="455"/> + <location filename="../keychain_unix.cpp" line="482"/> + <source>Unknown error</source> + <translation>Erreur inconnue</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="445"/> + <source>D-Bus is not running</source> + <translation>D-Bus n'est pas en cours d'exécution</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="501"/> + <source>Could not open wallet: %1; %2</source> + <translation>Impossible d'ouvrir le trousseau : %1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>Le chiffrement a échoué</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../keychain_unix.cpp" line="255"/> + <source>Access to keychain denied</source> + <translation>Accès au trousseau refusé</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="257"/> + <source>No keyring daemon</source> + <translation>Aucun démon de trousseau</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="259"/> + <source>Already unlocked</source> + <translation>Déjà déverrouillé</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="261"/> + <source>No such keyring</source> + <translation>Aucun trousseau</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="263"/> + <source>Bad arguments</source> + <translation>Mauvais arguments</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="265"/> + <source>I/O error</source> + <translation>Erreur d'E/S</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="267"/> + <source>Cancelled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="269"/> + <source>Keyring already exists</source> + <translation>Trousseau déjà existant</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="271"/> + <source>No match</source> + <translation>Aucune correspondance</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="276"/> + <source>Unknown error</source> + <translation>Erreur inconnue</translation> + </message> + <message> + <location filename="../libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation>Entrée introuvable</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_nl.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_nl.ts new file mode 100644 index 0000000000..7033a98457 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_nl.ts @@ -0,0 +1,320 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> + <name>KeyChainClass</name> + <message> + <location filename="TestAppExample/keychainclass.cpp" line="22"/> + <source>Read key failed: %1</source> + <translation>De sleutel kan niet worden ingelezen: %1</translation> + </message> + <message> + <location filename="TestAppExample/keychainclass.cpp" line="37"/> + <source>Write key failed: %1</source> + <translation>De sleutel kan niet worden weggeschreven: %1</translation> + </message> + <message> + <location filename="TestAppExample/keychainclass.cpp" line="54"/> + <source>Delete key failed: %1</source> + <translation>De sleutel kan niet worden verwijderd: %1</translation> + </message> +</context> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="keychain_android.cpp" line="173"/> + <source>Could not open keystore</source> + <translation>De sleutelbos kan niet worden geopend</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="179"/> + <source>Could not remove private key from keystore</source> + <translation>De privésleutel kan niet worden verwijderd uit de sleutelbos</translation> + </message> + <message> + <location filename="keychain_haiku.cpp" line="177"/> + <source>Password not found</source> + <translation>Het wachtwoord is niet gevonden</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="552"/> + <location filename="keychain_unix.cpp" line="560"/> + <source>Unknown error</source> + <translation>Onbekende foutmelding</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="578"/> + <source>Could not open wallet: %1; %2</source> + <translation>De sleutelbos kan niet worden geopend: %1; %2</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation>Het wachtwoord is niet gevonden</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation>De gegevens kunnen niet worden ongrendeld</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="keychain_unix.cpp" line="265"/> + <source>Unknown error</source> + <translation>Onbekende foutmelding</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="509"/> + <source>Access to keychain denied</source> + <translation>U heeft geen toegang tot de sleutelbos</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation>De gegevens kunnen niet worden opgeslagen in de instellingen: toegangsfout</translation> + </message> + <message> + <location filename="plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation>De gegevens kunnen niet worden opgeslagen in de instellingen: opmaakfout</translation> + </message> + <message> + <location filename="plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation>De gegevens kunnen niet worden verwijderd uit de instellingen: toegangsfout</translation> + </message> + <message> + <location filename="plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation>De gegevens kunnen niet worden verwijderd uit de instellingen: opmaakfout</translation> + </message> + <message> + <location filename="plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation>Het item is niet gevonden</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="keychain_android.cpp" line="52"/> + <location filename="keychain_unix.cpp" line="363"/> + <source>Entry not found</source> + <translation>Het item is niet gevonden</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="60"/> + <source>Could not open keystore</source> + <translation>De sleutelbos kan niet worden geopend</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="68"/> + <source>Could not retrieve private key from keystore</source> + <translation>De privésleutel kan niet worden verwijderd uit de sleutelbos</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="75"/> + <source>Could not create decryption cipher</source> + <translation>De ontgrendelcode kan niet worden aangemaakt</translation> + </message> + <message> + <location filename="keychain_haiku.cpp" line="96"/> + <source>Password not found</source> + <translation>Het wachtwoord is niet gevonden</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="178"/> + <source>D-Bus is not running</source> + <translation>D-Bus is niet actief</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="187"/> + <location filename="keychain_unix.cpp" line="197"/> + <source>Unknown error</source> + <translation>Onbekende foutmelding</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="286"/> + <source>No keychain service available</source> + <translation>De sleutelbosdienst is niet beschikbaar</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="288"/> + <source>Could not open wallet: %1; %2</source> + <translation>De sleutelbos kan niet worden geopend: %1; %2</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="333"/> + <source>Access to keychain denied</source> + <translation>U heeft geen toegang tot de sleutelbos</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="354"/> + <source>Could not determine data type: %1; %2</source> + <translation>De gegevensdrager kan niet worden bepaald: %1; %2</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="372"/> + <source>Unsupported entry type 'Map'</source> + <translation>Niet-ondersteund itemtype ‘Map’</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="375"/> + <source>Unknown kwallet entry type '%1'</source> + <translation>Onbekend KWallet-item van type ‘%1’</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation>Het wachtwoord is niet gevonden</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="36"/> + <location filename="keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>De gegevens kunnen niet worden ongrendeld</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="keychain_android.cpp" line="95"/> + <source>Could not open keystore</source> + <translation>De sleutelbos kan niet worden geopend</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="124"/> + <source>Could not create private key generator</source> + <translation>De privésleutelgenerator kan niet worden gestart</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="131"/> + <source>Could not generate new private key</source> + <translation>Er kan geen nieuwe privésleutel worden gegenereerd</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="139"/> + <source>Could not retrieve private key from keystore</source> + <translation>De privésleutel kan niet worden opgehaald uit de sleutelbos</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="147"/> + <source>Could not create encryption cipher</source> + <translation>De vergrendelcode kan niet worden aangemaakt</translation> + </message> + <message> + <location filename="keychain_android.cpp" line="155"/> + <source>Could not encrypt data</source> + <translation>De gegevens kunnen niet worden ontgrendeld</translation> + </message> + <message> + <location filename="keychain_haiku.cpp" line="144"/> + <source>Password not found</source> + <translation>Het wachtwoord is niet gevonden</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="415"/> + <source>D-Bus is not running</source> + <translation>D-Bus is niet actief</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="425"/> + <location filename="keychain_unix.cpp" line="452"/> + <source>Unknown error</source> + <translation>Onbekende foutmelding</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="468"/> + <source>Could not open wallet: %1; %2</source> + <translation>De sleutelbos kan niet worden geopend: %1; %2</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation>De omvang overschrijdt de maximumomvang van %1</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation>De sleutel overschrijdt de maximumomvang van %1</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation>De gegevens kunnen niet worden weggeschreven: Win32-foutcode %1</translation> + </message> + <message> + <location filename="keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>Het ontgrendelen is mislukt</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="keychain_haiku.cpp" line="72"/> + <source>error 0x%1: %2</source> + <translation>foutmelding 0x%1: %2</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="225"/> + <source>Access to keychain denied</source> + <translation>U heeft geen toegang tot de sleutelbos</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="227"/> + <source>No keyring daemon</source> + <translation>De sleutelbosdienst is niet actief</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="229"/> + <source>Already unlocked</source> + <translation>De sleutelbos is reeds ontgrendeld</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="231"/> + <source>No such keyring</source> + <translation>De sleutelbos bestaat niet</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="233"/> + <source>Bad arguments</source> + <translation>Onjuiste opties</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="235"/> + <source>I/O error</source> + <translation>I/O-fout</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="237"/> + <source>Cancelled</source> + <translation>Geannuleerd</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="239"/> + <source>Keyring already exists</source> + <translation>De sleutelbos bestaat reeds</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="241"/> + <source>No match</source> + <translation>Er zijn geen overeenkomsten</translation> + </message> + <message> + <location filename="keychain_unix.cpp" line="246"/> + <source>Unknown error</source> + <translation>Onbekende foutmelding</translation> + </message> + <message> + <location filename="libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation>Het item is niet gevonden</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ro.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ro.ts new file mode 100644 index 0000000000..fb4e590676 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ro.ts @@ -0,0 +1,235 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ro_RO"> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="../keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation type="unfinished">Nu se poate decripta data</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="585"/> + <location filename="../keychain_unix.cpp" line="593"/> + <source>Unknown error</source> + <translation type="unfinished">Eroare necunoscută</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="614"/> + <source>Could not open wallet: %1; %2</source> + <translation type="unfinished">Nu se poate deschide portofelul: %1; %2</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Parola nu a fost găsită</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="295"/> + <source>Unknown error</source> + <translation type="unfinished">Eroare necunoscută</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="542"/> + <source>Access to keychain denied</source> + <translation type="unfinished">Acces interzis la serviciul de chei</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="../plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation type="unfinished">Înregistrarea nu a fost găsită</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="214"/> + <location filename="../keychain_unix.cpp" line="224"/> + <source>Unknown error</source> + <translation>Eroare necunoscută</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="205"/> + <source>D-Bus is not running</source> + <translation>D-Bus nu rulează</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="316"/> + <source>No keychain service available</source> + <translatorcomment>Nu există niciun serviciu de chei disponibil</translatorcomment> + <translation>Kein Schlüsselbund-Dienst verfügbar</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="318"/> + <source>Could not open wallet: %1; %2</source> + <translation>Nu se poate deschide portofelul: %1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="363"/> + <source>Access to keychain denied</source> + <translation>Acces interzis la serviciul de chei</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="384"/> + <source>Could not determine data type: %1; %2</source> + <translation>Nu se poate stabili tipul de date: %1: %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="402"/> + <source>Unsupported entry type 'Map'</source> + <translation>Tip de înregistrare nesuportat 'Map'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="405"/> + <source>Unknown kwallet entry type '%1'</source> + <translation>Tip de înregistrare kwallet necunoscut '%1'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="393"/> + <source>Entry not found</source> + <translation>Înregistrarea nu a fost găsită</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="36"/> + <location filename="../keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>Nu se poate decripta data</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="455"/> + <location filename="../keychain_unix.cpp" line="482"/> + <source>Unknown error</source> + <translation>Eroare necunoscută</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="445"/> + <source>D-Bus is not running</source> + <translation>D-Bus nu rulează</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="501"/> + <source>Could not open wallet: %1; %2</source> + <translation>Nu se poate deschide portofelul: %1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>Criptarea a eșuat</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Parola nu a fost găsită</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../keychain_unix.cpp" line="255"/> + <source>Access to keychain denied</source> + <translation>Acces interzis la serviciul de chei</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="257"/> + <source>No keyring daemon</source> + <translation>Niciun demon pentru inelul de chei</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="259"/> + <source>Already unlocked</source> + <translation>Deja deblocat</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="261"/> + <source>No such keyring</source> + <translation>Nu există astfel de inel de chei</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="263"/> + <source>Bad arguments</source> + <translation>Argumente greșite</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="265"/> + <source>I/O error</source> + <translation>Eroare de I/E</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="267"/> + <source>Cancelled</source> + <translation>Anulat</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="269"/> + <source>Keyring already exists</source> + <translation>Inelul de chei deja există</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="271"/> + <source>No match</source> + <translation>Nicio potrivire</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="276"/> + <source>Unknown error</source> + <translation>Eroare necunoscută</translation> + </message> + <message> + <location filename="../libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation type="unfinished">Înregistrarea nu a fost găsită</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ru.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ru.ts new file mode 100644 index 0000000000..c4cec0bb52 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_ru.ts @@ -0,0 +1,234 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="585"/> + <location filename="../keychain_unix.cpp" line="593"/> + <source>Unknown error</source> + <translation>Неизвестная ошибка</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="614"/> + <source>Could not open wallet: %1; %2</source> + <translation>Не удалось открыть бумажник: %1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation>Пароль не найден</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation>Не удалось расшифровать данные</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Пароль не найден</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="295"/> + <source>Unknown error</source> + <translation>Неизвестная ошибка</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="542"/> + <source>Access to keychain denied</source> + <translation>Доступ к связке ключей запрещён</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="../plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation>Не удалось сохранить данные в настройках: ошибка доступа</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation>Не удалось сохранить данные в настройках: ошибка формата</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation>Не удалось удалить данные из настроек: ошибка доступа</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation>Не удалось удалить данные из настроек: ошибка формата</translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation>Запись не найдена</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="205"/> + <source>D-Bus is not running</source> + <translation>D-Bus не запущен</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="214"/> + <location filename="../keychain_unix.cpp" line="224"/> + <source>Unknown error</source> + <translation>Неизвестная ошибка</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="316"/> + <source>No keychain service available</source> + <translation>Служба связки ключей недоступна</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="318"/> + <source>Could not open wallet: %1; %2</source> + <translation>Не удалось открыть кошелёк: %1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="363"/> + <source>Access to keychain denied</source> + <translation>Доступ к связке ключей запрещён</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="384"/> + <source>Could not determine data type: %1; %2</source> + <translation>Не удалось определить тип данных: %1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="393"/> + <source>Entry not found</source> + <translation>Запись не найдена</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="402"/> + <source>Unsupported entry type 'Map'</source> + <translation>Неподдерживаемый тип записи 'Map'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="405"/> + <source>Unknown kwallet entry type '%1'</source> + <translation>Неизвестный тип записи kwallet '%1'</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation>Пароль не найден</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="36"/> + <location filename="../keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>Не удалось расшифровать данные</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="445"/> + <source>D-Bus is not running</source> + <translation>D-Bus не запущен</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="455"/> + <location filename="../keychain_unix.cpp" line="482"/> + <source>Unknown error</source> + <translation>Неизвестная ошибка</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="501"/> + <source>Could not open wallet: %1; %2</source> + <translation>Не удалось открыть кошелёк: %1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation>Учётные данные превышают максимальный размер %1</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation>Ключ учётных данных превышает максимальный размер %1</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation>Не удалось сохранить учётные данные: код ошибки win32 %1</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>Шифрование не удалось</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">Пароль не найден</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../keychain_unix.cpp" line="255"/> + <source>Access to keychain denied</source> + <translation>Доступ к связке ключей запрещён</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="257"/> + <source>No keyring daemon</source> + <translation>Нет демона связки ключей</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="259"/> + <source>Already unlocked</source> + <translation>Уже разблокировано</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="261"/> + <source>No such keyring</source> + <translation>Связка ключей не найдена</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="263"/> + <source>Bad arguments</source> + <translation>Неверные аргументы</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="265"/> + <source>I/O error</source> + <translation>Ошибка ввода/вывода</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="267"/> + <source>Cancelled</source> + <translation>Отменено</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="269"/> + <source>Keyring already exists</source> + <translation>Связка ключей уже существует</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="271"/> + <source>No match</source> + <translation>Нет совпадений</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="276"/> + <source>Unknown error</source> + <translation>Неизвестная ошибка</translation> + </message> + <message> + <location filename="../libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation>Запись не найдена</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/qtkeychain_zh.ts b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_zh.ts new file mode 100644 index 0000000000..5d4d64a499 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/qtkeychain_zh.ts @@ -0,0 +1,234 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_TW"> +<context> + <name>QKeychain::DeletePasswordJobPrivate</name> + <message> + <location filename="../keychain_win.cpp" line="104"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="108"/> + <source>Could not decrypt data</source> + <translation type="unfinished">無法解密資料</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="585"/> + <location filename="../keychain_unix.cpp" line="593"/> + <source>Unknown error</source> + <translation type="unfinished">未知的錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="614"/> + <source>Could not open wallet: %1; %2</source> + <translation type="unfinished">無法開啟錢包:%1; %2</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">找不到密碼</translation> + </message> +</context> +<context> + <name>QKeychain::JobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="295"/> + <source>Unknown error</source> + <translation type="unfinished">未知的錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="542"/> + <source>Access to keychain denied</source> + <translation type="unfinished">鑰匙圈存取被拒絕</translation> + </message> +</context> +<context> + <name>QKeychain::PlainTextStore</name> + <message> + <location filename="../plaintextstore.cpp" line="65"/> + <source>Could not store data in settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="67"/> + <source>Could not store data in settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="85"/> + <source>Could not delete data from settings: access error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="87"/> + <source>Could not delete data from settings: format error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../plaintextstore.cpp" line="104"/> + <source>Entry not found</source> + <translation type="unfinished">找不到項目</translation> + </message> +</context> +<context> + <name>QKeychain::ReadPasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="214"/> + <location filename="../keychain_unix.cpp" line="224"/> + <source>Unknown error</source> + <translation>未知的錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="205"/> + <source>D-Bus is not running</source> + <translation>D-Bus 不在執行中</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="316"/> + <source>No keychain service available</source> + <translation>沒有可用的鑰匙圈服務</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="318"/> + <source>Could not open wallet: %1; %2</source> + <translation>無法開啟錢包:%1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="363"/> + <source>Access to keychain denied</source> + <translation>鑰匙圈存取被拒絕</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="384"/> + <source>Could not determine data type: %1; %2</source> + <translation>無法判斷資料型別:%1; %2</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="402"/> + <source>Unsupported entry type 'Map'</source> + <translation>不支援的項目類型 'Map'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="405"/> + <source>Unknown kwallet entry type '%1'</source> + <translation>未知的 kwallet 項目類型 '%1'</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="393"/> + <source>Entry not found</source> + <translation>找不到項目</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="32"/> + <source>Password entry not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="36"/> + <location filename="../keychain_win.cpp" line="139"/> + <source>Could not decrypt data</source> + <translation>無法解密資料</translation> + </message> +</context> +<context> + <name>QKeychain::WritePasswordJobPrivate</name> + <message> + <location filename="../keychain_unix.cpp" line="455"/> + <location filename="../keychain_unix.cpp" line="482"/> + <source>Unknown error</source> + <translation>未知的錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="445"/> + <source>D-Bus is not running</source> + <translation>D-Bus 不在執行中</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="501"/> + <source>Could not open wallet: %1; %2</source> + <translation>無法開啟錢包:%1; %2</translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="78"/> + <source>Credential size exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="87"/> + <source>Credential key exceeds maximum size of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="92"/> + <source>Writing credentials failed: Win32 error code %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../keychain_win.cpp" line="162"/> + <source>Encryption failed</source> + <translation>加密失敗</translation> + </message> + <message> + <source>Password not found</source> + <translation type="obsolete">找不到密碼</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../keychain_unix.cpp" line="255"/> + <source>Access to keychain denied</source> + <translation>鑰匙圈存取被拒絕</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="257"/> + <source>No keyring daemon</source> + <translation>沒有可用的鑰匙圈背景程式</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="259"/> + <source>Already unlocked</source> + <translation>已解鎖</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="261"/> + <source>No such keyring</source> + <translation>鑰匙圈不存在</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="263"/> + <source>Bad arguments</source> + <translation>引數錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="265"/> + <source>I/O error</source> + <translation>I/O 錯誤</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="267"/> + <source>Cancelled</source> + <translation>已取消</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="269"/> + <source>Keyring already exists</source> + <translation>鑰匙圈已存在</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="271"/> + <source>No match</source> + <translation>無相符項目</translation> + </message> + <message> + <location filename="../keychain_unix.cpp" line="276"/> + <source>Unknown error</source> + <translation>未知的錯誤</translation> + </message> + <message> + <location filename="../libsecret.cpp" line="119"/> + <source>Entry not found</source> + <translation type="unfinished">找不到項目</translation> + </message> +</context> +</TS> diff --git a/src/libs/3rdparty/qtkeychain/translations/translations.qrc.in b/src/libs/3rdparty/qtkeychain/translations/translations.qrc.in new file mode 100644 index 0000000000..f49df66150 --- /dev/null +++ b/src/libs/3rdparty/qtkeychain/translations/translations.qrc.in @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/translations"> + @QM_FILE_LIST@ + </qresource> +</RCC> |