From defc495cf7e08f5568c213569599384d5ac2b9e4 Mon Sep 17 00:00:00 2001 From: Frank Osterfeld Date: Tue, 17 Mar 2015 14:28:21 +0100 Subject: [PATCH] Update qtkeychain Sync with 38cec09f314c93ffd4beab27c3dac70bfcebcd50 from master (post 0.4.0) Change-Id: Ibe66b3330cb4e077be4eb613c36c188cb8b0042d Reviewed-on: https://codereview.kdab.com/19039 Reviewed-by: Continuous Integration Reviewed-by: Guillermo Amaral --- Charm/CMakeLists.txt | 2 +- Charm/Keychain/gnomekeyring.cpp | 71 ++++ Charm/Keychain/gnomekeyring_p.h | 88 +++++ Charm/Keychain/keychain.cpp | 6 +- Charm/Keychain/keychain.h | 3 +- Charm/Keychain/keychain_mac.cpp | 8 +- Charm/Keychain/keychain_p.h | 35 +- .../{keychain_dbus.cpp => keychain_unix.cpp} | 313 +++++++++--------- Charm/Keychain/keychain_win.cpp | 2 +- 9 files changed, 344 insertions(+), 184 deletions(-) create mode 100644 Charm/Keychain/gnomekeyring.cpp create mode 100644 Charm/Keychain/gnomekeyring_p.h rename Charm/Keychain/{keychain_dbus.cpp => keychain_unix.cpp} (66%) diff --git a/Charm/CMakeLists.txt b/Charm/CMakeLists.txt index 420fe458..5e2b8fb3 100644 --- a/Charm/CMakeLists.txt +++ b/Charm/CMakeLists.txt @@ -110,7 +110,7 @@ ELSEIF ( WIN32 ) LIST( APPEND CharmApplication_SRCS Keychain/keychain_win.cpp ) ELSEIF ( UNIX ) IF (HAVE_DBUS) - LIST( APPEND CharmApplication_SRCS Keychain/keychain_dbus.cpp ) + LIST( APPEND CharmApplication_SRCS Keychain/gnomekeyring.cpp Keychain/keychain_unix.cpp ) QT_ADD_DBUS_INTERFACE( CharmApplication_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Keychain/org.kde.KWallet.xml kwallet_interface KWalletInterface ) LIST( APPEND CharmApplication_LIBS ${QT_QTDBUS_LIBRARY} ) ELSE() diff --git a/Charm/Keychain/gnomekeyring.cpp b/Charm/Keychain/gnomekeyring.cpp new file mode 100644 index 00000000..9cef00f6 --- /dev/null +++ b/Charm/Keychain/gnomekeyring.cpp @@ -0,0 +1,71 @@ +#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* 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, static_cast(0) ); +} + +GnomeKeyring::gpointer GnomeKeyring::find_network_password( const gchar* user, const gchar* server, + 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, 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 }, + { 0, static_cast( 0 ) }} + }; + + NETWORK_PASSWORD = &schema; + is_available = reinterpret_cast( resolve( "gnome_keyring_is_available" ) ); + find_password = reinterpret_cast( resolve( "gnome_keyring_find_password" ) ); + store_password = reinterpret_cast( resolve( "gnome_keyring_store_password" ) ); + delete_password = reinterpret_cast( resolve( "gnome_keyring_delete_password" ) ); +} + +GnomeKeyring& GnomeKeyring::instance() { + static GnomeKeyring keyring; + return keyring; +} diff --git a/Charm/Keychain/gnomekeyring_p.h b/Charm/Keychain/gnomekeyring_p.h new file mode 100644 index 00000000..6d150ba2 --- /dev/null +++ b/Charm/Keychain/gnomekeyring_p.h @@ -0,0 +1,88 @@ +#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, 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* password, + OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); + + static gpointer find_network_password( const gchar* user, const gchar* server, + OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ); + + static gpointer delete_network_password( const gchar* user, const gchar* server, + OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ); +private: + GnomeKeyring(); + + static GnomeKeyring& instance(); + + const PasswordSchema* NETWORK_PASSWORD; + typedef gboolean ( is_available_fn )( void ); + typedef gpointer ( store_password_fn )( const PasswordSchema* schema, const gchar* keyring, + const gchar* display_name, const gchar* password, + OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, + ... ); + typedef gpointer ( find_password_fn )( const PasswordSchema* schema, + OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data, + ... ); + typedef gpointer ( delete_password_fn )( const PasswordSchema* schema, + OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data, + ... ); + + is_available_fn* is_available; + find_password_fn* find_password; + store_password_fn* store_password; + delete_password_fn* delete_password; +}; + + +#endif diff --git a/Charm/Keychain/keychain.cpp b/Charm/Keychain/keychain.cpp index 70ea7e05..11a896e7 100644 --- a/Charm/Keychain/keychain.cpp +++ b/Charm/Keychain/keychain.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 * @@ -154,8 +154,10 @@ void DeletePasswordJob::doStart() { //In all current implementations, this deletes the entry so this is sufficient WritePasswordJob* job = new WritePasswordJob( service(), this ); connect( job, SIGNAL(finished(QKeychain::Job*)), d, SLOT(jobFinished(QKeychain::Job*)) ); + job->setInsecureFallback(true); + job->setSettings(settings()); job->setKey( d->key ); - job->start(); + job->doStart(); } QString DeletePasswordJob::key() const { diff --git a/Charm/Keychain/keychain.h b/Charm/Keychain/keychain.h index e2c700a7..3dcd49fd 100644 --- a/Charm/Keychain/keychain.h +++ b/Charm/Keychain/keychain.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 * @@ -115,6 +115,7 @@ class WritePasswordJob : public Job { private: friend class QKeychain::JobExecutor; friend class QKeychain::WritePasswordJobPrivate; + friend class DeletePasswordJob; WritePasswordJobPrivate* const d; }; diff --git a/Charm/Keychain/keychain_mac.cpp b/Charm/Keychain/keychain_mac.cpp index 9753f7b2..156a84e1 100644 --- a/Charm/Keychain/keychain_mac.cpp +++ b/Charm/Keychain/keychain_mac.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 * @@ -28,8 +28,10 @@ static QString strForStatus( OSStatus os ) { const Releaser str( SecCopyErrorMessageString( os, 0 ) ); const char * const buf = CFStringGetCStringPtr( str.value, kCFStringEncodingUTF8 ); if ( !buf ) - return QString(); - return QString::fromUtf8( buf, strlen( 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, diff --git a/Charm/Keychain/keychain_p.h b/Charm/Keychain/keychain_p.h index 83dd2a14..c2ad6c98 100644 --- a/Charm/Keychain/keychain_p.h +++ b/Charm/Keychain/keychain_p.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 * @@ -15,7 +15,7 @@ #include #include -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) #include @@ -35,7 +35,7 @@ class JobExecutor; class JobPrivate : public QObject { Q_OBJECT public: - explicit JobPrivate( const QString& service_ ) + JobPrivate( const QString& service_ ) : error( NoError ) , service( service_ ) , autoDelete( true ) @@ -52,15 +52,7 @@ class JobPrivate : public QObject { class ReadPasswordJobPrivate : public QObject { Q_OBJECT public: - explicit ReadPasswordJobPrivate( ReadPasswordJob* qq ) - : q( qq ) - , walletHandle( 0 ) - , dataType( Text ) -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) - , iface( 0 ) -#endif - { - } + explicit ReadPasswordJobPrivate( ReadPasswordJob* qq ) : q( qq ), walletHandle( 0 ), dataType( Text ) {} void scheduledStart(); ReadPasswordJob* const q; @@ -73,7 +65,7 @@ class ReadPasswordJobPrivate : public QObject { }; DataType dataType; -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) org::kde::KWallet* iface; static void gnomeKeyring_cb( int result, const char* string, ReadPasswordJobPrivate* data ); friend class QKeychain::JobExecutor; @@ -97,14 +89,7 @@ private Q_SLOTS: class WritePasswordJobPrivate : public QObject { Q_OBJECT public: - explicit WritePasswordJobPrivate( WritePasswordJob* qq ) - : q( qq ) - , mode( Delete ) -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) - , iface( 0 ) -#endif - { - } + explicit WritePasswordJobPrivate( WritePasswordJob* qq ) : q( qq ), mode( Delete ) {} void scheduledStart(); enum Mode { @@ -112,23 +97,29 @@ class WritePasswordJobPrivate : public QObject { Text, Binary }; + + static QString modeToString(Mode m); + static Mode stringToMode(const QString& s); + WritePasswordJob* const q; Mode mode; QString key; QByteArray binaryData; QString textData; -#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) org::kde::KWallet* iface; static void gnomeKeyring_cb( int result, WritePasswordJobPrivate* self ); friend class QKeychain::JobExecutor; void fallbackOnError(const QDBusError& err); private Q_SLOTS: + void kwalletWalletFound( QDBusPendingCallWatcher* watcher ); void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ); void kwalletWriteFinished( QDBusPendingCallWatcher* watcher ); #else private Q_SLOTS: + void kwalletWalletFound( QDBusPendingCallWatcher* ) {} void kwalletOpenFinished( QDBusPendingCallWatcher* ) {} void kwalletWriteFinished( QDBusPendingCallWatcher* ) {} #endif diff --git a/Charm/Keychain/keychain_dbus.cpp b/Charm/Keychain/keychain_unix.cpp similarity index 66% rename from Charm/Keychain/keychain_dbus.cpp rename to Charm/Keychain/keychain_unix.cpp index b8be24b0..be2d2753 100644 --- a/Charm/Keychain/keychain_dbus.cpp +++ b/Charm/Keychain/keychain_unix.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 * @@ -7,6 +7,7 @@ * details, check the accompanying file 'COPYING'. * *****************************************************************************/ #include "keychain_p.h" +#include "gnomekeyring_p.h" #include @@ -24,141 +25,88 @@ static QString dataKey( const QString& key ) return QString::fromLatin1( "%1/data" ).arg( key ); } -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 struct { - ItemType item_type; - struct { - const gchar* name; - AttributeType type; - } attributes[32]; - } PasswordSchema; - - typedef void ( *OperationGetStringCallback )( Result result, 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 isSupported() - { - const GnomeKeyring& keyring = instance(); - return keyring.isLoaded() && - keyring.NETWORK_PASSWORD && - keyring.find_password && - keyring.store_password && - keyring.delete_password; - } +enum KeyringBackend { + Backend_GnomeKeyring, + Backend_Kwallet4, + Backend_Kwallet5 +}; - static gpointer store_network_password( const gchar* keyring, const gchar* display_name, - const gchar* user, const gchar* server, const gchar* password, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ) - { - if ( !isSupported() ) - return 0; - return instance().store_password( instance().NETWORK_PASSWORD, - keyring, display_name, password, callback, data, destroy_data, - "user", user, "server", server, static_cast(0) ); - } +enum DesktopEnvironment { + DesktopEnv_Gnome, + DesktopEnv_Kde4, + DesktopEnv_Plasma5, + DesktopEnv_Unity, + DesktopEnv_Xfce, + DesktopEnv_Other +}; - static gpointer find_network_password( const gchar* user, const gchar* server, - OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data ) - { - if ( !isSupported() ) - return 0; - return instance().find_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, static_cast(0) ); - } +// the following detection algorithm is derived from chromium, +// licensed under BSD, see base/nix/xdg_util.cc - static gpointer delete_network_password( const gchar* user, const gchar* server, - OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data ) - { - if ( !isSupported() ) - return 0; - return instance().delete_password( instance().NETWORK_PASSWORD, - callback, data, destroy_data, - "user", user, "server", server, static_cast(0) ); +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; } +} -private: - GnomeKeyring(): QLibrary("gnome-keyring", 0) { - static const PasswordSchema schema = { - ITEM_NETWORK_PASSWORD, - {{ "user", ATTRIBUTE_TYPE_STRING }, - { "server", ATTRIBUTE_TYPE_STRING }, - { 0, static_cast( 0 ) }} - }; - - NETWORK_PASSWORD = &schema; - 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" ) ); +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(); } - static GnomeKeyring& instance() { - static GnomeKeyring keyring; - return keyring; + 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; } - const PasswordSchema* NETWORK_PASSWORD; - 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, - ... ); - find_password_fn* find_password; - store_password_fn* store_password; - delete_password_fn* delete_password; -}; - -const char* GnomeKeyring::GNOME_KEYRING_DEFAULT = NULL; + if ( !qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ) { + return DesktopEnv_Gnome; + } else if ( !qgetenv("KDE_FULL_SESSION").isEmpty() ) { + return getKdeVersion(); + } -enum KeyringBackend { - Backend_GnomeKeyring, - Backend_Kwallet -}; + return DesktopEnv_Other; +} static KeyringBackend detectKeyringBackend() { - if ( !qgetenv( "GNOME_KEYRING_CONTROL" ).isNull() && GnomeKeyring::isSupported() ) - return Backend_GnomeKeyring; - else - return Backend_Kwallet; + 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() @@ -167,6 +115,22 @@ static KeyringBackend getKeyringBackend() 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, priv->tr("D-Bus is not running") ); + priv->fallbackOnError( err ); + } +} + void ReadPasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_GnomeKeyring: @@ -176,20 +140,11 @@ void ReadPasswordJobPrivate::scheduledStart() { q->emitFinishedWithError( OtherError, tr("Unknown error") ); break; - case Backend_Kwallet: - if ( QDBusConnection::sessionBus().isConnected() ) - { - iface = new org::kde::KWallet( QLatin1String("org.kde.kwalletd"), QLatin1String("/modules/kwalletd"), QDBusConnection::sessionBus(), this ); - const QDBusPendingReply reply = iface->networkWallet(); - QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this ); - connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) ); - } - else - { - // D-Bus is not reachable so none can tell us something about KWalletd - QDBusError err( QDBusError::NoServer, tr("D-Bus is not running") ); - fallbackOnError( err ); - } + case Backend_Kwallet4: + kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd", "/modules/kwalletd", this); + break; + case Backend_Kwallet5: + kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd5", "/modules/kwalletd5", this); break; } } @@ -254,6 +209,11 @@ void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err ) if ( q->insecureFallback() && actual->contains( dataKey( key ) ) ) { + const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() ); + if (mode == WritePasswordJobPrivate::Binary) + dataType = Binary; + else + dataType = Text; data = actual->value( dataKey( key ) ).toByteArray(); q->emitFinished(); @@ -271,7 +231,6 @@ void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watch QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); QSettings* actual = q->settings() ? q->settings() : local.data(); - WritePasswordJobPrivate::Mode mode; if ( reply.isError() ) { fallbackOnError( reply.error() ); @@ -283,7 +242,7 @@ void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watch // Do the migration data = actual->value( dataKey( key ) ).toByteArray(); - mode = static_cast(actual->value( typeKey( key ) ).toInt()); + const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() ); actual->remove( key ); q->emitFinished(); @@ -379,6 +338,22 @@ void ReadPasswordJobPrivate::kwalletReadFinished( QDBusPendingCallWatcher* watch q->emitFinished(); } +static void kwalletWritePasswordScheduledStart( const char * service, const char * path, WritePasswordJobPrivate * 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, priv->tr("D-Bus is not running") ); + priv->fallbackOnError( err ); + } +} + void WritePasswordJobPrivate::scheduledStart() { switch ( getKeyringBackend() ) { case Backend_GnomeKeyring: @@ -398,23 +373,44 @@ void WritePasswordJobPrivate::scheduledStart() { } break; - case Backend_Kwallet: - if ( QDBusConnection::sessionBus().isConnected() ) - { - iface = new org::kde::KWallet( QLatin1String("org.kde.kwalletd"), QLatin1String("/modules/kwalletd"), QDBusConnection::sessionBus(), this ); - const QDBusPendingReply reply = iface->open( QLatin1String("kdewallet"), 0, q->service() ); - QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this ); - connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) ); - } - else - { - // D-Bus is not reachable so none can tell us something about KWalletd - QDBusError err( QDBusError::NoServer, tr("D-Bus is not running") ); - fallbackOnError( err ); - } + case Backend_Kwallet4: + kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this); + break; + case Backend_Kwallet5: + kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this); + break; } } +QString WritePasswordJobPrivate::modeToString(Mode m) +{ + switch (m) { + case Delete: + return QLatin1String("Delete"); + case Text: + return QLatin1String("Text"); + case Binary: + return QLatin1String("Binary"); + } + + Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value"); + return QString(); +} + +WritePasswordJobPrivate::Mode WritePasswordJobPrivate::stringToMode(const QString& s) +{ + if (s == QLatin1String("Delete") || s == QLatin1String("0")) + return Delete; + 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; +} + void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err) { QScopedPointer local( !q->settings() ? new QSettings( q->service() ) : 0 ); @@ -433,7 +429,7 @@ void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err) return; } - actual->setValue( QString::fromLatin1( "%1/type" ).arg( key ), int(mode) ); + actual->setValue( QString::fromLatin1( "%1/type" ).arg( key ), mode ); if ( mode == Text ) actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), textData.toUtf8() ); else if ( mode == Binary ) @@ -453,6 +449,15 @@ void WritePasswordJobPrivate::gnomeKeyring_cb( int result, WritePasswordJobPriva } } +void WritePasswordJobPrivate::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*)) ); +} + void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) { watcher->deleteLater(); QDBusPendingReply reply = *watcher; diff --git a/Charm/Keychain/keychain_win.cpp b/Charm/Keychain/keychain_win.cpp index 62ad75ce..24f1ec63 100644 --- a/Charm/Keychain/keychain_win.cpp +++ b/Charm/Keychain/keychain_win.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (C) 2011-2013 Frank Osterfeld * + * Copyright (C) 2011-2014 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 *