pax_global_header00006660000000000000000000000064127205466570014530gustar00rootroot0000000000000052 comment=737df764dfbb90d06a8fe1099800ec9686f6c7e0 qtkeychain-0.7.0/000077500000000000000000000000001272054665700136745ustar00rootroot00000000000000qtkeychain-0.7.0/CMakeLists.txt000066400000000000000000000151211272054665700164340ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8) project(qtkeychain) ### set(QTKEYCHAIN_VERSION 0.7.0) set(QTKEYCHAIN_SOVERSION 1) ### set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules") include(GNUInstallDirs) option(BUILD_WITH_QT4 "Build qtkeychain with Qt4 no matter if Qt5 was found" OFF) if (WIN32) option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) if (USE_CREDENTIAL_STORE) add_definitions(-DUSE_CREDENTIAL_STORE=1) endif() endif() if( NOT BUILD_WITH_QT4 ) # try Qt5 first, and prefer that if found find_package(Qt5Core QUIET) endif() if (Qt5Core_FOUND) set(QTKEYCHAIN_VERSION_INFIX 5) if(UNIX AND NOT APPLE) 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() 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) macro(qt_wrap_cpp) qt5_wrap_cpp(${ARGN}) endmacro() set(QTCORE_LIBRARIES ${Qt5Core_LIBRARIES}) include_directories(${Qt5Core_INCLUDE_DIRS}) if (Qt5_POSITION_INDEPENDENT_CODE) if (CMAKE_VERSION VERSION_LESS 2.8.9) # TODO remove once we increase the cmake requirement set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") else() set(CMAKE_POSITION_INDEPENDENT_CODE ON) 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 ) ADD_DEFINITIONS( -Wall ) if(WIN32) list(APPEND qtkeychain_SOURCES keychain_win.cpp) list(APPEND qtkeychain_LIBRARIES crypt32) #FIXME: mingw bug; otherwise getting undefined refs to RtlSecureZeroMemory there if(MINGW) add_definitions( -O2 ) endif() endif() if(APPLE) list(APPEND qtkeychain_SOURCES keychain_mac.cpp) find_library(COREFOUNDATION_LIBRARY CoreFoundation) list(APPEND qtkeychain_LIBRARIES ${COREFOUNDATION_LIBRARY}) find_library(SECURITY_LIBRARY Security) list(APPEND qtkeychain_LIBRARIES ${SECURITY_LIBRARY}) endif() if(UNIX AND NOT APPLE) list(APPEND qtkeychain_SOURCES keychain_unix.cpp gnomekeyring.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) set(qtkeychain_TR_FILES translations/qtkeychain_de.ts translations/qtkeychain_ro.ts ) file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui) 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}) 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}) set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS QKEYCHAIN_BUILD_QKEYCHAIN_LIB) target_link_libraries(${QTKEYCHAIN_TARGET_NAME} ${qtkeychain_LIBRARIES}) else() add_library(${QTKEYCHAIN_TARGET_NAME} STATIC ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES}) set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS QKEYCHAIN_STATICLIB) endif() 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(FILES keychain.h 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} ) add_executable( testclient testclient.cpp ) target_link_libraries( testclient ${QTKEYCHAIN_TARGET_NAME}) ### ### CMake config file ### configure_file(QtKeychainBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainBuildTreeSettings.cmake" @ONLY) configure_file(QtKeychainConfig.cmake.in "${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake" @ONLY) configure_file(QtKeychainConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" @ONLY) 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.7.0/COPYING000066400000000000000000000022501272054665700147260ustar00rootroot00000000000000Redistribution 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.7.0/ChangeLog000066400000000000000000000022571272054665700154540ustar00rootroot00000000000000ChangeLog ========= 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.7.0/QtKeychainBuildTreeSettings.cmake.in000066400000000000000000000001201272054665700226550ustar00rootroot00000000000000set(QTKEYCHAIN_INCLUDE_DIRS "@PROJECT_SOURCE_DIR@" "@PROJECT_BINARY_DIR@" ) qtkeychain-0.7.0/QtKeychainConfig.cmake.in000066400000000000000000000015321272054665700204720ustar00rootroot00000000000000# - Config file for the QtKeychain package # It defines the following variables # QTKEYCHAIN_INCLUDE_DIRS - include directories for QtKeychain # QTKEYCHAIN_LIBRARIES - libraries to link against # Compute paths get_filename_component(QTKEYCHAIN_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) if(EXISTS "${QTKEYCHAIN_CMAKE_DIR}/CMakeCache.txt") # In build tree include("${QTKEYCHAIN_CMAKE_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainBuildTreeSettings.cmake") else() set(QTKEYCHAIN_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@") endif() # Our library dependencies (contains definitions for IMPORTED targets) include("${QTKEYCHAIN_CMAKE_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainLibraryDepends.cmake") # These are IMPORTED targets created by FooBarLibraryDepends.cmake set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@") set(QTKEYCHAIN_FOUND TRUE) qtkeychain-0.7.0/QtKeychainConfigVersion.cmake.in000066400000000000000000000005761272054665700220470ustar00rootroot00000000000000set(PACKAGE_VERSION "@QTKEYCHAIN_VERSION@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif() qtkeychain-0.7.0/ReadMe.markdown000077700000000000000000000000001272054665700204662ReadMe.txtustar00rootroot00000000000000qtkeychain-0.7.0/ReadMe.txt000066400000000000000000000021211272054665700155660ustar00rootroot00000000000000QtKeychain ========== 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.7.0/cmake/000077500000000000000000000000001272054665700147545ustar00rootroot00000000000000qtkeychain-0.7.0/cmake/Modules/000077500000000000000000000000001272054665700163645ustar00rootroot00000000000000qtkeychain-0.7.0/cmake/Modules/GNUInstallDirs.cmake000066400000000000000000000162661272054665700222030ustar00rootroot00000000000000# - 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.7.0/gnomekeyring.cpp000066400000000000000000000064221272054665700171020ustar00rootroot00000000000000#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("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.7.0/gnomekeyring_p.h000066400000000000000000000066271272054665700170750ustar00rootroot00000000000000#ifndef QTKEYCHAIN_GNOME_P_H #define QTKEYCHAIN_GNOME_P_H #include class GnomeKeyring : private QLibrary { 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.7.0/keychain.cpp000066400000000000000000000127321272054665700162000ustar00rootroot00000000000000/****************************************************************************** * 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) : error( NoError ) , service( service_ ) , autoDelete( true ) , insecureFallback( false ) , q(qq) { } 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.7.0/keychain.h000066400000000000000000000067521272054665700156520ustar00rootroot00000000000000/****************************************************************************** * 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 #include "qkeychain_export.h" #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; class QKEYCHAIN_EXPORT Job : public QObject { Q_OBJECT public: ~Job(); QSettings* settings() const; void setSettings( QSettings* settings ); void start(); QString service() const; Error error() const; QString errorString() const; bool autoDelete() const; void setAutoDelete( bool autoDelete ); bool insecureFallback() const; void setInsecureFallback( bool insecureFallback ); QString key() const; void setKey( const QString& key ); Q_SIGNALS: 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 emitFinished(); void emitFinishedWithError(Error, 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; class QKEYCHAIN_EXPORT ReadPasswordJob : public Job { Q_OBJECT public: explicit ReadPasswordJob( const QString& service, QObject* parent=0 ); ~ReadPasswordJob(); QByteArray binaryData() const; QString textData() const; private: friend class QKeychain::ReadPasswordJobPrivate; }; class WritePasswordJobPrivate; class QKEYCHAIN_EXPORT WritePasswordJob : public Job { Q_OBJECT public: explicit WritePasswordJob( const QString& service, QObject* parent=0 ); ~WritePasswordJob(); void setBinaryData( const QByteArray& data ); void setTextData( const QString& data ); private: friend class QKeychain::WritePasswordJobPrivate; }; class DeletePasswordJobPrivate; class QKEYCHAIN_EXPORT DeletePasswordJob : public Job { Q_OBJECT public: explicit DeletePasswordJob( const QString& service, QObject* parent=0 ); ~DeletePasswordJob(); private: friend class QKeychain::DeletePasswordJobPrivate; }; } // namespace QtKeychain #endif qtkeychain-0.7.0/keychain_mac.cpp000066400000000000000000000134661272054665700170250ustar00rootroot00000000000000/****************************************************************************** * 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( "%1 (OSStatus %2)" ) .arg( "OSX Keychain Error" ).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.7.0/keychain_p.h000066400000000000000000000104641272054665700161640ustar00rootroot00000000000000/****************************************************************************** * 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) #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); Mode mode; #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) 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 *watcher) {} virtual void kwalletFinished( QDBusPendingCallWatcher* watcher ) {} virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {} #endif protected: JobPrivate( const QString& service_, Job *q ); protected: QKeychain::Error error; QString errorString; QString service; bool autoDelete; bool insecureFallback; QPointer settings; QString key; Job* const q; QByteArray data; friend class Job; friend class JobExecutor; friend class ReadPasswordJob; friend class WritePasswordJob; }; 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) 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) 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) 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.7.0/keychain_unix.cpp000066400000000000000000000457611272054665700172530ustar00rootroot00000000000000/****************************************************************************** * 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 #include using namespace QKeychain; static QString typeKey( const QString& key ) { return QString::fromLatin1( "%1/type" ).arg( key ); } static QString dataKey( const QString& key ) { return QString::fromLatin1( "%1/data" ).arg( key ); } enum KeyringBackend { 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() { QString 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(); } 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 KeyringBackend detectKeyringBackend() { switch (detectDesktopEnvironment()) { case DesktopEnv_Kde4: return Backend_Kwallet4; break; case DesktopEnv_Plasma5: return Backend_Kwallet5; break; // fall through case DesktopEnv_Gnome: case DesktopEnv_Unity: case DesktopEnv_Xfce: case DesktopEnv_Other: default: if ( GnomeKeyring::isAvailable() ) { return Backend_GnomeKeyring; } else { return Backend_Kwallet4; } } } 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_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 ) { QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.data(); if ( q->insecureFallback() && actual->contains( dataKey( key ) ) ) { mode = JobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() ); data = actual->value( dataKey( key ) ).toByteArray(); 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; QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.data(); if ( reply.isError() ) { fallbackOnError( reply.error() ); return; } if ( actual->contains( dataKey( key ) ) ) { // We previously stored data in the insecure QSettings, but now have KWallet available. // Do the migration data = actual->value( dataKey( key ) ).toByteArray(); const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() ); actual->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_GnomeKeyring: { QString type; QByteArray password; switch(mode) { case JobPrivate::Text: type = "plaintext"; password = data; break; default: type = "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) { 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->setValue( QString::fromLatin1( "%1/type" ).arg( key ), mode ); actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), data ); actual->sync(); 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; QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.data(); if ( reply.isError() ) { fallbackOnError( reply.error() ); return; } if ( actual->contains( key ) ) { // If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data actual->remove( key ); actual->sync(); } 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_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.7.0/keychain_win.cpp000066400000000000000000000143331272054665700170540ustar00rootroot00000000000000/****************************************************************************** * 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 #include using namespace QKeychain; #if defined(USE_CREDENTIAL_STORE) #include void ReadPasswordJobPrivate::scheduledStart() { LPCWSTR name = (LPCWSTR)key.utf16(); //Use settings member if there, create local settings object if not std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); 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 = L"QtKeychain"; cred.Type = CRED_TYPE_GENERIC; cred.TargetName = name; cred.CredentialBlobSize = data.size(); cred.CredentialBlob = (LPBYTE)pwd; cred.Persist = CRED_PERSIST_LOCAL_MACHINE; if (!CredWriteW(&cred, 0)) { q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available? } else { q->emitFinished(); } } 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() { //Use settings member if there, create local settings object if not std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.get(); QByteArray encrypted = actual->value( key ).toByteArray(); if ( encrypted.isNull() ) { q->emitFinishedWithError( EntryNotFound, tr("Entry not found") ); 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 ); //Use settings member if there, create local settings object if not std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.get(); actual->setValue( key, encrypted ); actual->sync(); if ( actual->status() != QSettings::NoError ) { const QString errorString = actual->status() == QSettings::AccessError ? tr("Could not store encrypted data in settings: access error") : tr("Could not store encrypted data in settings: format error"); q->emitFinishedWithError( OtherError, errorString ); return; } q->emitFinished(); } void DeletePasswordJobPrivate::scheduledStart() { //Use settings member if there, create local settings object if not std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.get(); actual->remove( key ); actual->sync(); if ( actual->status() != QSettings::NoError ) { const QString err = actual->status() == QSettings::AccessError ? tr("Could not delete encrypted data from settings: access error") : tr("Could not delete encrypted data from settings: format error"); q->emitFinishedWithError( OtherError, err ); } else { q->emitFinished(); } } #endif qtkeychain-0.7.0/org.kde.KWallet.xml000066400000000000000000000250121272054665700173110ustar00rootroot00000000000000 qtkeychain-0.7.0/qkeychain_export.h000066400000000000000000000005041272054665700174210ustar00rootroot00000000000000#ifndef QKEYCHAIN_EXPORT_H #define QKEYCHAIN_EXPORT_H #include # ifdef QKEYCHAIN_STATICLIB # undef QKEYCHAIN_SHAREDLIB # define QKEYCHAIN_EXPORT # else # ifdef QKEYCHAIN_BUILD_QKEYCHAIN_LIB # define QKEYCHAIN_EXPORT Q_DECL_EXPORT # else # define QKEYCHAIN_EXPORT Q_DECL_IMPORT # endif # endif #endif qtkeychain-0.7.0/testclient.cpp000066400000000000000000000107731272054665700165660ustar00rootroot00000000000000/****************************************************************************** * 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.7.0/translations/000077500000000000000000000000001272054665700164155ustar00rootroot00000000000000qtkeychain-0.7.0/translations/qtkeychain_de.ts000066400000000000000000000162201272054665700215760ustar00rootroot00000000000000 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.7.0/translations/qtkeychain_ro.ts000066400000000000000000000163021272054665700216270ustar00rootroot00000000000000 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)