qtkeychain-0.10.0/0000755000175000017500000000000013576175767012672 5ustar hefeehefeeqtkeychain-0.10.0/appveyor.yml0000644000175000017500000000145413576175767015266 0ustar hefeehefeeversion: '{build}' build_script: - ps: | $ErrorActionPreference="Stop" Import-Module $env:APPVEYOR_BUILD_FOLDER\appveyorHelp.psm1 Init @("ninja") mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build\$env:APPVEYOR_PROJECT_NAME cd $env:APPVEYOR_BUILD_FOLDER\work\build\$env:APPVEYOR_PROJECT_NAME LogExec cmake -G"Ninja" $env:APPVEYOR_BUILD_FOLDER -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_ROOT" CmakeImageInstall test: off cache: - work\install -> appveyor.yml - C:\ProgramData\chocolatey\bin -> appveyor.yml - C:\ProgramData\chocolatey\lib -> appveyor.yml environment: QT_VER: 5.7 matrix: - COMPILER: msvc2015 - COMPILER: msvc2015_64 - COMPILER: mingw53_32 qtkeychain-0.10.0/org.kde.KWallet.xml0000644000175000017500000002501213576175767016307 0ustar hefeehefee qtkeychain-0.10.0/qt5keychain.pri0000644000175000017500000000464213576175767015641 0ustar hefeehefee# Minimal qmake support. # This file is provided as is without any warranty. # It can break at anytime or be removed without notice. QT5KEYCHAIN_PWD = $$PWD CONFIG += depend_includepath DEFINES += QTKEYCHAIN_NO_EXPORT INCLUDEPATH += \ $$PWD/.. \ $$QT5KEYCHAIN_PWD HEADERS += \ $$QT5KEYCHAIN_PWD/keychain_p.h \ $$QT5KEYCHAIN_PWD/keychain.h SOURCES += \ $$QT5KEYCHAIN_PWD/keychain.cpp unix:!macx:!ios { # Remove the following LIBSECRET_SUPPORT line # to build without libsecret support. DEFINES += LIBSECRET_SUPPORT contains(DEFINES, LIBSECRET_SUPPORT) { packagesExist(libsecret-1) { !build_pass:message("Libsecret support: on") CONFIG += link_pkgconfig PKGCONFIG += libsecret-1 DEFINES += HAVE_LIBSECRET } else { !build_pass:warning("Libsecret not found.") !build_pass:message("Libsecret support: off") } } else { !build_pass:message("Libsecret support: off") } # Generate D-Bus interface: QT += dbus kwallet_interface.files = $$PWD/org.kde.KWallet.xml DBUS_INTERFACES += kwallet_interface HEADERS += \ $$QT5KEYCHAIN_PWD/gnomekeyring_p.h \ $$QT5KEYCHAIN_PWD/plaintextstore_p.h \ $$QT5KEYCHAIN_PWD/libsecret_p.h SOURCES += \ $$QT5KEYCHAIN_PWD/keychain_unix.cpp \ $$QT5KEYCHAIN_PWD/plaintextstore.cpp \ $$QT5KEYCHAIN_PWD/gnomekeyring.cpp \ $$QT5KEYCHAIN_PWD/libsecret.cpp } win32 { # Remove the following USE_CREDENTIAL_STORE line # to use the CryptProtectData Windows API function # instead of the Windows Credential Store. DEFINES += USE_CREDENTIAL_STORE contains(DEFINES, USE_CREDENTIAL_STORE) { !build_pass:message("Windows Credential Store support: on") LIBS += -lAdvapi32 } else { !build_pass:message("Windows Credential Store support: off") LIBS += -lCrypt32 HEADERS += $$QT5KEYCHAIN_PWD/plaintextstore_p.h SOURCES += $$QT5KEYCHAIN_PWD/plaintextstore.cpp } HEADERS += $$QT5KEYCHAIN_PWD/libsecret_p.h SOURCES += \ $$QT5KEYCHAIN_PWD/keychain_win.cpp \ $$QT5KEYCHAIN_PWD/libsecret.cpp } macx:!ios { LIBS += -framework Security -framework Foundation SOURCES += $$QT5KEYCHAIN_PWD/keychain_mac.cpp } ios { LIBS += -framework Security -framework Foundation OBJECTIVE_SOURCES += $$QT5KEYCHAIN_PWD/keychain_ios.mm } qtkeychain-0.10.0/translations/0000755000175000017500000000000013576175767015413 5ustar hefeehefeeqtkeychain-0.10.0/translations/qtkeychain_fr.ts0000644000175000017500000002622613576175767020622 0ustar hefeehefee QKeychain::DeletePasswordJobPrivate Password entry not found Mot de passe non trouvé Could not decrypt data Impossible de déchiffrer les données Unknown error Erreur inconnue Could not open wallet: %1; %2 Impossible d'ouvrir le trousseau : %1; %2 Password not found Mot de passe non trouvé QKeychain::JobPrivate Unknown error Erreur inconnue Access to keychain denied Accès au trousseau refusé QKeychain::PlainTextStore Could not store data in settings: access error Impossible de stocker les paramètres : Erreur d'accès Could not store data in settings: format error Impossible de stocker les paramètres : Erreur de format Could not delete data from settings: access error Impossible de supprimer des paramètres : Erreur d'accès Could not delete data from settings: format error Impossible de supprimer des paramètres : Erreur de format Entry not found Entrée non trouvée QKeychain::ReadPasswordJobPrivate Unknown error Erreur inconnue D-Bus is not running D-Bus non disponible No keychain service available Aucun service de trousseau disponible Could not open wallet: %1; %2 Impossible d'ouvrir le trousseau : %1; %2 Access to keychain denied Accès au trousseau refusé Could not determine data type: %1; %2 Impossible de déterminer le type de données : %1: %2 Unsupported entry type 'Map' Type d'entrée non supporté «Map» Unknown kwallet entry type '%1' Type de trousseau inconnu «%1» Could not read password: %1; %2 Impossible de lire le mot de passe : %1; %2 Password not found Mot de passe non trouvé Entry not found Entrée non trouvée Password entry not found Entrée non trouvée Could not decrypt data Impossible de déchiffrer les données QKeychain::WritePasswordJobPrivate Unknown error Erreur inconnue D-Bus is not running D-Bus non disponible Could not open wallet: %1; %2 Impossible d'ouvrir le trousseau : %1; %2 Access to keychain denied Accès au trousseau refusé Could not delete encrypted data from settings: access error Impossible de supprimer des données chiffrées dans les paramètres : Erreur d'accès Could not delete encrypted data from settings: format error Impossible de supprimer des données chiffrées dans les paramètres : Erreur de format Encryption failed Le chiffrement a échoué Could not store encrypted data in settings: access error Impossible de stocker des données chiffrées dans les paramètres : Erreur d'accès Could not store encrypted data in settings: format error Impossible de stocker des données chiffrées dans les paramètres : Erreur de format Password not found Mot de passe non trouvé QObject Access to keychain denied Accès au trousseau refusé No keyring daemon Aucun démon de trousseau Already unlocked Déjà déverrouillé No such keyring Trousseau non trouvé Bad arguments Mauvais arguments I/O error Erreur d'E/S Cancelled Annulé Keyring already exists Trousseau déjà existant No match Aucune correspondance Unknown error Erreur inconnue OS X Keychain error (OSStatus %1) %1 (OSStatus %2) Entry not found Entrée non trouvée error 0x%1: %2 Erreur 0x%1 : %2 qtkeychain-0.10.0/translations/qtkeychain_de.ts0000644000175000017500000001622013576175767020574 0ustar hefeehefee QKeychain::ReadPasswordJobPrivate Unknown error Unbekannter Fehler D-Bus is not running No keychain service available Kein Schlüsselbund-Dienst verfügbar Could not open wallet: %1; %2 Konnte Brieftasche nicht öffnen: %1; %2 Access to keychain denied Zugriff auf Schlüsselbund verweigert Could not determine data type: %1; %2 Datentyp kann nicht ermittelt werden: %1: %2 Unsupported entry type 'Map' Unknown kwallet entry type '%1' Could not read password: %1; %2 Passwort konnte nicht ausgelesen werden: %1; %2 Password not found Passwort nicht gefunden Entry not found Eintrag nicht gefunden Could not decrypt data Kann Daten nicht entschlüsseln QKeychain::WritePasswordJobPrivate Unknown error Unbekannter Fehler D-Bus is not running Could not open wallet: %1; %2 Konnte Brieftasche nicht öffnen: %1; %2 Access to keychain denied Zugriff auf Schlüsselbund verweigert Could not delete encrypted data from settings: access error Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Zugriffsfehler Could not delete encrypted data from settings: format error Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Formatfehler Encryption failed Verschlüsselung fehlgeschlagen Could not store encrypted data in settings: access error Kann verschlüsselte Daten nicht in den Einstellungen speichern: Zugriffsfehler Could not store encrypted data in settings: format error Kann verschlüsselte Daten nicht in den Einstellungen speichern: Formatfehler QObject Access to keychain denied Zugriff auf Schlüsselbund verweigert No keyring daemon Kein Schlüsselbund-Dienst Already unlocked Bereits entsperrt No such keyring Kein solcher Schlüsselbund Bad arguments Ungültige Argumente I/O error Ein-/Ausgabe-Fehler Cancelled Abgebrochen Keyring already exists Schlüsselbund existiert bereits No match Kein Treffer Unknown error Unbekannter Fehler %1 (OSStatus %2) qtkeychain-0.10.0/translations/qtkeychain_zh.ts0000644000175000017500000001561413576175767020633 0ustar hefeehefee QKeychain::ReadPasswordJobPrivate Unknown error 未知的錯誤 D-Bus is not running D-Bus 不在執行中 No keychain service available 沒有可用的鑰匙圈服務 Could not open wallet: %1; %2 無法開啟錢包:%1; %2 Access to keychain denied 鑰匙圈存取被拒絕 Could not determine data type: %1; %2 無法判斷資料型別:%1; %2 Unsupported entry type 'Map' 不支援的項目類型 'Map' Unknown kwallet entry type '%1' 未知的 kwallet 項目類型 '%1' Could not read password: %1; %2 無法讀取密碼:%1; %2 Password not found 找不到密碼 Entry not found 找不到項目 Could not decrypt data 無法解密資料 QKeychain::WritePasswordJobPrivate Unknown error 未知的錯誤 D-Bus is not running D-Bus 不在執行中 Could not open wallet: %1; %2 無法開啟錢包:%1; %2 Access to keychain denied 鑰匙圈存取被拒絕 Could not delete encrypted data from settings: access error 無法從設定刪除加密資料:存取錯誤 Could not delete encrypted data from settings: format error 無法從設定刪除加密資料:格式錯誤 Encryption failed 加密失敗 Could not store encrypted data in settings: access error 無法將加密資料儲存至設定:存取錯誤 Could not store encrypted data in settings: format error 無法將加密資料儲存至設定:格式錯誤 QObject Access to keychain denied 鑰匙圈存取被拒絕 No keyring daemon 沒有可用的鑰匙圈背景程式 Already unlocked 已解鎖 No such keyring 鑰匙圈不存在 Bad arguments 引數錯誤 I/O error I/O 錯誤 Cancelled 已取消 Keyring already exists 鑰匙圈已存在 No match 無相符項目 Unknown error 未知的錯誤 %1 (OSStatus %2) %1 (OSStatus %2) qtkeychain-0.10.0/translations/qtkeychain_ro.ts0000644000175000017500000001630213576175767020625 0ustar hefeehefee QKeychain::ReadPasswordJobPrivate Unknown error Eroare necunoscută D-Bus is not running D-Bus nu rulează No keychain service available Nu există niciun serviciu de chei disponibil Kein Schlüsselbund-Dienst verfügbar Could not open wallet: %1; %2 Nu se poate deschide portofelul: %1; %2 Access to keychain denied Acces interzis la serviciul de chei Could not determine data type: %1; %2 Nu se poate stabili tipul de date: %1: %2 Unsupported entry type 'Map' Tip de înregistrare nesuportat 'Map' Unknown kwallet entry type '%1' Tip de înregistrare kwallet necunoscut '%1' Could not read password: %1; %2 Nu se poate citi parola: %1; %2 Password not found Parola nu a fost găsită Entry not found Înregistrarea nu a fost găsită Could not decrypt data Nu se poate decripta data QKeychain::WritePasswordJobPrivate Unknown error Eroare necunoscută D-Bus is not running D-Bus nu rulează Could not open wallet: %1; %2 Nu se poate deschide portofelul: %1; %2 Access to keychain denied Acces interzis la serviciul de chei Could not delete encrypted data from settings: access error Nu se pot șterge datele criptate din setări: eroare de acces Could not delete encrypted data from settings: format error Nu se pot șterge datele criptate din setări: eroare de format Encryption failed Criptarea a eșuat Could not store encrypted data in settings: access error Nu se pot stoca datele criptate în setări: eroare de acces Could not store encrypted data in settings: format error Nu se pot stoca datele criptate în setări: eroare de format QObject Access to keychain denied Acces interzis la serviciul de chei No keyring daemon Niciun demon pentru inelul de chei Already unlocked Deja deblocat No such keyring Nu există astfel de inel de chei Bad arguments Argumente greșite I/O error Eroare de I/E Cancelled Anulat Keyring already exists Inelul de chei deja există No match Nicio potrivire Unknown error Eroare necunoscută %1 (OSStatus %2) %1 (OSStatus %2) qtkeychain-0.10.0/ReadMe.txt0000644000175000017500000000212113576175767014564 0ustar hefeehefeeQtKeychain ========== QtKeychain is a Qt API to store passwords and other secret data securely. How the data is stored depends on the platform: * **Mac OS X:** Passwords are stored in the OS X Keychain. * **Linux/Unix:** If running, GNOME Keyring is used, otherwise qtkeychain tries to use KWallet (via D-Bus), if available. * **Windows:** By default, the Windows Credential Store is used (requires Windows 7 or newer). Pass -DUSE_CREDENTIAL_STORE=OFF to cmake use 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. In unsupported environments QtKeychain will report an error. It will not store any data unencrypted unless explicitly requested (setInsecureFallback( true )). **License:** QtKeychain is available under the [Modified BSD License](http://www.gnu.org/licenses/license-list.html#ModifiedBSD). See the file COPYING for details. qtkeychain-0.10.0/ChangeLog0000644000175000017500000000561213576175767014450 0ustar hefeehefeeChangeLog ========= version 0.10.0 (release 2019-12-17) * Detect XFCE desktop correctly. (Sandro Knauß ) * Windows Use CRED_PERSIST_ENTERPRISE (Olivier Goffart ) * Windows: Improve CredWrite() error handling (Christian Kamm ) * Fix build with Qt 5.12.x (Sergey Ilinykh ) * Fix Qt 4 build (Robert-André Mauchin ) * Translation: Mandarin (Taiwan) (Poren Chiang ) * Translation: French (François Revol ) version 0.9.1 (release 2018-08-20) * Windows Credential Store: Use CRED_PERSIST_ENTERPRISE (Olivier Goffart ) * Secret: Don't match the schema name #114 (Christian Kamm ) * Fix qmake build on Windows (Alexander Gorishnyak ) version 0.9.0 (release 2018-07-13) * Fall back on libsecret if kwallet is not available (Christian Kamm ) * Only require QtLinguist if building translations (Victor Kropp ) * Fix building on Windows without credential store (Dmitry Ivanov ) * Fix Qt 4 build (Sandro Knauß ) * Make build of test application optional (Boris Pek ) version 0.8.0 (release 2017-04-19) * Buildsystem improvements (Kristofer Tingdahl , Hannah von Reth , Giuseppe D'Angelo ) * Enable C++11 support for Qt >= 5.7 (Dmitry Ivanov ) * Doxygen documentation ( Elvis Angelaccio ) * Libsecret support (Armin Novak ) * iOS support (Mathias Hasselmann ) 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 ) * Improved desktop environment detection at runtime (Daniel Molkentin ) version 0.3.0 (release 2014-03-13) * Gnome Keyring supported added (Francois Ferrand ) * Improved Qt 5 support * KWallet: Distinguish empty passwords from non-existing entries * KWallet: Do not use hardcoded wallet name * German translation (Daniel Molkentin ) * Romanian translation (Arthur Țițeică ) version 0.2.0: no official release version 0.1.0 (release 2013-01-16) * Initial release qtkeychain-0.10.0/gnomekeyring_p.h0000644000175000017500000000664513576175767016073 0ustar hefeehefee#ifndef QTKEYCHAIN_GNOME_P_H #define QTKEYCHAIN_GNOME_P_H #include class GnomeKeyring : private QLibrary { Q_OBJECT public: enum Result { RESULT_OK, RESULT_DENIED, RESULT_NO_KEYRING_DAEMON, RESULT_ALREADY_UNLOCKED, RESULT_NO_SUCH_KEYRING, RESULT_BAD_ARGUMENTS, RESULT_IO_ERROR, RESULT_CANCELLED, RESULT_KEYRING_ALREADY_EXISTS, RESULT_NO_MATCH }; enum ItemType { ITEM_GENERIC_SECRET = 0, ITEM_NETWORK_PASSWORD, ITEM_NOTE, ITEM_CHAINED_KEYRING_PASSWORD, ITEM_ENCRYPTION_KEY_PASSWORD, ITEM_PK_STORAGE = 0x100 }; enum AttributeType { ATTRIBUTE_TYPE_STRING, ATTRIBUTE_TYPE_UINT32 }; typedef char gchar; typedef void* gpointer; typedef bool gboolean; typedef struct { ItemType item_type; struct { const gchar* name; AttributeType type; } attributes[32]; } PasswordSchema; typedef void ( *OperationGetStringCallback )( Result result, bool binary, const char* string, gpointer data ); typedef void ( *OperationDoneCallback )( Result result, gpointer data ); typedef void ( *GDestroyNotify )( gpointer data ); static const char* GNOME_KEYRING_DEFAULT; static bool isAvailable(); static gpointer store_network_password( const gchar* keyring, const gchar* display_name, const gchar* user, const gchar* server, const gchar* type, const gchar* password, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); static gpointer find_network_password( const gchar* user, const gchar* server, const gchar* type, OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ); static gpointer delete_network_password( const gchar* user, const gchar* server, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); private: GnomeKeyring(); static GnomeKeyring& instance(); const PasswordSchema* NETWORK_PASSWORD; typedef gboolean ( is_available_fn )( void ); typedef gpointer ( store_password_fn )( const PasswordSchema* schema, const gchar* keyring, const gchar* display_name, const gchar* password, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, ... ); typedef gpointer ( find_password_fn )( const PasswordSchema* schema, OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data, ... ); typedef gpointer ( delete_password_fn )( const PasswordSchema* schema, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, ... ); is_available_fn* is_available; find_password_fn* find_password; store_password_fn* store_password; delete_password_fn* delete_password; }; #endif qtkeychain-0.10.0/libsecret_p.h0000644000175000017500000000137613576175767015345 0ustar hefeehefee#ifndef QTKEYCHAIN_LIBSECRET_P_H #define QTKEYCHAIN_LIBSECRET_P_H #include #include "keychain_p.h" class LibSecretKeyring : public QLibrary { public: static bool isAvailable(); static bool findPassword(const QString& user, const QString& server, QKeychain::JobPrivate* self); static bool writePassword(const QString& display_name, const QString& user, const QString& server, const QKeychain::JobPrivate::Mode type, const QByteArray& password, QKeychain::JobPrivate* self); static bool deletePassword(const QString &key, const QString &service, QKeychain::JobPrivate* self); private: LibSecretKeyring(); static LibSecretKeyring &instance(); }; #endif qtkeychain-0.10.0/keychain_p.h0000644000175000017500000001067613576175767015167 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #ifndef KEYCHAIN_P_H #define KEYCHAIN_P_H #include #include #include #include #include #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) #include #include "kwallet_interface.h" #else class QDBusPendingCallWatcher; #endif #include "keychain.h" namespace QKeychain { class JobExecutor; class JobPrivate : public QObject { Q_OBJECT public: enum Mode { Text, Binary }; virtual void scheduledStart() = 0; static QString modeToString(Mode m); static Mode stringToMode(const QString& s); Job* const q; Mode mode; QByteArray data; #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) org::kde::KWallet* iface; int walletHandle; static void gnomeKeyring_readCb( int result, const char* string, JobPrivate* data ); static void gnomeKeyring_writeCb( int result, JobPrivate* self ); virtual void fallbackOnError(const QDBusError& err) = 0; protected Q_SLOTS: void kwalletWalletFound( QDBusPendingCallWatcher* watcher ); virtual void kwalletFinished( QDBusPendingCallWatcher* watcher ); virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ); #else void kwalletWalletFound( QDBusPendingCallWatcher* ) {} virtual void kwalletFinished( QDBusPendingCallWatcher* ) {} virtual void kwalletOpenFinished( QDBusPendingCallWatcher* ) {} #endif protected: JobPrivate( const QString& service_, Job *q ); protected: QKeychain::Error error; QString errorString; QString service; bool autoDelete; bool insecureFallback; QPointer settings; QString key; friend class Job; friend class JobExecutor; friend class ReadPasswordJob; friend class WritePasswordJob; friend class PlainTextStore; }; class ReadPasswordJobPrivate : public JobPrivate { Q_OBJECT public: explicit ReadPasswordJobPrivate( const QString &service_, ReadPasswordJob* qq ); void scheduledStart(); #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) void fallbackOnError(const QDBusError& err); private Q_SLOTS: void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ); void kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ); void kwalletFinished( QDBusPendingCallWatcher* watcher ); #else //moc's too dumb to respect above macros, so just define empty slot implementations private Q_SLOTS: void kwalletOpenFinished( QDBusPendingCallWatcher* ) {} void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {} void kwalletFinished( QDBusPendingCallWatcher* ) {} #endif friend class ReadPasswordJob; }; class WritePasswordJobPrivate : public JobPrivate { Q_OBJECT public: explicit WritePasswordJobPrivate( const QString &service_, WritePasswordJob* qq ); void scheduledStart(); #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) void fallbackOnError(const QDBusError& err); #endif friend class WritePasswordJob; }; class DeletePasswordJobPrivate : public JobPrivate { Q_OBJECT public: explicit DeletePasswordJobPrivate( const QString &service_, DeletePasswordJob* qq ); void scheduledStart(); #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) void fallbackOnError(const QDBusError& err); #endif protected: void doStart(); friend class DeletePasswordJob; }; class JobExecutor : public QObject { Q_OBJECT public: static JobExecutor* instance(); void enqueue( Job* job ); private: explicit JobExecutor(); void startNextIfNoneRunning(); private Q_SLOTS: void jobFinished( QKeychain::Job* ); void jobDestroyed( QObject* object ); private: static JobExecutor* s_instance; QQueue > m_queue; bool m_jobRunning; }; } #endif // KEYCHAIN_P_H qtkeychain-0.10.0/CMakeLists.txt0000644000175000017500000002214713576175767015440 0ustar hefeehefeecmake_minimum_required(VERSION 2.8.11) project(qtkeychain) include(FindPkgConfig) ### set(QTKEYCHAIN_VERSION 0.10.0) set(QTKEYCHAIN_SOVERSION 1) ### set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules") include(GNUInstallDirs) include(GenerateExportHeader) include(ECMPackageConfigHelpers) include(ECMSetupVersion) include(ECMGeneratePriFile) option(BUILD_WITH_QT4 "Build qtkeychain with Qt4 no matter if Qt5 was found" OFF) option(BUILD_TEST_APPLICATION "Build test application" ON) option(BUILD_TRANSLATIONS "Build translations" ON) option(QTKEYCHAIN_STATIC "Build static library" OFF) if(CMAKE_SYSTEM_NAME STREQUAL Android) set(ANDROID 1) endif() if (WIN32) option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) if (USE_CREDENTIAL_STORE) add_definitions(-DUSE_CREDENTIAL_STORE=1) endif() endif() if( NOT BUILD_WITH_QT4 ) # try Qt5 first, and prefer that if found find_package(Qt5Core QUIET) endif() if (Qt5Core_FOUND AND NOT BUILD_WITH_QT4) set(QTKEYCHAIN_VERSION_INFIX 5) if(UNIX AND NOT APPLE AND NOT ANDROID) find_package(Qt5DBus REQUIRED) include_directories(${Qt5DBus_INCLUDE_DIRS}) set(QTDBUS_LIBRARIES ${Qt5DBus_LIBRARIES}) macro(qt_add_dbus_interface) qt5_add_dbus_interface(${ARGN}) endmacro() endif() if(BUILD_TRANSLATIONS) find_package(Qt5LinguistTools REQUIRED) macro(qt_add_translation) qt5_add_translation(${ARGN}) endmacro(qt_add_translation) macro(qt_create_translation) qt5_create_translation(${ARGN}) endmacro(qt_create_translation) endif() macro(qt_wrap_cpp) qt5_wrap_cpp(${ARGN}) endmacro() set(QTCORE_LIBRARIES ${Qt5Core_LIBRARIES}) include_directories(${Qt5Core_INCLUDE_DIRS}) if (NOT Qt5Core_VERSION VERSION_LESS "5.7.0") if (CMAKE_COMPILER_IS_GNUCXX) if ((NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.1.0")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") message(FATAL_ERROR "Can't build QtKeychain using g++-${CMAKE_CXX_COMPILER_VERSION} and Qt ${Qt5Core_VERSION}: compiler supporting C++11 is required") endif() elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 3.3) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() message(FATAL_ERROR "Can't build QtKeychain using clang++-${CMAKE_CXX_COMPILER_VERSION} and Qt ${Qt5Core_VERSION}: compiler supporting C++11 is required") endif() elseif ((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND (MSVC_VERSION LESS 1700)) message(FATAL_ERROR "Can't build QtKeychain using VC++-${MSVC_VERSION} and Qt ${Qt5Core_VERSION}: compiler supporting C++11 is required") endif() endif() else() set(QTKEYCHAIN_VERSION_INFIX "") if(UNIX AND NOT APPLE) find_package(Qt4 COMPONENTS QtCore QtDBus REQUIRED) set(QTDBUS_LIBRARIES ${QT_QTDBUS_LIBRARY}) macro(qt_add_dbus_interface) qt4_add_dbus_interface(${ARGN}) endmacro() else() find_package(Qt4 COMPONENTS QtCore REQUIRED) endif() include_directories(${QT_INCLUDES}) set(QTCORE_LIBRARIES ${QT_QTCORE_LIBRARY}) macro(qt_add_translation) qt4_add_translation(${ARGN}) endmacro(qt_add_translation) macro(qt_create_translation) qt4_create_translation(${ARGN}) endmacro(qt_create_translation) macro(qt_wrap_cpp) qt4_wrap_cpp(${ARGN}) endmacro() endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) list(APPEND qtkeychain_LIBRARIES ${QTCORE_LIBRARIES}) set(qtkeychain_SOURCES keychain.cpp qkeychain_export.h keychain.h ) add_definitions( -Wall ) 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) if(IOS) list(APPEND qtkeychain_SOURCES keychain_ios.cpp) else() list(APPEND qtkeychain_SOURCES keychain_mac.cpp) endif() find_library(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) list(APPEND qtkeychain_LIBRARIES ${COREFOUNDATION_LIBRARY}) find_library(SECURITY_LIBRARY Security REQUIRED) list(APPEND qtkeychain_LIBRARIES ${SECURITY_LIBRARY}) endif() if(UNIX AND NOT APPLE AND NOT ANDROID) option(LIBSECRET_SUPPORT "Build with libsecret support" ON) if(LIBSECRET_SUPPORT) pkg_check_modules(LIBSECRET libsecret-1) if (LIBSECRET_FOUND) add_definitions(-DHAVE_LIBSECRET=1) endif() INCLUDE_DIRECTORIES(${LIBSECRET_INCLUDE_DIRS}) list(APPEND qtkeychain_LIBRARIES ${LIBSECRET_LIBRARIES}) endif() list(APPEND qtkeychain_SOURCES keychain_unix.cpp gnomekeyring.cpp libsecret.cpp plaintextstore.cpp) qt_add_dbus_interface(qtkeychain_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface) list(APPEND qtkeychain_LIBRARIES ${QTDBUS_LIBRARIES} ) endif() QT_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h gnomekeyring_p.h) set(qtkeychain_TR_FILES translations/qtkeychain_de.ts translations/qtkeychain_ro.ts ) file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui) if ( BUILD_TRANSLATIONS ) qt_create_translation(qtkeychain_MESSAGES ${qtkeychain_TR_SOURCES} ${qtkeychain_TR_FILES}) qt_add_translation(qtkeychain_QM_FILES ${qtkeychain_TR_FILES}) add_custom_target(messages DEPENDS ${qtkeychain_MESSAGES}) add_custom_target(translations DEPENDS ${qtkeychain_QM_FILES}) if(NOT QT_TRANSLATIONS_DIR) # If this directory is missing, we are in a Qt5 environment. # Extract the qmake executable location get_target_property(QT5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) # Ask Qt5 where to put the translations execute_process( COMMAND ${QT5_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS OUTPUT_VARIABLE qt_translations_dir OUTPUT_STRIP_TRAILING_WHITESPACE ) # make sure we have / and not \ as qmake gives on windows file( TO_CMAKE_PATH "${qt_translations_dir}" qt_translations_dir) set( QT_TRANSLATIONS_DIR ${qt_translations_dir} CACHE PATH "The location of the Qt translations" FORCE) endif() install(FILES ${qtkeychain_QM_FILES} DESTINATION ${QT_TRANSLATIONS_DIR}) endif( BUILD_TRANSLATIONS ) set(QTKEYCHAIN_TARGET_NAME qt${QTKEYCHAIN_VERSION_INFIX}keychain) if(NOT QTKEYCHAIN_STATIC) add_library(${QTKEYCHAIN_TARGET_NAME} SHARED ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) else() add_library(${QTKEYCHAIN_TARGET_NAME} STATIC ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) endif() target_link_libraries(${QTKEYCHAIN_TARGET_NAME} PUBLIC ${qtkeychain_LIBRARIES}) target_include_directories(${QTKEYCHAIN_TARGET_NAME} PUBLIC $) generate_export_header(${QTKEYCHAIN_TARGET_NAME} EXPORT_FILE_NAME qkeychain_export.h EXPORT_MACRO_NAME QKEYCHAIN_EXPORT ) set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES VERSION ${QTKEYCHAIN_VERSION} SOVERSION ${QTKEYCHAIN_SOVERSION} MACOSX_RPATH 1 INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" INSTALL_RPATH_USE_LINK_PATH TRUE ) install(FILES keychain.h ${CMAKE_CURRENT_BINARY_DIR}/qkeychain_export.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qt${QTKEYCHAIN_VERSION_INFIX}keychain/ ) install(TARGETS ${QTKEYCHAIN_TARGET_NAME} EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) if(BUILD_TEST_APPLICATION) add_executable( testclient testclient.cpp ) target_link_libraries( testclient ${QTKEYCHAIN_TARGET_NAME}) endif() ### ### CMake config file ### ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/QtKeychainConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake" INSTALL_DESTINATION Qt${QTKEYCHAIN_VERSION_INFIX}Keychain) ecm_setup_version("${QTKEYCHAIN_VERSION}" VARIABLE_PREFIX SNORE PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" SOVERSION ${QTKEYCHAIN_VERSION}) if(UNIX AND NOT APPLE AND NOT ANDROID) set(PRI_EXTRA_DEPS "dbus") endif() ecm_generate_pri_file(BASE_NAME Qt${QTKEYCHAIN_VERSION_INFIX}Keychain LIB_NAME ${QTKEYCHAIN_TARGET_NAME} DEPS "core ${PRI_EXTRA_DEPS}" INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} FILENAME_VAR pri_filename) install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) install(EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain" ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain ) qtkeychain-0.10.0/keychain_unix.cpp0000644000175000017500000005303113576175767016236 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" #include "gnomekeyring_p.h" #include "libsecret_p.h" #include "plaintextstore_p.h" #include using namespace QKeychain; enum KeyringBackend { Backend_LibSecretKeyring, Backend_GnomeKeyring, Backend_Kwallet4, Backend_Kwallet5 }; enum DesktopEnvironment { DesktopEnv_Gnome, DesktopEnv_Kde4, DesktopEnv_Plasma5, DesktopEnv_Unity, DesktopEnv_Xfce, DesktopEnv_Other }; // the following detection algorithm is derived from chromium, // licensed under BSD, see base/nix/xdg_util.cc static DesktopEnvironment getKdeVersion() { QByteArray value = qgetenv("KDE_SESSION_VERSION"); if ( value == "5" ) { return DesktopEnv_Plasma5; } else if (value == "4" ) { return DesktopEnv_Kde4; } else { // most likely KDE3 return DesktopEnv_Other; } } static DesktopEnvironment detectDesktopEnvironment() { QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); if ( xdgCurrentDesktop == "GNOME" ) { return DesktopEnv_Gnome; } else if ( xdgCurrentDesktop == "Unity" ) { return DesktopEnv_Unity; } else if ( xdgCurrentDesktop == "KDE" ) { return getKdeVersion(); } else if ( xdgCurrentDesktop == "XFCE" ) { return DesktopEnv_Xfce; } QByteArray desktopSession = qgetenv("DESKTOP_SESSION"); if ( desktopSession == "gnome" ) { return DesktopEnv_Gnome; } else if ( desktopSession == "kde" ) { return getKdeVersion(); } else if ( desktopSession == "kde4" ) { return DesktopEnv_Kde4; } else if ( desktopSession.contains("xfce") || desktopSession == "xubuntu" ) { return DesktopEnv_Xfce; } if ( !qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ) { return DesktopEnv_Gnome; } else if ( !qgetenv("KDE_FULL_SESSION").isEmpty() ) { return getKdeVersion(); } return DesktopEnv_Other; } static bool isKwallet5Available() { if (!QDBusConnection::sessionBus().isConnected()) return false; org::kde::KWallet iface( QLatin1String("org.kde.kwalletd5"), QLatin1String("/modules/kwalletd5"), QDBusConnection::sessionBus()); // At this point iface.isValid() can return false even though the // interface is activatable by making a call. Hence we check whether // a wallet can be opened. iface.setTimeout(500); QDBusMessage reply = iface.call(QLatin1String("networkWallet")); return reply.type() == QDBusMessage::ReplyMessage; } static KeyringBackend detectKeyringBackend() { /* The secret service dbus api, accessible through libsecret, is supposed * to unify password services. * * Unfortunately at the time of Kubuntu 18.04 the secret service backend * in KDE is gnome-keyring-daemon - using it has several complications: * - the default collection isn't opened on session start, so users need * to manually unlock it when the first application uses it * - it's separate from the kwallet5 keyring, so switching to it means the * existing keyring data can't be accessed anymore * * Thus we still prefer kwallet backends on KDE even if libsecret is * available. */ switch (detectDesktopEnvironment()) { case DesktopEnv_Kde4: return Backend_Kwallet4; case DesktopEnv_Plasma5: if (isKwallet5Available()) { return Backend_Kwallet5; } if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } if (GnomeKeyring::isAvailable()) { return Backend_GnomeKeyring; } // During startup the keychain backend might just not have started yet return Backend_Kwallet5; case DesktopEnv_Gnome: case DesktopEnv_Unity: case DesktopEnv_Xfce: case DesktopEnv_Other: default: if (LibSecretKeyring::isAvailable()) { return Backend_LibSecretKeyring; } if (GnomeKeyring::isAvailable()) { return Backend_GnomeKeyring; } if (isKwallet5Available()) { return Backend_Kwallet5; } // During startup the keychain backend might just not have started yet // // This doesn't need to be libsecret because LibSecretKeyring::isAvailable() // only fails if the libsecret shared library couldn't be loaded. In contrast // to that GnomeKeyring::isAvailable() can return false if the shared library // *was* loaded but its libgnome_keyring::is_available() returned false. // // In the future there should be a difference between "API available" and // "keychain available". return Backend_GnomeKeyring; } } static KeyringBackend getKeyringBackend() { static KeyringBackend backend = detectKeyringBackend(); return backend; } static void kwalletReadPasswordScheduledStartImpl(const char * service, const char * path, ReadPasswordJobPrivate * priv) { if ( QDBusConnection::sessionBus().isConnected() ) { priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv ); const QDBusPendingReply reply = priv->iface->networkWallet(); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv ); priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) ); } else { // D-Bus is not reachable so none can tell us something about KWalletd QDBusError err( QDBusError::NoServer, ReadPasswordJobPrivate::tr("D-Bus is not running") ); priv->fallbackOnError( err ); } } void ReadPasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_LibSecretKeyring: { if ( !LibSecretKeyring::findPassword(key, q->service(), this) ) { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; case Backend_GnomeKeyring: this->mode = JobPrivate::Text; if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(), "plaintext", reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), this, 0 ) ) q->emitFinishedWithError( OtherError, tr("Unknown error") ); break; case Backend_Kwallet4: kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd", "/modules/kwalletd", this); break; case Backend_Kwallet5: kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd5", "/modules/kwalletd5", this); break; } } void JobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher) { watcher->deleteLater(); const QDBusPendingReply reply = *watcher; const QDBusPendingReply pendingReply = iface->open( reply.value(), 0, q->service() ); QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this ); connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) ); } static QPair mapGnomeKeyringError( int result ) { Q_ASSERT( result != GnomeKeyring::RESULT_OK ); switch ( result ) { case GnomeKeyring::RESULT_DENIED: return qMakePair( AccessDenied, QObject::tr("Access to keychain denied") ); case GnomeKeyring::RESULT_NO_KEYRING_DAEMON: return qMakePair( NoBackendAvailable, QObject::tr("No keyring daemon") ); case GnomeKeyring::RESULT_ALREADY_UNLOCKED: return qMakePair( OtherError, QObject::tr("Already unlocked") ); case GnomeKeyring::RESULT_NO_SUCH_KEYRING: return qMakePair( OtherError, QObject::tr("No such keyring") ); case GnomeKeyring::RESULT_BAD_ARGUMENTS: return qMakePair( OtherError, QObject::tr("Bad arguments") ); case GnomeKeyring::RESULT_IO_ERROR: return qMakePair( OtherError, QObject::tr("I/O error") ); case GnomeKeyring::RESULT_CANCELLED: return qMakePair( OtherError, QObject::tr("Cancelled") ); case GnomeKeyring::RESULT_KEYRING_ALREADY_EXISTS: return qMakePair( OtherError, QObject::tr("Keyring already exists") ); case GnomeKeyring::RESULT_NO_MATCH: return qMakePair( EntryNotFound, QObject::tr("No match") ); default: break; } return qMakePair( OtherError, QObject::tr("Unknown error") ); } void JobPrivate::gnomeKeyring_readCb( int result, const char* string, JobPrivate* self ) { if ( result == GnomeKeyring::RESULT_OK ) { if (self->mode == JobPrivate::Text) self->data = QByteArray(string); else self->data = QByteArray::fromBase64(string); self->q->emitFinished(); } else if (self->mode == JobPrivate::Text) { self->mode = JobPrivate::Binary; if ( !GnomeKeyring::find_network_password( self->key.toUtf8().constData(), self->q->service().toUtf8().constData(), "base64", reinterpret_cast( &JobPrivate::gnomeKeyring_readCb ), self, 0 ) ) self->q->emitFinishedWithError( OtherError, tr("Unknown error") ); } else { const QPair errorResult = mapGnomeKeyringError( result ); self->q->emitFinishedWithError( errorResult.first, errorResult.second ); } } void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err ) { PlainTextStore plainTextStore( q->service(), q->settings() ); if ( q->insecureFallback() && plainTextStore.contains( key ) ) { mode = plainTextStore.readMode( key ); data = plainTextStore.readData( key ); if ( plainTextStore.error() != NoError ) q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); else q->emitFinished(); } else { if ( err.type() == QDBusError::ServiceUnknown ) //KWalletd not running q->emitFinishedWithError( NoBackendAvailable, tr("No keychain service available") ); else q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); } } void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { watcher->deleteLater(); const QDBusPendingReply reply = *watcher; if ( reply.isError() ) { fallbackOnError( reply.error() ); return; } PlainTextStore plainTextStore( q->service(), q->settings() ); if ( plainTextStore.contains( key ) ) { // We previously stored data in the insecure QSettings, but now have KWallet available. // Do the migration data = plainTextStore.readData( key ); const WritePasswordJobPrivate::Mode mode = plainTextStore.readMode( key ); plainTextStore.remove( key ); q->emitFinished(); WritePasswordJob* j = new WritePasswordJob( q->service(), 0 ); j->setSettings( q->settings() ); j->setKey( key ); j->setAutoDelete( true ); if ( mode == WritePasswordJobPrivate::Binary ) j->setBinaryData( data ); else if ( mode == WritePasswordJobPrivate::Text ) j->setTextData( QString::fromUtf8( data ) ); else Q_ASSERT( false ); j->start(); return; } walletHandle = reply.value(); if ( walletHandle < 0 ) { q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") ); return; } const QDBusPendingReply nextReply = iface->entryType( walletHandle, q->service(), key, q->service() ); QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletEntryTypeFinished(QDBusPendingCallWatcher*)) ); } //Must be in sync with KWallet::EntryType (kwallet.h) enum KWalletEntryType { Unknown=0, Password, Stream, Map }; void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) { watcher->deleteLater(); if ( watcher->isError() ) { const QDBusError err = watcher->error(); q->emitFinishedWithError( OtherError, tr("Could not determine data type: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); return; } const QDBusPendingReply reply = *watcher; const int value = reply.value(); switch ( value ) { case Unknown: q->emitFinishedWithError( EntryNotFound, tr("Entry not found") ); return; case Password: mode = Text; break; case Stream: mode = Binary; break; case Map: q->emitFinishedWithError( EntryNotFound, tr("Unsupported entry type 'Map'") ); return; default: q->emitFinishedWithError( OtherError, tr("Unknown kwallet entry type '%1'").arg( value ) ); return; } const QDBusPendingCall nextReply = (mode == Text) ? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) ) : QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) ); QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletFinished(QDBusPendingCallWatcher*)) ); } void ReadPasswordJobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) { if ( !watcher->isError() ) { if ( mode == Binary ) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { data = reply.value(); } } else { QDBusPendingReply reply = *watcher; if (reply.isValid()) { data = reply.value().toUtf8(); } } } JobPrivate::kwalletFinished(watcher); } static void kwalletWritePasswordScheduledStart( const char * service, const char * path, JobPrivate * priv ) { if ( QDBusConnection::sessionBus().isConnected() ) { priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv ); const QDBusPendingReply reply = priv->iface->networkWallet(); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv ); priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) ); } else { // D-Bus is not reachable so none can tell us something about KWalletd QDBusError err( QDBusError::NoServer, WritePasswordJobPrivate::tr("D-Bus is not running") ); priv->fallbackOnError( err ); } } void WritePasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_LibSecretKeyring: { if ( !LibSecretKeyring::writePassword(service, key, service, mode, data, this) ) { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; case Backend_GnomeKeyring: { QString type; QByteArray password; switch(mode) { case JobPrivate::Text: type = QLatin1String("plaintext"); password = data; break; default: type = QLatin1String("base64"); password = data.toBase64(); break; } QByteArray service = q->service().toUtf8(); if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, service.constData(), key.toUtf8().constData(), service.constData(), type.toUtf8().constData(), password.constData(), reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), this, 0 ) ) q->emitFinishedWithError( OtherError, tr("Unknown error") ); } break; case Backend_Kwallet4: kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this); break; case Backend_Kwallet5: kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this); break; } } void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err) { if ( !q->insecureFallback() ) { q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) ); return; } PlainTextStore plainTextStore( q->service(), q->settings() ); plainTextStore.write( key, data, mode ); if ( plainTextStore.error() != NoError ) q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); else q->emitFinished(); } void JobPrivate::gnomeKeyring_writeCb(int result, JobPrivate* self ) { if ( result == GnomeKeyring::RESULT_OK ) { self->q->emitFinished(); } else { const QPair errorResult = mapGnomeKeyringError( result ); self->q->emitFinishedWithError( errorResult.first, errorResult.second ); } } void JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { watcher->deleteLater(); QDBusPendingReply reply = *watcher; if ( reply.isError() ) { fallbackOnError( reply.error() ); return; } PlainTextStore plainTextStore( q->service(), q->settings() ); if ( plainTextStore.contains( key ) ) { // If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data plainTextStore.remove( key ); } const int handle = reply.value(); if ( handle < 0 ) { q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") ); return; } QDBusPendingReply nextReply; if ( mode == Text ) nextReply = iface->writePassword( handle, q->service(), key, QString::fromUtf8(data), q->service() ); else if ( mode == Binary ) nextReply = iface->writeEntry( handle, q->service(), key, data, q->service() ); else nextReply = iface->removeEntry( handle, q->service(), key, q->service() ); QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this ); connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletFinished(QDBusPendingCallWatcher*)) ); } void JobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) { if ( !watcher->isError() ) { if ( mode == Binary ) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { data = reply.value(); } } else { QDBusPendingReply reply = *watcher; if (reply.isValid()) { data = reply.value().toUtf8(); } } } q->emitFinished(); } void DeletePasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_LibSecretKeyring: { if ( !LibSecretKeyring::deletePassword(key, q->service(), this) ) { q->emitFinishedWithError( OtherError, tr("Unknown error") ); } } break; case Backend_GnomeKeyring: { if ( !GnomeKeyring::delete_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(), reinterpret_cast( &JobPrivate::gnomeKeyring_writeCb ), this, 0 ) ) q->emitFinishedWithError( OtherError, tr("Unknown error") ); } break; case Backend_Kwallet4: kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this); break; case Backend_Kwallet5: kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this); break; } } void DeletePasswordJobPrivate::fallbackOnError(const QDBusError &err) { QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.data(); if ( !q->insecureFallback() ) { q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2") .arg( QDBusError::errorString( err.type() ), err.message() ) ); return; } actual->remove( key ); actual->sync(); q->emitFinished(); q->emitFinished(); } qtkeychain-0.10.0/cmake/0000755000175000017500000000000013576175767013752 5ustar hefeehefeeqtkeychain-0.10.0/cmake/Modules/0000755000175000017500000000000013576175767015362 5ustar hefeehefeeqtkeychain-0.10.0/cmake/Modules/ECMPackageConfigHelpers.cmake0000644000175000017500000002031013576175767022711 0ustar hefeehefee#.rst: # ECMPackageConfigHelpers # ----------------------- # # Helper macros for generating CMake package config files. # # ``write_basic_package_version_file()`` is the same as the one provided by the # `CMakePackageConfigHelpers # `_ # module in CMake; see that module's documentation for # more information. # # :: # # ecm_configure_package_config_file( # INSTALL_DESTINATION # [PATH_VARS [ [...]] # [NO_SET_AND_CHECK_MACRO] # [NO_CHECK_REQUIRED_COMPONENTS_MACRO]) # # # This behaves in the same way as configure_package_config_file() from CMake # 2.8.12, except that it adds an extra helper macro: find_dependency(). It is # highly recommended that you read the `documentation for # CMakePackageConfigHelpers # `_ # for more information, particularly with regard to the PATH_VARS argument. # # Note that there is no argument that will disable the find_dependency() macro; # if you do not require this macro, you should use # ``configure_package_config_file`` from the CMakePackageConfigHelpers module. # # CMake 3.0 includes a CMakeFindDependencyMacro module that provides the # find_dependency() macro (which you can ``include()`` in your package config # file), so this file is only useful for projects wishing to provide config # files that will work with CMake 2.8.12. # # Additional Config File Macros # ============================= # # :: # # find_dependency( [ [EXACT]]) # # find_dependency() should be used instead of find_package() to find package # dependencies. It forwards the correct parameters for EXACT, QUIET and # REQUIRED which were passed to the original find_package() call. It also sets # an informative diagnostic message if the dependency could not be found. # # Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry # Copyright 2013 Stephen Kelly # # 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 copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the 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. 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() qtkeychain-0.10.0/cmake/Modules/ECMSetupVersion.cmake0000644000175000017500000002247713576175767021373 0ustar hefeehefee#.rst: # ECMSetupVersion # --------------- # # Handle library version information. # # :: # # ecm_setup_version( # VARIABLE_PREFIX # [SOVERSION ] # [VERSION_HEADER ] # [PACKAGE_VERSION_FILE [COMPATIBILITY ]] ) # # This parses a version string and sets up a standard set of version variables. # It can optionally also create a C version header file and a CMake package # version file to install along with the library. # # If the ```` argument is of the form ``..`` # (or ``...``), The following CMake variables are # set:: # # _VERSION_MAJOR - # _VERSION_MINOR - # _VERSION_PATCH - # _VERSION - # _VERSION_STRING - (for compatibility: use _VERSION instead) # _SOVERSION - , or if SOVERSION was not given # # If CMake policy CMP0048 is not NEW, the following CMake variables will also # be set: # # PROJECT_VERSION_MAJOR - # PROJECT_VERSION_MINOR - # PROJECT_VERSION_PATCH - # PROJECT_VERSION - # PROJECT_VERSION_STRING - (for compatibility: use PROJECT_VERSION instead) # # If the VERSION_HEADER option is used, a simple C header is generated with the # given filename. If filename is a relative path, it is interpreted as relative # to CMAKE_CURRENT_BINARY_DIR. The generated header contains the following # macros:: # # _VERSION_MAJOR - as an integer # _VERSION_MINOR - as an integer # _VERSION_PATCH - as an integer # _VERSION_STRING - as a C string # _VERSION - the version as an integer # # ``_VERSION`` has ```` in the bottom 8 bits, ```` in the # next 8 bits and ```` in the remaining bits. Note that ```` and # ```` must be less than 256. # # If the PACKAGE_VERSION_FILE option is used, a simple CMake package version # file is created using the write_basic_package_version_file() macro provided by # CMake. It should be installed in the same location as the Config.cmake file of # the library so that it can be found by find_package(). If the filename is a # relative path, it is interpreted as relative to CMAKE_CURRENT_BINARY_DIR. The # optional COMPATIBILITY option is forwarded to # write_basic_package_version_file(), and defaults to AnyNewerVersion. # # If CMake policy CMP0048 is NEW, an alternative form of the command is # available:: # # ecm_setup_version(PROJECT # [VARIABLE_PREFIX ] # [SOVERSION ] # [VERSION_HEADER ] # [PACKAGE_VERSION_FILE ] ) # # This will use the version information set by the project() command. # VARIABLE_PREFIX defaults to the project name. Note that PROJECT must be the # first argument. In all other respects, it behaves like the other form of the # command. # # Since pre-1.0.0. # # COMPATIBLITY option available since 1.6.0. #============================================================================= # Copyright 2014 Alex Merry # Copyright 2012 Alexander Neundorf # # 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 copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the 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. 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-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major "${_version}") string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor "${_version}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([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() qtkeychain-0.10.0/cmake/Modules/GNUInstallDirs.cmake0000644000175000017500000001626613576175767021201 0ustar hefeehefee# - Define GNU standard installation directories # Provides install directory variables as defined for GNU software: # http://www.gnu.org/prep/standards/html_node/Directory-Variables.html # Inclusion of this module defines the following variables: # CMAKE_INSTALL_ - destination for files of a given type # CMAKE_INSTALL_FULL_ - corresponding absolute path # where is one of: # BINDIR - user executables (bin) # SBINDIR - system admin executables (sbin) # LIBEXECDIR - program executables (libexec) # SYSCONFDIR - read-only single-machine data (etc) # SHAREDSTATEDIR - modifiable architecture-independent data (com) # LOCALSTATEDIR - modifiable single-machine data (var) # LIBDIR - object code libraries (lib or lib64 or lib/ on Debian) # INCLUDEDIR - C header files (include) # OLDINCLUDEDIR - C header files for non-gcc (/usr/include) # DATAROOTDIR - read-only architecture-independent data root (share) # DATADIR - read-only architecture-independent data (DATAROOTDIR) # INFODIR - info documentation (DATAROOTDIR/info) # LOCALEDIR - locale-dependent data (DATAROOTDIR/locale) # MANDIR - man documentation (DATAROOTDIR/man) # DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME) # Each CMAKE_INSTALL_ value may be passed to the DESTINATION options of # install() commands for the corresponding file type. If the includer does # not define a value the above-shown default will be used and the value will # appear in the cache for editing by the user. # Each CMAKE_INSTALL_FULL_ value contains an absolute path constructed # from the corresponding destination by prepending (if necessary) the value # of CMAKE_INSTALL_PREFIX. #============================================================================= # Copyright 2011 Nikita Krupen'ko # Copyright 2011 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # Installation directories # if(NOT DEFINED CMAKE_INSTALL_BINDIR) set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)") endif() if(NOT DEFINED CMAKE_INSTALL_SBINDIR) set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)") endif() if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR) set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)") endif() if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR) set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)") endif() if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR) set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)") endif() if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR) set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(_LIBDIR_DEFAULT "lib") # Override this default 'lib' with 'lib64' iff: # - we are on Linux system but NOT cross-compiling # - we are NOT on debian # - we are on a 64 bits system # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf # For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if # CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu" # See http://wiki.debian.org/Multiarch if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT CMAKE_CROSSCOMPILING) if (EXISTS "/etc/debian_version") # is this a debian system ? if(CMAKE_LIBRARY_ARCHITECTURE) set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}") endif() else() # not debian, rely on CMAKE_SIZEOF_VOID_P: if(NOT DEFINED CMAKE_SIZEOF_VOID_P) message(AUTHOR_WARNING "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. " "Please enable at least one language before including GNUInstallDirs.") else() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(_LIBDIR_DEFAULT "lib64") endif() endif() endif() endif() set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})") endif() if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR) set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)") endif() if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR) set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)") endif() if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR) set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)") endif() #----------------------------------------------------------------------------- # Values whose defaults are relative to DATAROOTDIR. Store empty values in # the cache and store the defaults in local variables if the cache values are # not set explicitly. This auto-updates the defaults as DATAROOTDIR changes. if(NOT CMAKE_INSTALL_DATADIR) set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)") set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}") endif() if(NOT CMAKE_INSTALL_INFODIR) set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)") set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info") endif() if(NOT CMAKE_INSTALL_LOCALEDIR) set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)") set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale") endif() if(NOT CMAKE_INSTALL_MANDIR) set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)") set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man") endif() if(NOT CMAKE_INSTALL_DOCDIR) set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)") set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}") endif() #----------------------------------------------------------------------------- mark_as_advanced( CMAKE_INSTALL_BINDIR CMAKE_INSTALL_SBINDIR CMAKE_INSTALL_LIBEXECDIR CMAKE_INSTALL_SYSCONFDIR CMAKE_INSTALL_SHAREDSTATEDIR CMAKE_INSTALL_LOCALSTATEDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_OLDINCLUDEDIR CMAKE_INSTALL_DATAROOTDIR CMAKE_INSTALL_DATADIR CMAKE_INSTALL_INFODIR CMAKE_INSTALL_LOCALEDIR CMAKE_INSTALL_MANDIR CMAKE_INSTALL_DOCDIR ) # Result directories # foreach(dir BINDIR SBINDIR LIBEXECDIR SYSCONFDIR SHAREDSTATEDIR LOCALSTATEDIR LIBDIR INCLUDEDIR OLDINCLUDEDIR DATAROOTDIR DATADIR INFODIR LOCALEDIR MANDIR DOCDIR ) if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}}) set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}") else() set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}") endif() endforeach() qtkeychain-0.10.0/cmake/Modules/ECMGeneratePriFile.cmake0000644000175000017500000002077713576175767021733 0ustar hefeehefee#.rst: # ECMGeneratePriFile # ------------------ # # Generate a ``.pri`` file for the benefit of qmake-based projects. # # As well as the function below, this module creates the cache variable # ``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``. # This assumes Qt and the current project are both installed to the same # non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will # certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like # ``share/qt5/mkspecs/modules``. # # The main thing is that this should be the ``modules`` subdirectory of either # the default qmake ``mkspecs`` directory or of a directory that will be in the # ``$QMAKEPATH`` environment variable when qmake is run. # # :: # # ecm_generate_pri_file(BASE_NAME # LIB_NAME # [DEPS " [ [...]]"] # [FILENAME_VAR ] # [INCLUDE_INSTALL_DIR ] # [LIB_INSTALL_DIR ]) # # If your CMake project produces a Qt-based library, you may expect there to be # applications that wish to use it that use a qmake-based build system, rather # than a CMake-based one. Creating a ``.pri`` file will make use of your # library convenient for them, in much the same way that CMake config files make # things convenient for CMake-based applications. # # ecm_generate_pri_file() generates just such a file. It requires the # ``PROJECT_VERSION_STRING`` variable to be set. This is typically set by # :module:`ECMSetupVersion`, although the project() command in CMake 3.0.0 and # later can also set this. # # BASE_NAME specifies the name qmake project (.pro) files should use to refer to # the library (eg: KArchive). LIB_NAME is the name of the actual library to # link to (ie: the first argument to add_library()). DEPS is a space-separated # list of the base names of other libraries (for Qt libraries, use the same # names you use with the ``QT`` variable in a qmake project file, such as "core" # for QtCore). FILENAME_VAR specifies the name of a variable to store the path # to the generated file in. # # INCLUDE_INSTALL_DIR is the path (relative to ``CMAKE_INSTALL_PREFIX``) that # include files will be installed to. It defaults to # ``${INCLUDE_INSTALL_DIR}/`` if the ``INCLUDE_INSTALL_DIR`` variable # is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable # is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR # operates similarly for the installation location for libraries; it defaults to # ``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order. # # Example usage: # # .. code-block:: cmake # # ecm_generate_pri_file( # BASE_NAME KArchive # LIB_NAME KF5KArchive # DEPS "core" # FILENAME_VAR pri_filename # ) # install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) # # A qmake-based project that wished to use this would then do:: # # QT += KArchive # # in their ``.pro`` file. # # Since pre-1.0.0. #============================================================================= # Copyright 2014 David Faure # # 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 copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the 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. # Replicate the logic from KDEInstallDirs.cmake as we can't depend on it # Ask qmake if we're using the same prefix as Qt set(_askqmake OFF) if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS) include(ECMQueryQmake) query_qmake(qt_install_prefix_dir QT_INSTALL_PREFIX) if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}") set(_askqmake ON) endif() endif() if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake) include(ECMQueryQmake) query_qmake(qt_host_data_dir QT_HOST_DATA) set(ECM_MKSPECS_INSTALL_DIR ${qt_host_data_dir}/mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") else() set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") endif() function(ECM_GENERATE_PRI_FILE) set(options ) set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) set(multiValueArgs ) cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(EGPF_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"") endif() if(NOT EGPF_BASE_NAME) message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call") endif() if(NOT EGPF_LIB_NAME) message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call") endif() if(NOT PROJECT_VERSION_STRING) message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING not set before ECM_GENERATE_PRI_FILE() call. Did you call ecm_setup_version?") endif() if(NOT EGPF_INCLUDE_INSTALL_DIR) if(INCLUDE_INSTALL_DIR) set(EGPF_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/${EGPF_BASE_NAME}") elseif(CMAKE_INSTALL_INCLUDEDIR) set(EGPF_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${EGPF_BASE_NAME}") else() set(EGPF_INCLUDE_INSTALL_DIR "include/${EGPF_BASE_NAME}") endif() endif() if(NOT EGPF_LIB_INSTALL_DIR) if(LIB_INSTALL_DIR) set(EGPF_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") elseif(CMAKE_INSTALL_LIBDIR) set(EGPF_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") else() set(EGPF_LIB_INSTALL_DIR "lib") endif() endif() string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_STRING}") string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PROJECT_VERSION_MINOR "${PROJECT_VERSION_STRING}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PROJECT_VERSION_PATCH "${PROJECT_VERSION_STRING}") set(PRI_TARGET_BASENAME ${EGPF_BASE_NAME}) set(PRI_TARGET_LIBNAME ${EGPF_LIB_NAME}) set(PRI_TARGET_QTDEPS ${EGPF_DEPS}) if(IS_ABSOLUTE "${EGPF_INCLUDE_INSTALL_DIR}") set(PRI_TARGET_INCLUDES "${EGPF_INCLUDE_INSTALL_DIR}") else() set(PRI_TARGET_INCLUDES "${CMAKE_INSTALL_PREFIX}/${EGPF_INCLUDE_INSTALL_DIR}") endif() if(IS_ABSOLUTE "${EGPF_LIB_INSTALL_DIR}") set(PRI_TARGET_LIBS "${EGPF_LIB_INSTALL_DIR}") else() set(PRI_TARGET_LIBS "${CMAKE_INSTALL_PREFIX}/${EGPF_LIB_INSTALL_DIR}") endif() set(PRI_TARGET_DEFINES "") set(PRI_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/qt_${PRI_TARGET_BASENAME}.pri) if (EGPF_FILENAME_VAR) set(${EGPF_FILENAME_VAR} ${PRI_FILENAME} PARENT_SCOPE) endif() file(GENERATE OUTPUT ${PRI_FILENAME} CONTENT "QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING} QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR} QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR} QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH} QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME} QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME} QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES} QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES} QT.${PRI_TARGET_BASENAME}.private_includes = QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS} QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS} " ) endfunction() qtkeychain-0.10.0/cmake/Modules/ECMQueryQmake.cmake0000644000175000017500000000213613576175767020777 0ustar hefeehefeefind_package(Qt5Core QUIET) if (Qt5Core_FOUND) set(_qmake_executable_default "qmake-qt5") endif () if (TARGET Qt5::qmake) get_target_property(_qmake_executable_default Qt5::qmake LOCATION) endif() set(QMAKE_EXECUTABLE ${_qmake_executable_default} CACHE FILEPATH "Location of the Qt5 qmake executable") # This is not public API (yet)! function(query_qmake result_variable qt_variable) if(NOT QMAKE_EXECUTABLE) set(${result_variable} "" PARENT_SCOPE) message(WARNING "Should specify a qmake Qt5 binary. Can't check ${qt_variable}") return() endif() execute_process( COMMAND ${QMAKE_EXECUTABLE} -query "${qt_variable}" RESULT_VARIABLE return_code OUTPUT_VARIABLE output ) if(return_code EQUAL 0) string(STRIP "${output}" output) file(TO_CMAKE_PATH "${output}" output_path) set(${result_variable} "${output_path}" PARENT_SCOPE) else() message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query \"${qt_variable}\"") message(FATAL_ERROR "QMake call failed: ${return_code}") endif() endfunction() qtkeychain-0.10.0/COPYING0000644000175000017500000000225013576175767013724 0ustar hefeehefeeRedistribution 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. 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. qtkeychain-0.10.0/keychain_mac.cpp0000644000175000017500000001343113576175767016013 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" #include #include #include using namespace QKeychain; template struct Releaser { explicit Releaser( const T& v ) : value( v ) {} ~Releaser() { CFRelease( value ); } const T value; }; static QString strForStatus( OSStatus os ) { const Releaser str( SecCopyErrorMessageString( os, 0 ) ); const char * const buf = CFStringGetCStringPtr( str.value, kCFStringEncodingUTF8 ); if ( !buf ) return QObject::tr( "OS X Keychain error (OSStatus %1)" ).arg( os ); return QObject::tr( "%1 (OSStatus %2)" ) .arg( QString::fromUtf8( buf, strlen( buf ) ) ).arg( os ); } static OSStatus readPw( QByteArray* pw, const QString& service, const QString& account, SecKeychainItemRef* ref ) { Q_ASSERT( pw ); pw->clear(); const QByteArray serviceData = service.toUtf8(); const QByteArray accountData = account.toUtf8(); void* data = 0; UInt32 len = 0; const OSStatus ret = SecKeychainFindGenericPassword( NULL, // default keychain serviceData.size(), serviceData.constData(), accountData.size(), accountData.constData(), &len, &data, ref ); if ( ret == noErr ) { *pw = QByteArray( reinterpret_cast( data ), len ); const OSStatus ret2 = SecKeychainItemFreeContent ( 0, data ); if ( ret2 != noErr ) qWarning() << "Could not free item content: " << strForStatus( ret2 ); } return ret; } void ReadPasswordJobPrivate::scheduledStart() { QString errorString; Error error = NoError; const OSStatus ret = readPw( &data, q->service(), q->key(), 0 ); switch ( ret ) { case noErr: break; case errSecItemNotFound: errorString = tr("Password not found"); error = EntryNotFound; break; default: errorString = strForStatus( ret ); error = OtherError; break; } q->emitFinishedWithError( error, errorString ); } static QKeychain::Error deleteEntryImpl( const QString& service, const QString& account, QString* err ) { SecKeychainItemRef ref; QByteArray pw; const OSStatus ret1 = readPw( &pw, service, account, &ref ); if ( ret1 == errSecItemNotFound ) return NoError; // No item stored, we're done if ( ret1 != noErr ) { *err = strForStatus( ret1 ); //TODO map error code, set errstr return OtherError; } const Releaser releaser( ref ); const OSStatus ret2 = SecKeychainItemDelete( ref ); if ( ret2 == noErr ) return NoError; //TODO map error code *err = strForStatus( ret2 ); return CouldNotDeleteEntry; } static QKeychain::Error writeEntryImpl( const QString& service, const QString& account, const QByteArray& data, QString* err ) { Q_ASSERT( err ); err->clear(); const QByteArray serviceData = service.toUtf8(); const QByteArray accountData = account.toUtf8(); const OSStatus ret = SecKeychainAddGenericPassword( NULL, //default keychain serviceData.size(), serviceData.constData(), accountData.size(), accountData.constData(), data.size(), data.constData(), NULL //item reference ); if ( ret != noErr ) { switch ( ret ) { case errSecDuplicateItem: { Error derr = deleteEntryImpl( service, account, err ); if ( derr != NoError ) return CouldNotDeleteEntry; else return writeEntryImpl( service, account, data, err ); } default: *err = strForStatus( ret ); return OtherError; } } return NoError; } void WritePasswordJobPrivate::scheduledStart() { QString errorString; Error error = NoError; error = writeEntryImpl( q->service(), key, data, &errorString ); q->emitFinishedWithError( error, errorString ); } void DeletePasswordJobPrivate::scheduledStart() { QString errorString; Error error = NoError; const Error derr = deleteEntryImpl( q->service(), key, &errorString ); if ( derr != NoError ) error = CouldNotDeleteEntry; q->emitFinishedWithError( error, errorString ); } qtkeychain-0.10.0/keychain_win.cpp0000644000175000017500000001407113576175767016051 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" #include "plaintextstore_p.h" #include #include #include using namespace QKeychain; #if defined(USE_CREDENTIAL_STORE) #include void ReadPasswordJobPrivate::scheduledStart() { LPCWSTR name = (LPCWSTR)key.utf16(); PCREDENTIALW cred; if (!CredReadW(name, CRED_TYPE_GENERIC, 0, &cred)) { Error error; QString msg; switch(GetLastError()) { case ERROR_NOT_FOUND: error = EntryNotFound; msg = tr("Password entry not found"); break; default: error = OtherError; msg = tr("Could not decrypt data"); break; } q->emitFinishedWithError( error, msg ); return; } data = QByteArray((char*)cred->CredentialBlob, cred->CredentialBlobSize); CredFree(cred); q->emitFinished(); } void WritePasswordJobPrivate::scheduledStart() { CREDENTIALW cred; char *pwd = data.data(); LPWSTR name = (LPWSTR)key.utf16(); memset(&cred, 0, sizeof(cred)); cred.Comment = const_cast(L"QtKeychain"); cred.Type = CRED_TYPE_GENERIC; cred.TargetName = name; cred.CredentialBlobSize = data.size(); cred.CredentialBlob = (LPBYTE)pwd; cred.Persist = CRED_PERSIST_ENTERPRISE; if (CredWriteW(&cred, 0)) { q->emitFinished(); return; } DWORD err = GetLastError(); // Detect size-exceeded errors and provide nicer messages. // Unfortunately these error codes aren't documented. // Found empirically on Win10 1803 build 17134.523. if (err == RPC_X_BAD_STUB_DATA) { const size_t maxBlob = CRED_MAX_CREDENTIAL_BLOB_SIZE; if (cred.CredentialBlobSize > maxBlob) { q->emitFinishedWithError( OtherError, tr("Credential size exceeds maximum size of %1").arg(maxBlob)); return; } } if (err == RPC_S_INVALID_BOUND) { const size_t maxTargetName = CRED_MAX_GENERIC_TARGET_NAME_LENGTH; if (key.size() > maxTargetName) { q->emitFinishedWithError( OtherError, tr("Credential key exceeds maximum size of %1").arg(maxTargetName)); return; } } q->emitFinishedWithError( OtherError, tr("Writing credentials failed: Win32 error code %1").arg(err) ); } void DeletePasswordJobPrivate::scheduledStart() { LPCWSTR name = (LPCWSTR)key.utf16(); if (!CredDeleteW(name, CRED_TYPE_GENERIC, 0)) { Error error; QString msg; switch(GetLastError()) { case ERROR_NOT_FOUND: error = EntryNotFound; msg = tr("Password entry not found"); break; default: error = OtherError; msg = tr("Could not decrypt data"); break; } q->emitFinishedWithError( error, msg ); } else { q->emitFinished(); } } #else void ReadPasswordJobPrivate::scheduledStart() { PlainTextStore plainTextStore( q->service(), q->settings() ); QByteArray encrypted = plainTextStore.readData( key ); if ( plainTextStore.error() != NoError ) { q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); return; } DATA_BLOB blob_in, blob_out; blob_in.pbData = reinterpret_cast( encrypted.data() ); blob_in.cbData = encrypted.size(); const BOOL ret = CryptUnprotectData( &blob_in, NULL, NULL, NULL, NULL, 0, &blob_out ); if ( !ret ) { q->emitFinishedWithError( OtherError, tr("Could not decrypt data") ); return; } data = QByteArray( reinterpret_cast( blob_out.pbData ), blob_out.cbData ); SecureZeroMemory( blob_out.pbData, blob_out.cbData ); LocalFree( blob_out.pbData ); q->emitFinished(); } void WritePasswordJobPrivate::scheduledStart() { DATA_BLOB blob_in, blob_out; blob_in.pbData = reinterpret_cast( data.data() ); blob_in.cbData = data.size(); const BOOL res = CryptProtectData( &blob_in, L"QKeychain-encrypted data", NULL, NULL, NULL, 0, &blob_out ); if ( !res ) { q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available? return; } const QByteArray encrypted( reinterpret_cast( blob_out.pbData ), blob_out.cbData ); LocalFree( blob_out.pbData ); PlainTextStore plainTextStore( q->service(), q->settings() ); plainTextStore.write( key, encrypted, Binary ); if ( plainTextStore.error() != NoError ) { q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); return; } q->emitFinished(); } void DeletePasswordJobPrivate::scheduledStart() { PlainTextStore plainTextStore( q->service(), q->settings() ); plainTextStore.remove( key ); if ( plainTextStore.error() != NoError ) { q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() ); } else { q->emitFinished(); } } #endif qtkeychain-0.10.0/keychain.h0000644000175000017500000001761513576175767014650 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #ifndef KEYCHAIN_H #define KEYCHAIN_H #if !defined(QTKEYCHAIN_NO_EXPORT) #include "qkeychain_export.h" #else #define QKEYCHAIN_EXPORT #endif #include #include class QSettings; #define QTKEYCHAIN_VERSION 0x000100 namespace QKeychain { /** * Error codes */ enum Error { NoError=0, /**< No error occurred, operation was successful */ EntryNotFound, /**< For the given key no data was found */ CouldNotDeleteEntry, /**< Could not delete existing secret data */ AccessDeniedByUser, /**< User denied access to keychain */ AccessDenied, /**< Access denied for other reasons */ NoBackendAvailable, /**< No platform-specific keychain service available */ NotImplemented, /**< Not implemented on platform */ OtherError /**< Something else went wrong (errorString() might provide details) */ }; class JobExecutor; class JobPrivate; /** * @brief Abstract base class for all QKeychain jobs. */ class QKEYCHAIN_EXPORT Job : public QObject { Q_OBJECT public: ~Job(); /** * @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=0 ); Q_INVOKABLE void doStart(); private: void setError( Error error ); void setErrorString( const QString& errorString ); void scheduledStart(); protected: JobPrivate* const d; friend class JobExecutor; friend class JobPrivate; friend class ReadPasswordJobPrivate; friend class WritePasswordJobPrivate; friend class DeletePasswordJobPrivate; }; class ReadPasswordJobPrivate; /** * @brief Job for reading secrets from the keychain. * You can use a ReadPasswordJob to read passwords or binary data from the keychain. * This job requires a "service" string, which is basically a namespace of keys within the keychain. * This means that you can read all the pairs stored in the same service string. */ class QKEYCHAIN_EXPORT ReadPasswordJob : public Job { Q_OBJECT public: /** * Create a new ReadPasswordJob. * @param service The service string used by this job (can be empty). * @param parent The parent of this job. */ explicit ReadPasswordJob( const QString& service, QObject* parent=0 ); ~ReadPasswordJob(); /** * @return The binary data stored as value of this job's key(). * @see Job::key() */ QByteArray binaryData() const; /** * @return The string stored as value of this job's key(). * @see Job::key() * @warning Returns meaningless data if the data was stored as binary data. * @see WritePasswordJob::setTextData() */ QString textData() const; private: friend class QKeychain::ReadPasswordJobPrivate; }; class WritePasswordJobPrivate; /** * @brief Job for writing secrets to the keychain. * You can use a WritePasswordJob to store passwords or binary data in the keychain. * This job requires a "service" string, which is basically a namespace of keys within the keychain. * This means that you can store different pairs under the same service string. */ class QKEYCHAIN_EXPORT WritePasswordJob : public Job { Q_OBJECT public: /** * Create a new WritePasswordJob. * @param service The service string used by this job (can be empty). * @param parent The parent of this job. */ explicit WritePasswordJob( const QString& service, QObject* parent=0 ); ~WritePasswordJob(); /** * Set the @p data that the job will store in the keychain as binary data. * @warning setBinaryData() and setTextData() are mutually exclusive. */ void setBinaryData( const QByteArray& data ); /** * Set the @p data that the job will store in the keychain as string. * Typically @p data is a password. * @warning setBinaryData() and setTextData() are mutually exclusive. */ void setTextData( const QString& data ); private: friend class QKeychain::WritePasswordJobPrivate; }; class DeletePasswordJobPrivate; /** * @brief Job for deleting secrets from the keychain. * You can use a DeletePasswordJob to delete passwords or binary data from the keychain. * This job requires a "service" string, which is basically a namespace of keys within the keychain. * This means that you can delete all the pairs stored in the same service string. */ class QKEYCHAIN_EXPORT DeletePasswordJob : public Job { Q_OBJECT public: /** * Create a new DeletePasswordJob. * @param service The service string used by this job (can be empty). * @param parent The parent of this job. */ explicit DeletePasswordJob( const QString& service, QObject* parent=0 ); ~DeletePasswordJob(); private: friend class QKeychain::DeletePasswordJobPrivate; }; } // namespace QtKeychain #endif qtkeychain-0.10.0/plaintextstore.cpp0000644000175000017500000000667513576175767016501 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * Copyright (C) 2016 Mathias Hasselmann * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "plaintextstore_p.h" using namespace QKeychain; namespace { #ifdef Q_OS_WIN inline QString dataKey(const QString &key) { return key; } #else // Q_OS_WIN inline QString dataKey(const QString &key) { return key + QLatin1String("/data"); } inline QString typeKey(const QString &key) { return key + QLatin1String("/type"); } #endif // Q_OS_WIN } PlainTextStore::PlainTextStore(const QString &service, QSettings *settings) : m_localSettings(settings ? 0 : new QSettings(service)) , m_actualSettings(settings ? settings : m_localSettings.data()) , m_error(NoError) { } bool PlainTextStore::contains(const QString &key) const { return m_actualSettings->contains(dataKey(key)); } QByteArray PlainTextStore::readData(const QString &key) { return read(dataKey(key)).toByteArray(); } #ifndef Q_OS_WIN JobPrivate::Mode PlainTextStore::readMode(const QString &key) { return JobPrivate::stringToMode(read(typeKey(key)).toString()); } #endif // Q_OS_WIN void PlainTextStore::write(const QString &key, const QByteArray &data, JobPrivate::Mode mode) { if (m_actualSettings->status() != QSettings::NoError) return; #ifndef Q_OS_WIN m_actualSettings->setValue(typeKey(key), JobPrivate::modeToString(mode)); #else // Q_OS_WIN Q_UNUSED(mode); #endif // Q_OS_WIN m_actualSettings->setValue(dataKey(key), data); m_actualSettings->sync(); if (m_actualSettings->status() == QSettings::AccessError) { setError(AccessDenied, tr("Could not store data in settings: access error")); } else if (m_actualSettings->status() != QSettings::NoError) { setError(OtherError, tr("Could not store data in settings: format error")); } else { setError(NoError, QString()); } } void PlainTextStore::remove(const QString &key) { if (m_actualSettings->status() != QSettings::NoError) return; #ifndef Q_OS_WIN m_actualSettings->remove(typeKey(key)); #endif // Q_OS_WIN m_actualSettings->remove(dataKey(key)); m_actualSettings->sync(); if (m_actualSettings->status() == QSettings::AccessError) { setError(AccessDenied, tr("Could not delete data from settings: access error")); } else if (m_actualSettings->status() != QSettings::NoError) { setError(OtherError, tr("Could not delete data from settings: format error")); } else { setError(NoError, QString()); } } void PlainTextStore::setError(Error error, const QString &errorString) { m_error = error; m_errorString = errorString; } QVariant PlainTextStore::read(const QString &key) { const QVariant value = m_actualSettings->value(key); if (value.isNull()) { setError(EntryNotFound, tr("Entry not found")); } else { setError(NoError, QString()); } return value; } qtkeychain-0.10.0/QtKeychainConfig.cmake.in0000644000175000017500000000124613576175767017472 0ustar hefeehefee# - Config file for the QtKeychain package # It defines the following variables # QTKEYCHAIN_INCLUDE_DIRS - include directories for QtKeychain # QTKEYCHAIN_LIBRARIES - libraries to link against @PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainLibraryDepends.cmake") if("@QTKEYCHAIN_VERSION_INFIX@" STREQUAL "5") find_dependency(Qt5Core) if(UNIX AND NOT APPLE) find_dependency(Qt5DBus) endif() else() find_dependency(Qt4 COMPONENTS QtCore) endif() set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@") get_target_property(QTKEYCHAIN_INCLUDE_DIRS "@QTKEYCHAIN_TARGET_NAME@" INTERFACE_INCLUDE_DIRECTORIES) qtkeychain-0.10.0/testclient.cpp0000644000175000017500000001077313576175767015564 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include #include #include "keychain.h" #include using namespace QKeychain; static int printUsage() { std::cerr << "testclient store " << std::endl; std::cerr << "testclient restore " << std::endl; std::cerr << "testclient delete " << std::endl; return 1; } int main( int argc, char** argv ) { QCoreApplication app( argc, argv ); const QStringList args = app.arguments(); if ( args.count() < 2 ) return printUsage(); QStringList::ConstIterator it = args.constBegin(); ++it; if ( *it == QLatin1String("store") ) { if ( ++it == args.constEnd() ) return printUsage(); const QString acc = *it; if ( ++it == args.constEnd() ) return printUsage(); const QString pass = *it; if ( ++it != args.constEnd() ) return printUsage(); WritePasswordJob job( QLatin1String("qtkeychain-testclient") ); job.setAutoDelete( false ); job.setKey( acc ); job.setTextData( pass ); QEventLoop loop; job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); job.start(); loop.exec(); if ( job.error() ) { std::cerr << "Storing password failed: " << qPrintable(job.errorString()) << std::endl; return 1; } std::cout << "Password stored successfully" << std::endl; } else if ( *it == QLatin1String("bstore") ) { if ( ++it == args.constEnd() ) return printUsage(); const QString acc = *it; if ( ++it == args.constEnd() ) return printUsage(); const QString pass = *it; if ( ++it != args.constEnd() ) return printUsage(); WritePasswordJob job( QLatin1String("qtkeychain-testclient") ); job.setAutoDelete( false ); job.setKey( acc ); job.setBinaryData( pass.toUtf8() ); QEventLoop loop; job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); job.start(); loop.exec(); if ( job.error() ) { std::cerr << "Storing binary password failed: " << qPrintable(job.errorString()) << std::endl; return 1; } std::cout << "Password stored successfully" << std::endl; } else if ( *it == QLatin1String("restore") ) { if ( ++it == args.constEnd() ) return printUsage(); const QString acc = *it; if ( ++it != args.constEnd() ) return printUsage(); ReadPasswordJob job( QLatin1String("qtkeychain-testclient") ); job.setAutoDelete( false ); job.setKey( acc ); QEventLoop loop; job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); job.start(); loop.exec(); const QString pw = job.textData(); if ( job.error() ) { std::cerr << "Restoring password failed: " << qPrintable(job.errorString()) << std::endl; return 1; } std::cout << qPrintable(pw) << std::endl; } else if ( *it == QLatin1String("delete") ) { if ( ++it == args.constEnd() ) return printUsage(); const QString acc = *it; if ( ++it != args.constEnd() ) return printUsage(); DeletePasswordJob job( QLatin1String("qtkeychain-testclient") ); job.setAutoDelete( false ); job.setKey( acc ); QEventLoop loop; job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); job.start(); loop.exec(); if ( job.error() ) { std::cerr << "Deleting password failed: " << qPrintable(job.errorString()) << std::endl; return 1; } std::cout << "Password deleted successfully" << std::endl; } else { return printUsage(); } } qtkeychain-0.10.0/keychain_ios.mm0000644000175000017500000001457213576175767015703 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2016 Mathias Hasselmann * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" #import #import using namespace QKeychain; struct ErrorDescription { QKeychain::Error code; QString message; ErrorDescription(QKeychain::Error code, const QString &message) : code(code), message(message) {} static ErrorDescription fromStatus(OSStatus status) { switch(status) { case errSecSuccess: return ErrorDescription(QKeychain::NoError, Job::tr("No error")); case errSecItemNotFound: return ErrorDescription(QKeychain::EntryNotFound, Job::tr("The specified item could not be found in the keychain")); case errSecUserCanceled: return ErrorDescription(QKeychain::AccessDeniedByUser, Job::tr("User canceled the operation")); case errSecInteractionNotAllowed: return ErrorDescription(QKeychain::AccessDenied, Job::tr("User interaction is not allowed")); case errSecNotAvailable: return ErrorDescription(QKeychain::AccessDenied, Job::tr("No keychain is available. You may need to restart your computer")); case errSecAuthFailed: return ErrorDescription(QKeychain::AccessDenied, Job::tr("The user name or passphrase you entered is not correct")); case errSecVerifyFailed: return ErrorDescription(QKeychain::AccessDenied, Job::tr("A cryptographic verification failure has occurred")); case errSecUnimplemented: return ErrorDescription(QKeychain::NotImplemented, Job::tr("Function or operation not implemented")); case errSecIO: return ErrorDescription(QKeychain::OtherError, Job::tr("I/O error")); case errSecOpWr: return ErrorDescription(QKeychain::OtherError, Job::tr("Already open with with write permission")); case errSecParam: return ErrorDescription(QKeychain::OtherError, Job::tr("Invalid parameters passed to a function")); case errSecAllocate: return ErrorDescription(QKeychain::OtherError, Job::tr("Failed to allocate memory")); case errSecBadReq: return ErrorDescription(QKeychain::OtherError, Job::tr("Bad parameter or invalid state for operation")); case errSecInternalComponent: return ErrorDescription(QKeychain::OtherError, Job::tr("An internal component failed")); case errSecDuplicateItem: return ErrorDescription(QKeychain::OtherError, Job::tr("The specified item already exists in the keychain")); case errSecDecode: return ErrorDescription(QKeychain::OtherError, Job::tr("Unable to decode the provided data")); } return ErrorDescription(QKeychain::OtherError, Job::tr("Unknown error")); } }; void ReadPasswordJobPrivate::scheduledStart() { NSDictionary *const query = @{ (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), (__bridge id) kSecReturnData: @YES, }; CFTypeRef dataRef = nil; const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef); data.clear(); mode = Binary; if (status == errSecSuccess) { if (dataRef) data = QByteArray::fromCFData((CFDataRef) dataRef); q->emitFinished(); } else { const ErrorDescription error = ErrorDescription::fromStatus(status); q->emitFinishedWithError(error.code, Job::tr("Could not retrieve private key from keystore: %1").arg(error.message)); } if (dataRef) [dataRef release]; } void WritePasswordJobPrivate::scheduledStart() { NSDictionary *const query = @{ (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), }; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, nil); if (status == errSecSuccess) { NSDictionary *const update = @{ (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(), }; status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) update); } else { NSDictionary *const insert = @{ (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(), }; status = SecItemAdd((__bridge CFDictionaryRef) insert, nil); } if (status == errSecSuccess) { q->emitFinished(); } else { const ErrorDescription error = ErrorDescription::fromStatus(status); q->emitFinishedWithError(error.code, tr("Could not store data in settings: %1").arg(error.message)); } } void DeletePasswordJobPrivate::scheduledStart() { const NSDictionary *const query = @{ (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword, (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(), (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(), }; const OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query); if (status == errSecSuccess) { q->emitFinished(); } else { const ErrorDescription error = ErrorDescription::fromStatus(status); q->emitFinishedWithError(error.code, Job::tr("Could not remove private key from keystore: %1").arg(error.message)); } } qtkeychain-0.10.0/gnomekeyring.cpp0000644000175000017500000000644113576175767016101 0ustar hefeehefee#include "gnomekeyring_p.h" const char* GnomeKeyring::GNOME_KEYRING_DEFAULT = NULL; bool GnomeKeyring::isAvailable() { const GnomeKeyring& keyring = instance(); return keyring.isLoaded() && keyring.NETWORK_PASSWORD && keyring.is_available && keyring.find_password && keyring.store_password && keyring.delete_password && keyring.is_available(); } GnomeKeyring::gpointer GnomeKeyring::store_network_password( const gchar* keyring, const gchar* display_name, const gchar* user, const gchar* server, const gchar* type, const gchar* password, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ) { if ( !isAvailable() ) return 0; return instance().store_password( instance().NETWORK_PASSWORD, keyring, display_name, password, callback, data, destroy_data, "user", user, "server", server, "type", type, static_cast(0) ); } GnomeKeyring::gpointer GnomeKeyring::find_network_password( const gchar* user, const gchar* server, const gchar* type, OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ) { if ( !isAvailable() ) return 0; return instance().find_password( instance().NETWORK_PASSWORD, callback, data, destroy_data, "user", user, "server", server, "type", type, static_cast(0) ); } GnomeKeyring::gpointer GnomeKeyring::delete_network_password( const gchar* user, const gchar* server, OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ) { if ( !isAvailable() ) return 0; return instance().delete_password( instance().NETWORK_PASSWORD, callback, data, destroy_data, "user", user, "server", server, static_cast(0) ); } GnomeKeyring::GnomeKeyring() : QLibrary(QLatin1String("gnome-keyring"), 0) { static const PasswordSchema schema = { ITEM_NETWORK_PASSWORD, {{ "user", ATTRIBUTE_TYPE_STRING }, { "server", ATTRIBUTE_TYPE_STRING }, { "type", ATTRIBUTE_TYPE_STRING }, { 0, static_cast( 0 ) }} }; NETWORK_PASSWORD = &schema; is_available = reinterpret_cast( resolve( "gnome_keyring_is_available" ) ); find_password = reinterpret_cast( resolve( "gnome_keyring_find_password" ) ); store_password = reinterpret_cast( resolve( "gnome_keyring_store_password" ) ); delete_password = reinterpret_cast( resolve( "gnome_keyring_delete_password" ) ); } GnomeKeyring& GnomeKeyring::instance() { static GnomeKeyring keyring; return keyring; } qtkeychain-0.10.0/libsecret.cpp0000644000175000017500000002602413576175767015356 0ustar hefeehefee#if defined(HAVE_LIBSECRET) #include #endif #include "libsecret_p.h" #include #include #if defined(HAVE_LIBSECRET) const SecretSchema* qtkeychainSchema(void) { static const SecretSchema schema = { "org.qt.keychain", SECRET_SCHEMA_DONT_MATCH_NAME, { { "user", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "server", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "type", SECRET_SCHEMA_ATTRIBUTE_STRING } } }; return &schema; } typedef struct { QKeychain::JobPrivate *self; QString user; QString server; } callbackArg; typedef void (*secret_password_lookup_t) (const SecretSchema *schema, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; typedef gchar *(*secret_password_lookup_finish_t) (GAsyncResult *result, GError **error); typedef void (*secret_password_store_t) (const SecretSchema *schema, const gchar *collection, const gchar *label, const gchar *password, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; typedef gboolean (*secret_password_store_finish_t) (GAsyncResult *result, GError **error); typedef void (*secret_password_clear_t) (const SecretSchema *schema, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; typedef gboolean (*secret_password_clear_finish_t) (GAsyncResult *result, GError **error); typedef void (*secret_password_free_t) (gchar *password); typedef GQuark (*secret_error_get_quark_t) (void) G_GNUC_CONST; static secret_password_lookup_t secret_password_lookup_fn = NULL; static secret_password_lookup_finish_t secret_password_lookup_finish_fn = NULL; static secret_password_store_t secret_password_store_fn = NULL; static secret_password_store_finish_t secret_password_store_finish_fn = NULL; static secret_password_clear_t secret_password_clear_fn = NULL; static secret_password_clear_finish_t secret_password_clear_finish_fn = NULL; static secret_password_free_t secret_password_free_fn = NULL; static secret_error_get_quark_t secret_error_get_quark_fn = NULL; 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 = NULL; 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 != NULL) { 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(), NULL, on_password_lookup, arg, "user", arg->user.toUtf8().constData(), "server", arg->server.toUtf8().constData(), "type", "base64", NULL); 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 = NULL; QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst; Q_UNUSED(source); secret_password_store_finish_fn (result, &error); if (self) { if (error != NULL) { self->q->emitFinishedWithError( gerrorToCode(error), QString::fromUtf8(error->message) ); } else { self->q->emitFinished(); } } if (error != NULL) { g_error_free (error); } } static void on_password_cleared (GObject *source, GAsyncResult *result, gpointer inst) { GError *error = NULL; 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 != NULL) { 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 == NULL) return false; if (secret_password_lookup_finish_fn == NULL) return false; if (secret_password_store_fn == NULL) return false; if (secret_password_store_finish_fn == NULL) return false; if (secret_password_clear_fn == NULL) return false; if (secret_password_clear_finish_fn == NULL) return false; if (secret_password_free_fn == NULL) return false; if (secret_error_get_quark_fn == NULL) 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; qDebug() << Q_FUNC_INFO; secret_password_lookup_fn (qtkeychainSchema(), NULL, on_password_lookup, arg, "user", user.toUtf8().constData(), "server", server.toUtf8().constData(), "type", "plaintext", NULL); return true; #else 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; } qDebug() << Q_FUNC_INFO; secret_password_store_fn (qtkeychainSchema(), SECRET_COLLECTION_DEFAULT, display_name.toUtf8().constData(), pwd.constData(), NULL, on_password_stored, self, "user", user.toUtf8().constData(), "server", server.toUtf8().constData(), "type", type.toUtf8().constData(), NULL); return true; #else return false; #endif } bool LibSecretKeyring::deletePassword(const QString &key, const QString &service, QKeychain::JobPrivate* self) { #if defined(HAVE_LIBSECRET) if (!isAvailable()) { return false; } qDebug() << Q_FUNC_INFO; secret_password_clear_fn (qtkeychainSchema(), NULL, on_password_cleared, self, "user", key.toUtf8().constData(), "server", service.toUtf8().constData(), NULL); return true; #else 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; } qtkeychain-0.10.0/appveyorHelp.psm10000644000175000017500000002646513576175767016167 0ustar hefeehefeeWrite-Host "Appveyor Helper scrips https://github.com/TheOneRing/appVeyorHelp" $ErrorActionPreference="Stop" $script:INSTALL_DIR="$env:APPVEYOR_BUILD_FOLDER\work\install" $CMAKE_INSTALL_ROOT="`"$INSTALL_DIR`"" -replace "\\", "/" $env:PATH="$env:PATH;$script:INSTALL_DIR" if(!$env:CI -eq "true") { function Push-AppveyorArtifact() { Write-Host "Push-AppveyorArtifact $ARGS" } function Start-FileDownload([string] $url, [string] $out) { if(!$out) { $out = $url.SubString($url.LastIndexOf("/")) } wget $url -Outfile $out } } function LogExec() { $OldErrorActionPreference=$ErrorActionPreference $ErrorActionPreference="Continue" $LastExitCode = 0 Write-Host $Args[0], $Args[1..(($Args.Count)-1)] & $Args[0] $Args[1..(($Args.Count)-1)] if(!$LastExitCode -eq 0) { exit $LastExitCode } $ErrorActionPreference=$OldErrorActionPreference } #Set environment variables for Visual Studio Command Prompt #http://stackoverflow.com/questions/2124753/how-i-can-use-powershell-with-the-visual-studio-command-prompt function BAT-CALL([string] $path, [string] $arg) { Write-Host "Calling `"$path`" `"$arg`"" cmd /c "$path" "$arg" `&`& set `|`| exit 1| foreach { if ($_ -match "=") { $v = $_.split("=") #Write-Host "ENV:\$($v[0])=$($v[1])" set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" } } if($LastExitCode -eq 1) { Write-Error "$path not found." } } function Get-QtDir() { $ver = 5.5 if($env:QT_VER) { $ver = $env:QT_VER } return "C:\Qt\$ver\$env:COMPILER\" } function SETUP-QT() { [string] $compiler=$env:COMPILER $qtDir = Get-QtDir $script:QT_BINARY_DIRS = @($qtDir) BAT-CALL "$qtDir\bin\qtenv2.bat" if ($compiler.StartsWith("mingw49")) { #remove sh.exe from path $env:PATH=$env:PATH -replace "C:\\Program Files \(x86\)\\Git\\bin", "" $script:MAKE="mingw32-make" $script:CMAKE_GENERATOR="MinGW Makefiles" $script:STRIP=@("strip", "-s") $script:QT_BINARY_DIRS += (Resolve-Path "$qtDir\..\..\Tools\mingw492_32\opt\") } elseif ($compiler.StartsWith("msvc")) { $arch = "x86" if($compiler.EndsWith("64")) { $arch = "amd64" } $compilerDirs = @{ "msvc2010" = "VS100COMNTOOLS"; "msvc2012" = "VS110COMNTOOLS"; "msvc2013" = "VS120COMNTOOLS"; "msvc2015" = "VS140COMNTOOLS" } $compilerVar = $compilerDirs[$compiler.Split("_")[0]] $compilerDir = (get-item -path "env:\$($compilerVar)").Value BAT-CALL "$compilerDir\..\..\VC\vcvarsall.bat" $arch $script:MAKE="nmake" $script:CMAKE_GENERATOR="NMake Makefiles" if($arch -eq "x86") { $script:QT_BINARY_DIRS += ("C:\OpenSSL-Win32") } else { $script:QT_BINARY_DIRS += ("C:\OpenSSL-Win64") } } } function Install-ChocolatelyModule([string] $module, [string[]] $myargs) { Write-Host "Install chocolately package $module" LogExec cinst $module @myargs -y } function Install-CmakeGitModule([string] $url, [hashtable] $arguments) { $module = $url.SubString($url.LastIndexOf("/")+1) $module = $module.Substring(0,$module.Length - 4) if(!$arguments.Contains("branch")) { $arguments["branch"] = "master" } if(!$arguments.Contains("buildType")) { $arguments["buildType"] = "Release" } mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build\$module pushd $env:APPVEYOR_BUILD_FOLDER\work\git LogExec git clone -q --depth 1 --branch ([string]$arguments["branch"]) $url $module popd pushd $env:APPVEYOR_BUILD_FOLDER\work\build\$module LogExec cmake -G $script:CMAKE_GENERATOR ("-DCMAKE_BUILD_TYPE=`"{0}`"" -f [string]$arguments["buildType"]) $env:APPVEYOR_BUILD_FOLDER\work\git\$module -DCMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_ROOT" $arguments["options"] LogExec $script:MAKE install popd } function Init([string[]] $chocoDeps, [System.Collections.Specialized.OrderedDictionary] $cmakeModules) { $script:MAKE="" $script:CMAKE_GENERATOR="" $script:STRIP=$null mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\image | Out-Null mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build | Out-Null SETUP-QT if($chocoDeps -contains "ninja") { $script:CMAKE_GENERATOR="Ninja" $script:MAKE="ninja" } if ( !(Test-Path "$env:APPVEYOR_BUILD_FOLDER\work\install" ) ) { mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\install | Out-Null mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\git | Out-Null foreach($module in $chocoDeps) { if($module -eq "nsis") { Install-ChocolatelyModule "nsis.portable" @("-pre") continue } Install-ChocolatelyModule $module } foreach($key in $cmakeModules.Keys) { Install-CmakeGitModule $key $cmakeModules[$key] } [string] $compiler=$env:COMPILER if($compiler.StartsWith("msvc")) { Write-Host "Downloading vcredist.exe" if ($compiler.StartsWith("msvc2015")) { if($compiler.EndsWith("64")) { Start-FileDownload https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe } else { Start-FileDownload https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe } } else { if($compiler.EndsWith("64")) { Start-FileDownload http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe } else { Start-FileDownload http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe } } } } } function relativePath([string] $root, [string] $path) { pushd $root $out = Resolve-Path -Relative $path popd return $out } function StripFile([string] $name) { if($script:STRIP) { if( $name.EndsWith(".dll") -or $name.EndsWith(".exe")) { Write-Host "strip file $name" LogExec @script:STRIP $name } } } function Get-DeployImageName() { $version = Get-Version if($env:APPVEYOR_REPO_TAG -eq "true") { return "$env:APPVEYOR_PROJECT_NAME`_$version`_Qt$env:QT_VER`_$env:COMPILER" }else{ return "$env:APPVEYOR_PROJECT_NAME`_$env:APPVEYOR_REPO_BRANCH`_$version`_Qt$env:QT_VER`_$env:COMPILER" } } function Get-Version() { if($env:APPVEYOR_REPO_TAG -eq "true") { return $env:APPVEYOR_REPO_TAG_NAME }else{ $commit = ([string]$env:APPVEYOR_REPO_COMMIT).SubString(0,6) return $commit } } function CmakeImageInstall() { $imageName = Get-DeployImageName $destDir = "$env:APPVEYOR_BUILD_FOLDER\work\cmakeDeployImage\$imageName" $env:DESTDIR = $destDir LogExec $script:MAKE install $env:DESTDIR = $null if(!$LastExitCode -eq 0) { Write-Error "Build Failed" } $env:DESTDIR=$null $prefix=$script:INSTALL_DIR if( $prefix.substring(1,1) -eq ":") { $prefix=$prefix.substring(3) } Write-Host "move $destDir\$prefix to $destDir" mv -Force "$destDir\$prefix\*" "$destDir" $rootLeftOver = $prefix.substring(0, $prefix.indexOf("\")) rm -Recurse "$destDir\$rootLeftOver" } function CreateDeployImage([string[]] $whiteList, [string[]] $blackList) { $imageName = Get-DeployImageName $deployPath = "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName" function copyWithWhitelist([string] $root) { $files = ls $root -Recurse foreach($fileName in $files.FullName) { $relPath = (relativePath $root $fileName).SubString(2) if($whiteList | Where {$relPath -match $_}) { if($blackList | Where {$relPath -match $_}) { continue } if(!(Test-Path $deployPath\$relPath)) { Write-Host "copy $fileName to $deployPath\$relPath" mkdir -Force (Split-Path -Parent $deployPath\$relPath) | Out-Null cp -Force $fileName $deployPath\$relPath StripFile $deployPath\$relPath } } } } Write-Host "CreateDeployImage $imageName" mkdir $deployPath | Out-Null copyWithWhitelist "$env:APPVEYOR_BUILD_FOLDER\work\cmakeDeployImage\$imageName" copyWithWhitelist "$env:APPVEYOR_BUILD_FOLDER\work\install\" foreach($folder in $script:QT_BINARY_DIRS) { copyWithWhitelist $folder } Write-Host "Deploy path $deployPath" return $deployPath } function 7ZipDeployImage() { $imageName = Get-DeployImageName LogExec 7za a "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.7z" "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName" Push-AppveyorArtifact "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.7z" } function NsisDeployImage([string] $scriptName) { $imageName = Get-DeployImageName $installerName = "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.exe" $version = Get-Version if(([string]$env:COMPILER).StartsWith("msvc")) { $redist = "$env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe" }else{ $redist = "none" } if($env:COMPILER.EndsWith("64")) { $defaultinstdir = "`$PROGRAMFILES64" }else{ $defaultinstdir = "`$PROGRAMFILES" } LogExec makensis.exe /DgitDir=$env:APPVEYOR_BUILD_FOLDER /Dsetupname=$installerName /Dcaption=$imageName /Dversion=$version /Dcompiler=$env:COMPILER /Dvcredist=$redist /Ddefaultinstdir=$defaultinstdir /Dsrcdir=$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName $scriptName Push-AppveyorArtifact $installerName } # based on http://thesurlyadmin.com/2013/01/07/remove-empty-directories-recursively/ function DeleteEmptyFodlers([string] $root) { $Folders = @() foreach($Folder in (Get-ChildItem -Path $root -Recurse -Directory)) { $Folders += New-Object PSObject -Property @{ Object = $Folder Depth = ($Folder.FullName.Split("\")).Count } } $Folders = $Folders | Sort Depth -Descending foreach($Folder in $Folders) { If ($Folder.Object.GetFileSystemInfos().Count -eq 0) { Write-Host "Delete empty dir:" $Folder.Object.FullName Remove-Item -Path $Folder.Object.FullName -Force } } } Write-Host "CMAKE_INSTALL_ROOT: $CMAKE_INSTALL_ROOT" Write-Host "Image-Name: ", (Get-DeployImageName) Export-ModuleMember -Function @("Init","CmakeImageInstall", "CreateDeployImage", "LogExec", "7ZipDeployImage", "NsisDeployImage", "DeleteEmptyFodlers") -Variable @("CMAKE_INSTALL_ROOT") qtkeychain-0.10.0/plaintextstore_p.h0000644000175000017500000000320413576175767016446 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * Copyright (C) 2016 Mathias Hasselmann * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #ifndef QTKEYCHAIN_PLAINTEXTSTORE_P_H #define QTKEYCHAIN_PLAINTEXTSTORE_P_H #include "keychain_p.h" namespace QKeychain { class PlainTextStore { Q_DECLARE_TR_FUNCTIONS(QKeychain::PlainTextStore) public: explicit PlainTextStore(const QString &service, QSettings *settings); Error error() const { return m_error; } QString errorString() const { return m_errorString; } bool contains(const QString &key) const; QByteArray readData(const QString &key); JobPrivate::Mode readMode(const QString &key); void write(const QString &key, const QByteArray &data, JobPrivate::Mode mode); void remove(const QString &key); private: void setError(Error error, const QString &errorString); QVariant read(const QString &key); const QScopedPointer m_localSettings; QSettings *const m_actualSettings; QString m_errorString; Error m_error; }; } #endif // QTKEYCHAIN_PLAINTEXTSTORE_P_H qtkeychain-0.10.0/keychain.cpp0000644000175000017500000001275413576175767015202 0ustar hefeehefee/****************************************************************************** * Copyright (C) 2011-2015 Frank Osterfeld * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution * * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain.h" #include "keychain_p.h" using namespace QKeychain; Job::Job( JobPrivate *q, QObject *parent ) : QObject( parent ) , d ( q ) { } Job::~Job() { delete d; } QString Job::service() const { return d->service; } QSettings* Job::settings() const { return d->settings; } void Job::setSettings( QSettings* settings ) { d->settings = settings; } void Job::start() { QMetaObject::invokeMethod( this, "doStart", Qt::QueuedConnection ); } bool Job::autoDelete() const { return d->autoDelete; } void Job::setAutoDelete( bool autoDelete ) { d->autoDelete = autoDelete; } bool Job::insecureFallback() const { return d->insecureFallback; } void Job::setInsecureFallback( bool insecureFallback ) { d->insecureFallback = insecureFallback; } void Job::doStart() { JobExecutor::instance()->enqueue( this ); } void Job::emitFinished() { emit finished( this ); if ( d->autoDelete ) deleteLater(); } void Job::emitFinishedWithError( Error error, const QString& errorString ) { d->error = error; d->errorString = errorString; emitFinished(); } void Job::scheduledStart() { d->scheduledStart(); } Error Job::error() const { return d->error; } QString Job::errorString() const { return d->errorString; } void Job::setError( Error error ) { d->error = error; } void Job::setErrorString( const QString& errorString ) { d->errorString = errorString; } ReadPasswordJob::ReadPasswordJob( const QString& service, QObject* parent ) : Job( new ReadPasswordJobPrivate( service, this ), parent ) { } ReadPasswordJob::~ReadPasswordJob() { } QString ReadPasswordJob::textData() const { return QString::fromUtf8( d->data ); } QByteArray ReadPasswordJob::binaryData() const { return d->data; } QString Job::key() const { return d->key; } void Job::setKey( const QString& key_ ) { d->key = key_; } WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent ) : Job( new WritePasswordJobPrivate( service, this ), parent ) { } WritePasswordJob::~WritePasswordJob() { } void WritePasswordJob::setBinaryData( const QByteArray& data ) { d->data = data; d->mode = JobPrivate::Binary; } void WritePasswordJob::setTextData( const QString& data ) { d->data = data.toUtf8(); d->mode = JobPrivate::Text; } DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent ) : Job( new DeletePasswordJobPrivate( service, this ), parent ) { } DeletePasswordJob::~DeletePasswordJob() { } DeletePasswordJobPrivate::DeletePasswordJobPrivate(const QString &service_, DeletePasswordJob *qq) : JobPrivate(service_, qq) { } JobExecutor::JobExecutor() : QObject( 0 ) , m_jobRunning( false ) { } void JobExecutor::enqueue( Job* job ) { m_queue.enqueue( job ); startNextIfNoneRunning(); } void JobExecutor::startNextIfNoneRunning() { if ( m_queue.isEmpty() || m_jobRunning ) return; QPointer next; while ( !next && !m_queue.isEmpty() ) { next = m_queue.dequeue(); } if ( next ) { connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) ); connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) ); m_jobRunning = true; next->scheduledStart(); } } void JobExecutor::jobDestroyed( QObject* object ) { Job* job = static_cast(object); Q_UNUSED( object ) // for release mode job->disconnect( this ); m_jobRunning = false; startNextIfNoneRunning(); } void JobExecutor::jobFinished( Job* job ) { Q_UNUSED( job ) // for release mode job->disconnect( this ); m_jobRunning = false; startNextIfNoneRunning(); } JobExecutor* JobExecutor::s_instance = 0; JobExecutor* JobExecutor::instance() { if ( !s_instance ) s_instance = new JobExecutor; return s_instance; } ReadPasswordJobPrivate::ReadPasswordJobPrivate(const QString &service_, ReadPasswordJob *qq) : JobPrivate(service_, qq) { } JobPrivate::JobPrivate(const QString &service_, Job *qq) : q(qq) , mode( Text ) , error( NoError ) , service( service_ ) , autoDelete( true ) , insecureFallback( false ) { } QString JobPrivate::modeToString(Mode m) { switch (m) { case Text: return QLatin1String("Text"); case Binary: return QLatin1String("Binary"); } Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value"); return QString(); } JobPrivate::Mode JobPrivate::stringToMode(const QString& s) { if (s == QLatin1String("Text") || s == QLatin1String("1")) return Text; if (s == QLatin1String("Binary") || s == QLatin1String("2")) return Binary; qCritical("Unexpected mode string '%s'", qPrintable(s)); return Text; } WritePasswordJobPrivate::WritePasswordJobPrivate(const QString &service_, WritePasswordJob *qq) : JobPrivate(service_, qq) { } qtkeychain-0.10.0/ReadMe.markdown0000777000175000017500000000000013576175767017466 2ReadMe.txtustar hefeehefee