[129822] trunk/dports/kde/kdelibs4
nicos at macports.org
nicos at macports.org
Sat Dec 20 23:21:28 PST 2014
Revision: 129822
https://trac.macports.org/changeset/129822
Author: nicos at macports.org
Date: 2014-12-20 23:21:28 -0800 (Sat, 20 Dec 2014)
Log Message:
-----------
kdelibs4: fix osxkeychain variant (ticket #46293)
Modified Paths:
--------------
trunk/dports/kde/kdelibs4/Portfile
Removed Paths:
-------------
trunk/dports/kde/kdelibs4/files/patch-authBackends.diff
Modified: trunk/dports/kde/kdelibs4/Portfile
===================================================================
--- trunk/dports/kde/kdelibs4/Portfile 2014-12-21 05:01:58 UTC (rev 129821)
+++ trunk/dports/kde/kdelibs4/Portfile 2014-12-21 07:21:28 UTC (rev 129822)
@@ -144,7 +144,6 @@
#patch-authBackends: make possible to use OS X keychain through kwallet (see https://git.reviewboard.kde.org/r/119838/, shipped)
variant osxkeychain description {kwallet uses the OSX KeyChain} {
configure.args-append -DMAC_USE_OSXKEYCHAIN:BOOL=ON
- patchfiles-append patch-authBackends.diff
}
variant no_root description {Run the kde cache agent as MacPorts install user.} {
Deleted: trunk/dports/kde/kdelibs4/files/patch-authBackends.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-authBackends.diff 2014-12-21 05:01:58 UTC (rev 129821)
+++ trunk/dports/kde/kdelibs4/files/patch-authBackends.diff 2014-12-21 07:21:28 UTC (rev 129822)
@@ -1,4535 +0,0 @@
-diff -urN kdelibs-4.13.3-orig/kdecore/auth/backends/mac/AuthServicesBackend.cpp kdelibs-4.13.3/kdecore/auth/backends/mac/AuthServicesBackend.cpp
---- kdelibs-4.13.3-orig/kdecore/auth/backends/mac/AuthServicesBackend.cpp 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdecore/auth/backends/mac/AuthServicesBackend.cpp 2014-09-22 19:46:01.000000000 +0900
-@@ -1,5 +1,6 @@
- /*
- * Copyright (C) 2008 Nicola Gigante <nicola.gigante at gmail.com>
-+* Modifications (C) 2014 René Bertin <rjvbertin at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
-@@ -21,6 +22,7 @@
- #include <Security/Security.h>
-
- #include <QtCore/qplugin.h>
-+#include <QtCore/QtCore>
-
- namespace KAuth
- {
-@@ -34,14 +36,35 @@
- if (!s_authRef) {
- AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &s_authRef);
- }
--
- return s_authRef;
- }
-
-+static OSStatus GetActionRights(const QString &action, AuthorizationFlags flags, AuthorizationRef auth=NULL)
-+{
-+ AuthorizationItem item;
-+ item.name = action.toUtf8();
-+ item.valueLength = 0;
-+ item.value = NULL;
-+ item.flags = 0;
-+
-+ AuthorizationRights rights;
-+ rights.count = 1;
-+ rights.items = &item;
-+
-+ OSStatus result = AuthorizationCopyRights( (auth)? auth : authRef(),
-+ &rights,
-+ kAuthorizationEmptyEnvironment,
-+ flags, NULL);
-+ return result;
-+}
-+
-+// On OS X, the suggestion is to make the helper grant the actual privilege. The app does instead a
-+// "pre-authorization", that's equivalent to look at isCallerAuthorized() in policykit.
-+// RJVB: grab the privilege from here, the client.
- AuthServicesBackend::AuthServicesBackend()
- : AuthBackend()
- {
-- setCapabilities(AuthorizeFromHelperCapability | CheckActionExistenceCapability);
-+ setCapabilities(AuthorizeFromClientCapability | CheckActionExistenceCapability);
- }
-
- void AuthServicesBackend::setupAction(const QString&)
-@@ -51,29 +74,24 @@
-
- // On OS X, the suggestion is to make the helper grant the actual privilege. The app does instead a
- // "pre-authorization", that's equivalent to look at isCallerAuthorized() in policykit.
-+// RJVB: grab the privilege from here, the client.
- Action::AuthStatus AuthServicesBackend::authorizeAction(const QString &action)
- {
-- return actionStatus(action);
-+ OSStatus result = GetActionRights( action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed );
-+// qWarning() << "AuthServicesBackend::authorizeAction(" << action << ") AuthorizationCopyRights returned" << result;
-+ switch (result) {
-+ case errAuthorizationSuccess:
-+ return Action::Authorized;
-+ case errAuthorizationInteractionNotAllowed:
-+ default:
-+ return Action::Denied;
-+ }
- }
-
- Action::AuthStatus AuthServicesBackend::actionStatus(const QString &action)
- {
-- AuthorizationItem item;
-- item.name = action.toUtf8();
-- item.valueLength = 0;
-- item.value = NULL;
-- item.flags = 0;
--
-- AuthorizationRights rights;
-- rights.count = 1;
-- rights.items = &item;
--
-- OSStatus result = AuthorizationCopyRights(authRef(),
-- &rights,
-- kAuthorizationEmptyEnvironment,
-- kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize,
-- NULL);
--
-+ OSStatus result = GetActionRights( action, kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize );
-+// qWarning() << "AuthServicesBackend::actionStatus(" << action << ") AuthorizationCopyRights returned" << result;
- switch (result) {
- case errAuthorizationSuccess:
- return Action::Authorized;
-@@ -101,35 +119,28 @@
-
- AuthorizationRef auth;
-
-- if (AuthorizationCreateFromExternalForm(&ext, &auth) != noErr)
-+ if (AuthorizationCreateFromExternalForm(&ext, &auth) != noErr){
-+// qWarning() << "AuthorizationCreateFromExternalForm(" << action << "," << callerID.constData() << ") failed";
- return false;
-+ }
-
-- AuthorizationItem item;
-- item.name = action.toUtf8();
-- item.valueLength = 0;
-- item.value = NULL;
-- item.flags = 0;
--
-- AuthorizationRights rights;
-- rights.count = 1;
-- rights.items = &item;
--
-- OSStatus result = AuthorizationCopyRights(auth,
-- &rights,
-- kAuthorizationEmptyEnvironment,
-- kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed,
-- NULL);
-+ OSStatus result = GetActionRights( action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed,
-+ auth);
-
- AuthorizationFree(auth, kAuthorizationFlagDefaults);
-+// qWarning() << "AuthServicesBackend::isCallerAuthorized(" << action << "," << callerID.constData() << ") AuthorizationCopyRights returned" << result;
-
- return result == errAuthorizationSuccess;
- }
-
-+// RJVB: OS X doesn't distinguish between "action doesn't exist" and "action not allowed". So the
-+// best thing we can do is return true and hope that the action will be created if it didn't exist...
- bool AuthServicesBackend::actionExists(const QString& action)
- {
- OSStatus exists = AuthorizationRightGet(action.toUtf8(), NULL);
-+// qWarning() << "AuthServicesBackend::actionExists(" << action << ") AuthorizationRightGet returned" << exists;
-
-- return exists == errAuthorizationSuccess;
-+ return true;//exists == errAuthorizationSuccess;
- }
-
- }; // namespace KAuth
-diff -urN kdelibs-4.13.3-orig/kdecore/auth/kauthaction.cpp kdelibs-4.13.3/kdecore/auth/kauthaction.cpp
---- kdelibs-4.13.3-orig/kdecore/auth/kauthaction.cpp 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdecore/auth/kauthaction.cpp 2014-09-22 19:46:01.000000000 +0900
-@@ -356,6 +356,13 @@
- return executeActions(QList<Action>() << *this, NULL, helperID) ?
- ActionReply::SuccessReply : ActionReply::AuthorizationDeniedReply;
- } else {
-+#if defined(Q_OS_MACX) || defined(__APPLE__) || defined(__MACH__)
-+ if( BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability ){
-+ // RJVB: authorisation through DBus seems to be flaky (at least when using the OSX keychain ... maybe because DBus
-+ // isn't built with Keychain support in MacPorts?)
-+ return ActionReply::SuccessReply;
-+ }
-+#endif //APPLE
- if (hasHelper()) {
- // Perform the pre auth here
- if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) {
-diff -urN kdelibs-4.13.3-orig/kdeui/CMakeLists.txt kdelibs-4.13.3/kdeui/CMakeLists.txt
---- kdelibs-4.13.3-orig/kdeui/CMakeLists.txt 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/CMakeLists.txt 2014-09-22 19:46:10.000000000 +0900
-@@ -309,11 +309,12 @@
-
- if (Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
- FIND_LIBRARY(SECURITY_LIBRARY Security)
-- set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet_mac.cpp)
-+ set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet_mac.cpp util/qosxkeychain.cpp)
-+ add_definitions(-DMAC_USE_OSXKEYCHAIN)
-+ else(Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-+ set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet.cpp)
- else(Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-- set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet.cpp)
--else(Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-- set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet.cpp)
-+ set(kdeui_LIB_SRCS ${kdeui_LIB_SRCS} util/kwallet.cpp)
- endif(Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-
- if(NOT WINCE)
-diff -urN kdelibs-4.13.3-orig/kdeui/tests/CMakeLists.txt kdelibs-4.13.3/kdeui/tests/CMakeLists.txt
---- kdelibs-4.13.3-orig/kdeui/tests/CMakeLists.txt 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/tests/CMakeLists.txt 2014-09-22 19:46:28.000000000 +0900
-@@ -7,6 +7,7 @@
- # The alternative (which requires Qt>=4.6) is #include <QTestGui>
- add_definitions(-DQT_GUI_LIB)
-
-+option(MAC_USE_OSXKEYCHAIN "On OS X, use the keychain as backend for kwallet, instead of kwalletd.")
-
- MACRO(KDEUI_UNIT_TESTS)
- FOREACH(_testname ${ARGN})
-@@ -154,6 +155,11 @@
- kpixmapsequenceoverlaypaintertest
- )
-
-+if (Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-+ set_source_files_properties(kwallettest.cpp PROPERTIES
-+ COMPILE_FLAGS -DMAC_USE_OSXKEYCHAIN)
-+endif(Q_WS_MAC AND MAC_USE_OSXKEYCHAIN)
-+
- if (NOT KDE_NO_DEPRECATED)
- KDEUI_EXECUTABLE_TESTS(
- keditlistboxtest
-diff -urN kdelibs-4.13.3-orig/kdeui/tests/kwallettest.cpp kdelibs-4.13.3/kdeui/tests/kwallettest.cpp
---- kdelibs-4.13.3-orig/kdeui/tests/kwallettest.cpp 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/tests/kwallettest.cpp 2014-09-22 19:46:28.000000000 +0900
-@@ -32,11 +32,12 @@
-
- void KWalletTest::testWallet()
- {
-- QString testWallet = "kdewallet";
-+ QString testWallet = "kwallettestWallet";
- QString testFolder = "wallettestfolder";
- QString testKeys[] = { "testKey", "account-302948", "\\", "/abc",
- "a at b.c" };
- QByteArray testValues[] = { "test", "@(!§\"%&", "", ".test", "\\" };
-+ QMap<QString,QString> pwmap;
- int numTests = 5;
-
- // Start kdeinit4, so that the wallet damon is started in the background
-@@ -49,15 +50,24 @@
-
- // open
- Wallet *wallet = Wallet::openWallet( testWallet, w->winId(), Wallet::Synchronous );
-- if ( wallet == 0 )
-- kDebug() << "Couldn't open the wallet. Maybe the wallet daemon is not running?";
-+ if ( wallet == 0 ){
-+ kWarning() << "Couldn't open the wallet. Maybe the wallet daemon is not running?";
-+ }
-+ else{
-+ kWarning() << "Opened wallet" << wallet->walletName();
-+ }
- QVERIFY( wallet != 0 );
- QVERIFY( Wallet::isOpen( testWallet ) );
-+ kWarning() << "Wallet list:" << Wallet::walletList();
-+
-+ // check on a couple of existing items, preferably at least 1 "internet account" and 1 "application password"
-+ // OSXKeychain::readEntry( "existing name", "existing account", &value, NULL, NULL )
-
- // create folder
- wallet->createFolder( testFolder );
- QVERIFY( wallet->hasFolder( testFolder ) );
- wallet->setFolder( testFolder );
-+ kWarning() << "Wallet's folder list:" << wallet->folderList();
- QVERIFY( wallet->currentFolder() == testFolder );
- QVERIFY( wallet->folderList().contains( testFolder ) );
-
-@@ -70,10 +80,36 @@
- QVERIFY( readEntry == testValues[i] );
- }
-
-+ pwmap[QString("Bugzilla_login")] = QString("bugs at kde.org");
-+ pwmap[QString("Bugzilla_password")] = QString("buggyPassw0rd");
-+ kWarning() << "pwmap=" << pwmap;
-+
-+ QMap<QString,QString> v;
-+ QVERIFY( !wallet->writeMap( "https://bugs.kde.org/#", pwmap ) );
-+ QVERIFY( wallet->hasEntry("https://bugs.kde.org/#") );
-+ QVERIFY( !wallet->readMap( "https://bugs.kde.org/#", v ) );
-+ QVERIFY( v == pwmap );
-+ // do it again
-+ QVERIFY( !wallet->writeMap( "https://bugs.kde.org/#", pwmap ) );
-+ QVERIFY( wallet->hasEntry("https://bugs.kde.org/#") );
-+ QVERIFY( !wallet->readMap( "https://bugs.kde.org/#", v ) );
-+ QVERIFY( v == pwmap );
-+
-+ QVERIFY( wallet->entryType( testKeys[0] ) == Wallet::Stream );
-+ QVERIFY( wallet->entryType( "https://bugs.kde.org/#" ) == Wallet::Map );
-+
-+ QVERIFY( !wallet->renameEntry( "https://bugs.kde.org/#", "kdeBugs" ) );
-+ QVERIFY( wallet->hasEntry("kdeBugs") );
-+ QVERIFY( !wallet->readMap( "kdeBugs", v ) );
-+ QVERIFY( v == pwmap );
-+
- // close
- wallet->sync();
-- Wallet::closeWallet( "kdewallet", true );
-- QVERIFY( !Wallet::isOpen( "kdewallet" ) );
-+ QStringList l = wallet->entryList();
-+ kWarning() << "Entry list:" << l;
-+ QVERIFY( l.size() == 6 );
-+ Wallet::closeWallet( testWallet, true );
-+ QVERIFY( !Wallet::isOpen( testWallet ) );
-
- // test for key - closed wallet
- for ( int i = 0; i < 5; i++ ) {
-@@ -108,13 +144,21 @@
- QVERIFY( readEntry == testValues[i] );
- }
-
-+ // remove those many test keys
-+ for ( int i = 0; i < numTests; i++ ) {
-+ QVERIFY( !wallet->removeEntry( testKeys[i] ) );
-+ }
-+
-+#ifndef MAC_USE_OSXKEYCHAIN
- // delete folder
- wallet->removeFolder( testFolder );
- QVERIFY( !wallet->hasFolder( testFolder ) );
-+#endif
-
- // close
-- Wallet::closeWallet( "kdewallet", true );
-- QVERIFY( !Wallet::isOpen( "kdewallet" ) );
-+ Wallet::closeWallet( testWallet, true );
-+ QVERIFY( !Wallet::isOpen( testWallet ) );
-+ QVERIFY( !Wallet::deleteWallet( testWallet ) );
- }
-
- QTEST_KDEMAIN(KWalletTest, GUI)
-diff -urN kdelibs-4.13.3-orig/kdeui/util/kwallet_mac.cpp kdelibs-4.13.3/kdeui/util/kwallet_mac.cpp
---- kdelibs-4.13.3-orig/kdeui/util/kwallet_mac.cpp 2014-07-11 15:42:13.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/kwallet_mac.cpp 2014-09-22 19:46:50.000000000 +0900
-@@ -1,8 +1,10 @@
--/* This file is part of the KDE project
-+/* @file kwallet_mac.cpp
-+ * This file is part of the KDE project
- *
- * Copyright (C) 2002-2004 George Staikos <staikos at kde.org>
- * Copyright (C) 2008 Michael Leupold <lemma at confuego.org>
- * Copyright (C) 2010 Frank Osterfeld <osterfeld at kde.org>
-+ * Copyright (C) 2014 René Bertin <rjvbertin at gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
-@@ -26,7 +28,9 @@
- #include <kdeversion.h>
- #include <QtGui/QApplication>
- #include <QtCore/QPointer>
-+#include <QtCore/QSharedMemory>
- #include <QtGui/QWidget>
-+#include <QtCore/QTimer>
- #include <ktoolinvocation.h>
-
- #include <kglobal.h>
-@@ -36,11 +40,13 @@
-
- #include <cassert>
-
--#include <Carbon/Carbon.h>
--#include <Security/Security.h>
--#include <Security/SecKeychain.h>
-+#include <sys/param.h>
-
--using namespace KWallet;
-+#include "qosxkeychain.h"
-+
-+#ifdef USE_KWALLETD
-+# include "kwallet_interface.h"
-+#endif
-
- typedef QMap<QString, QString> StringStringMap;
- Q_DECLARE_METATYPE(StringStringMap)
-@@ -49,30 +55,151 @@
- typedef QMap<QString, QByteArray> StringByteArrayMap;
- Q_DECLARE_METATYPE(StringByteArrayMap)
-
--namespace {
-- template <typename T>
-- struct CFReleaser {
-- explicit CFReleaser( const T& r ) : ref( r ) {}
-- ~CFReleaser() { CFRelease( ref ); }
-- T ref;
-- };
--}
-+#include <mach/mach.h>
-+#include <mach/mach_time.h>
-+#include <mach/mach_init.h>
-+#include <sys/sysctl.h>
-
--static QString asQString( CFStringRef sr ) {
-- return QString::fromLatin1( CFStringGetCStringPtr( sr, NULL ) ); //TODO Latin1 correct?
--}
-+#define IDLETIMER_DEBUG
-
--static QString errorString( OSStatus s ) {
-- const CFReleaser<CFStringRef> ref( SecCopyErrorMessageString( s, NULL ) );
-- return asQString( ref.ref );
-+template <typename T>
-+class QSharedValue : public QSharedMemory
-+{
-+public:
-+ virtual bool attachOrCreate(QSharedMemory::AccessMode mode=QSharedMemory::ReadWrite)
-+ { bool ret = attach(mode);
-+ if( !ret ){
-+ ret = create( sizeof(T), mode );
-+ }
-+ return ret;
-+ }
-+ virtual bool attachOrCreate(QString &key, QSharedMemory::AccessMode mode=QSharedMemory::ReadWrite)
-+ {
-+ setKey(key);
-+ bool ret = attach(mode);
-+ if( !ret ){
-+ ret = create( sizeof(T), mode );
-+ }
-+ return ret;
-+ }
-+ virtual bool attachOrCreate(QString &key, T *initVal, QSharedMemory::AccessMode mode=QSharedMemory::ReadWrite)
-+ {
-+ setKey(key);
-+ bool ret = attach(mode);
-+ if( !ret ){
-+ ret = create( sizeof(T), mode );
-+ if( ret ){
-+ setValue(initVal);
-+ }
-+ }
-+ return ret;
-+ }
-+ virtual bool attachOrCreate(QString &key, T initVal, QSharedMemory::AccessMode mode=QSharedMemory::ReadWrite)
-+ {
-+ return attachOrCreate( key, &initVal, mode );
-+ }
-+ virtual bool getValue(T &val)
-+ {
-+ if( lock() ){
-+ val = *((T*)data());
-+ return unlock();
-+ }
-+ else{
-+ return false;
-+ }
-+ }
-+ virtual bool setValue(T *newVal)
-+ {
-+ if( lock() ){
-+ *((T*)data()) = *newVal;
-+ return unlock();
-+ }
-+ else{
-+ return false;
-+ }
-+ }
-+ virtual bool setValue(T newVal)
-+ {
-+ return setValue(&newVal);
-+ }
-+};
-+
-+static mach_timebase_info_data_t sTimebaseInfo;
-+static double calibrator= 0, startTime = 0;
-+static QSharedValue<double> sharedStartTime;
-+
-+double HRTime_Time()
-+{
-+ return mach_absolute_time() * calibrator - startTime;
- }
-
--static bool isError( OSStatus s, QString* errMsg ) {
-- if ( errMsg )
-- *errMsg = errorString( s );
-- return s != 0;
-+void init_HRTime()
-+{
-+ if( !calibrator ){
-+ mach_timebase_info(&sTimebaseInfo);
-+ /* go from absolute time units to seconds (the timebase is calibrated in nanoseconds): */
-+ calibrator= 1e-9 * sTimebaseInfo.numer / sTimebaseInfo.denom;
-+ QString key = "kwalletWallClockStartTime";
-+ sharedStartTime.attachOrCreate( key, HRTime_Time() );
-+ sharedStartTime.getValue(startTime);
-+ qDebug() << "init_HRTime(): connected to kwalletWallClock at t=" << HRTime_Time();
-+ }
- }
-
-+namespace KWallet
-+{
-+
-+#ifdef USE_KWALLETD
-+class KWalletDLauncher
-+{
-+public:
-+ KWalletDLauncher();
-+ ~KWalletDLauncher();
-+ org::kde::KWallet &getInterface();
-+
-+ org::kde::KWallet *m_wallet;
-+ KConfigGroup m_cgroup;
-+};
-+
-+K_GLOBAL_STATIC(KWalletDLauncher, walletLauncher)
-+static const char s_kwalletdServiceName[] = "org.kde.kwalletd";
-+
-+#else
-+
-+/**
-+ * maps wallet name to a map of app name to <wallet,pid> instances
-+ */
-+// deserialising the WalletUsersList from a QDataStream works only for a few WalletInstancePtr types
-+// We could store the Wallet* in a QByteArray, but that would make it impossible to dump the WalletUsersList
-+// to the console for debugging. So we use a QVariant.
-+typedef QVariant WalletInstancePtr;
-+// typedef QList<QPair<WalletInstancePtr,pid_t> > WalletUsersListEntryData;
-+class WalletUsersListEntryData : public QList<QPair<WalletInstancePtr,pid_t> >
-+{
-+public:
-+ static WalletUsersListEntryData create(QPair<WalletInstancePtr,pid_t> &head)
-+ {
-+ WalletUsersListEntryData self;
-+ self.clear();
-+ self.append(head);
-+ return self;
-+ }
-+ static WalletUsersListEntryData create(QPair<WalletInstancePtr,pid_t> head)
-+ {
-+ WalletUsersListEntryData self;
-+ self.clear();
-+ self.append(head);
-+ return self;
-+ }
-+};
-+
-+typedef QMap<QString,WalletUsersListEntryData> WalletUsersListEntry;
-+typedef QMap<QString,WalletUsersListEntry> WalletUsersList;
-+static WalletUsersList walletUsers;
-+
-+#endif //USE_KWALLETD
-+
-+
- static QString appid()
- {
- KComponentData cData = KGlobal::mainComponent();
-@@ -86,27 +213,8 @@
- return qApp->applicationName();
- }
-
--static OSStatus removeEntryImplementation(const QString& walletName, const QString& key) {
-- const QByteArray serviceName( walletName.toUtf8() );
-- const QByteArray accountName( key.toUtf8() );
-- SecKeychainItemRef itemRef;
-- QString errMsg;
-- OSStatus result = SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, &itemRef );
-- if ( isError( result, &errMsg ) ) {
-- qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
-- return result;
-- }
-- const CFReleaser<SecKeychainItemRef> itemReleaser( itemRef );
-- result = SecKeychainItemDelete( itemRef );
-- if ( isError( result, &errMsg ) ) {
-- qWarning() << "Could not delete password:" << qPrintable(errMsg);
-- return result;
-- }
-- return result;
--}
--
--
--const QString Wallet::LocalWallet() {
-+/*static*/ const QString Wallet::LocalWallet()
-+{
- KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
- if (!cfg.readEntry("Use One Wallet", true)) {
- QString tmp = cfg.readEntry("Local Wallet", "localwallet");
-@@ -123,7 +231,8 @@
- return tmp;
- }
-
--const QString Wallet::NetworkWallet() {
-+/*static*/ const QString Wallet::NetworkWallet()
-+{
- KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
-
- QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
-@@ -133,132 +242,440 @@
- return tmp;
- }
-
--const QString Wallet::PasswordFolder() {
-+/*static*/ const QString Wallet::PasswordFolder()
-+{
- return "Passwords";
- }
-
--const QString Wallet::FormDataFolder() {
-+/*static*/ const QString Wallet::FormDataFolder()
-+{
- return "Form Data";
- }
-
--class Wallet::WalletPrivate
-+static QStringList getUsersFromRegistry(QString &name)
-+{ QString app = appid();
-+ QStringList users;
-+ users.clear();
-+ if( walletUsers.contains(name) ){
-+ WalletUsersListEntry entry = walletUsers[name];
-+ for( WalletUsersListEntry::const_iterator it = entry.constBegin() ; it != entry.constEnd() ; ++it ){
-+ if( !it.value().isEmpty() ){
-+ users.append(it.key());
-+ }
-+ }
-+ }
-+ return users;
-+}
-+
-+static void removeFromRegistry( QString app, QString &name, WalletUsersListEntryData &entries )
-+{
-+ for( WalletUsersListEntryData::const_iterator it = entries.constBegin() ; it != entries.constEnd() ; ++it ){
-+ QPair<WalletInstancePtr,pid_t> wdat = *it;
-+ if( walletUsers.contains(name) && walletUsers[name].contains(app) ){
-+ WalletUsersListEntry entry = walletUsers[name];
-+ WalletUsersListEntryData appInstances = entry[app];
-+ if( appInstances.contains(wdat) ){
-+ appInstances.removeAll(wdat);
-+ qDebug() << "removing application instance" << wdat << "from registry";
-+ }
-+ if( appInstances.isEmpty() ){
-+ entry.remove(app);
-+ qDebug() << "removing application" << app << "from registry";
-+ }
-+ else{
-+ entry[app] = appInstances;
-+ }
-+ if( entry[app].isEmpty() ){
-+ walletUsers.remove(name);
-+ qDebug() << "removing wallet" << name << "from registry";
-+ }
-+ else{
-+ walletUsers[name] = entry;
-+ }
-+ }
-+ }
-+}
-+
-+#pragma mark ==== Wallet::WalletPrivate ====
-+class Wallet::WalletPrivate : public OSXKeychain
- {
- public:
-- explicit WalletPrivate(const QString &n)
-- : name(n)
-- {}
-+ explicit WalletPrivate(Wallet *wallet, const QString &n, int h)
-+ : OSXKeychain(n, &isNew), q(wallet), handle(h)
-+ , idleTimer(NULL), idleTimerTriggered(0), lastConfigCheckTime(-1)
-+ {
-+ isKDEChain = ( n == LocalWallet() || n == NetworkWallet() || n.contains( "wallet", Qt::CaseInsensitive ) );
-+ if( !calibrator ){
-+ init_HRTime();
-+ }
-+ if( isKDEChain ){
-+ if( !lastAccessTime.attachOrCreate( (QString&)n, QSharedMemory::ReadWrite) ){
-+ qDebug() << "Couldn't create shared lastAccessTime member for wallet" << n
-+ << "; idle timeouts will be per-client. Error" << lastAccessTime.errorString();
-+ }
-+ handleIdleTiming(__FUNCTION__);
-+ }
-+ }
-+ virtual ~WalletPrivate()
-+ {
-+ removeFromRegistry();
-+ deleteIdleTimer();
-+ }
-+
-+ void addToRegistry()
-+ { QString app = appid();
-+ QPair<WalletInstancePtr,pid_t> wdat = qMakePair(QVariant((qulonglong)q),getpid());
-+ if( !walletUsers.contains(name) ){
-+ // Unknown wallet name, so there ought not be an existing QMap<appName,walletInstanceList>
-+ WalletUsersListEntryData detail;
-+ detail.clear();
-+ detail.append(wdat);
-+ WalletUsersListEntry entry;
-+ entry.clear();
-+ entry[app] = detail;
-+ walletUsers[name] = entry;
-+ }
-+ else{
-+ WalletUsersListEntry entry = walletUsers[name];
-+ WalletUsersListEntryData detail;
-+ if( entry.contains(app) ){
-+ detail = entry[app];
-+ }
-+ else{
-+ detail.clear();
-+ }
-+ detail.append(wdat);
-+ entry[app] = detail;
-+ walletUsers[name] = entry;
-+ }
-+ QByteArray mapData;
-+ QDataStream ds(&mapData, QIODevice::WriteOnly);
-+ ds << walletUsers;
-+ qDebug() << "@@@" << HRTime_Time() << "Added" << wdat << "for app" << app << "to wallet" << name << "in registry of len=" << mapData.length() << walletUsers;
-+ }
-+
-+ void removeFromRegistry()
-+ {
-+ WalletUsersListEntryData entries = WalletUsersListEntryData::create(qMakePair(QVariant((qulonglong)q),getpid()));
-+ KWallet::removeFromRegistry( appid(), name, entries );
-+ }
-+ QStringList getUsersFromRegistry()
-+ {
-+ return KWallet::getUsersFromRegistry(name);
-+ }
-+
-+ virtual void close()
-+ {
-+// // close the keychain wallet but only if we get here through the kwalletmanager
-+// // or TODO if wallets should be closed when the last client disconnects
-+// // and we are the last client.
-+// if( appid() == "KDE Wallet Manager" ){
-+ deleteIdleTimer();
-+ OSXKeychain::close();
-+// }
-+ }
-+ OSStatus lock()
-+ {
-+ if( idleTimer ){
-+ idleTimer->stop();
-+ }
-+ return Lock(reference());
-+ }
-
-- // needed for compilation reasons
-- void walletServiceUnregistered() {
-+ void walletServiceUnregistered()
-+ {
-+#ifdef USE_KWALLETD
-+ if( handle >= 0 ){
-+ q->slotWalletClosed(handle);
-+ }
-+#endif
- }
-
-- QString name;
-- QString folder;
-+ void deleteIdleTimer()
-+ {
-+ if( idleTimer ){
-+ idleTimer->stop();
-+ idleTimer->deleteLater();
-+ idleTimer = NULL;
-+ }
-+ }
-+ // This function is to be called at every operation that is supposed to launch or reset
-+ // the idle timing.
-+ void handleIdleTiming(const char *caller="", bool touchAccessTime=true)
-+ {
-+ if( !isKDEChain ){
-+ return;
-+ }
-+ double now = HRTime_Time();
-+ if( lastConfigCheckTime < 0 || (now - lastConfigCheckTime >= 10) ){
-+ lastConfigCheckTime = now;
-+ KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
-+ if (cfg.readEntry("Close When Idle", true)) {
-+ timeOut = cfg.readEntry( "Idle Timeout", ((int)0) );
-+ if( caller && idleTimer ){
-+ qDebug() << "###" << caller << "->handleIdleTiming: setting" << idleTimer << "for wallet" << name << "handle" << handle << "timeout to" << timeOut;
-+ }
-+ }
-+ else{
-+ timeOut = -1;
-+ }
-+ }
-+ if( timeOut >= 0 ){
-+ if( !idleTimer ){
-+ idleTimer = new QTimer(0);
-+ connect( idleTimer, SIGNAL(timeout()), this, SLOT(slotIdleTimedOut()), Qt::DirectConnection );
-+ }
-+ else{
-+ idleTimer->stop();
-+ }
-+ // when the idle timer fires, the wallet is supposed to be closed. There is thus
-+ // no reason to use a repeating timer.
-+ idleTimer->setSingleShot(true);
-+ if( touchAccessTime ){
-+ if( !lastAccessTime.setValue(HRTime_Time()) ){
-+ qDebug() << "Cannot set new lastAccessTime for wallet" << name << "error" << lastAccessTime.errorString();
-+ }
-+ }
-+ idleTimer->start( timeOut * 60 * 1000 );
-+ }
-+ else{
-+ timeOut = -1;
-+ deleteIdleTimer();
-+ }
-+ }
-+
-+ void slotIdleTimedOut()
-+ { double lastTime = 0;
-+ // check the last time anyone accessed this wallet:
-+ if( !lastAccessTime.getValue(lastTime) ){
-+ qDebug() << "Cannot get lastAccessTime for wallet" << name << "error" << lastAccessTime.errorString();
-+ }
-+ // the time elapsed since that last access, in minutes:
-+ double elapsed = (HRTime_Time() - lastTime) / 60;
-+ #ifdef IDLETIMER_DEBUG
-+ idleTimerTriggered += 1;
-+ qDebug() << "###" << HRTime_Time() << appid() << "Idle timeout" << timeOut << "min. for" << q << name << "handle" << handle
-+ << "; elapsed minutes=" << elapsed << "timer" << idleTimer << "triggered" << idleTimerTriggered << "times";
-+ #endif //IDLETIMER_DEBUG
-+ if( elapsed >= timeOut ){
-+ // we have a true timeout, i.e. we didn't access the wallet in timeOut minutes, and no one else did either.
-+ q->slotWalletClosed(handle);
-+ }
-+ else{
-+ // false alarm, reset the timer, but there's no need to count this as an access!
-+ handleIdleTiming(__FUNCTION__, false);
-+ }
-+ }
-+
-+public:
-+ Wallet *q;
-+ int handle;
-+ bool isNew;
-+ //! idle timeout in minutes
-+ int timeOut;
-+ QTimer *idleTimer;
-+#ifdef IDLETIMER_DEBUG
-+ size_t idleTimerTriggered;
-+#endif
-+ double lastConfigCheckTime;
-+ QSharedValue<double> lastAccessTime;
- };
-
- Wallet::Wallet(int handle, const QString& name)
-- : QObject(0L), d(new WalletPrivate(name)) {
-- Q_UNUSED(handle);
-+ : QObject(0L), d(new WalletPrivate(this, name, handle))
-+{
-+#ifdef USE_KWALLETD
-+ QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QString::fromLatin1(s_kwalletdServiceName), QDBusConnection::sessionBus(),
-+ QDBusServiceWatcher::WatchForUnregistration, this);
-+ connect(watcher, SIGNAL(serviceUnregistered(QString)),
-+ this, SLOT(walletServiceUnregistered()));
-+
-+ connect(&walletLauncher->getInterface(), SIGNAL(walletClosed(int)), SLOT(slotWalletClosed(int)));
-+ connect(&walletLauncher->getInterface(), SIGNAL(folderListUpdated(QString)), SLOT(slotFolderListUpdated(QString)));
-+ connect(&walletLauncher->getInterface(), SIGNAL(folderUpdated(QString,QString)), SLOT(slotFolderUpdated(QString,QString)));
-+ connect(&walletLauncher->getInterface(), SIGNAL(applicationDisconnected(QString,QString)), SLOT(slotApplicationDisconnected(QString,QString)));
-+#else
-+ d->addToRegistry();
-+#endif // USE_KWALLETD
-+ if( d->handle != handle ){
-+ qDebug() << "Wallet::Wallet(" << name << ") handle changed from" << handle << "to" << d->handle;
-+ }
- }
-
--Wallet::~Wallet() {
-+Wallet::~Wallet()
-+{
- delete d;
- }
-
--
--QStringList Wallet::walletList() {
-+/*static*/ QStringList Wallet::walletList()
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- return walletLauncher->getInterface().wallets();
- #else
-- return QStringList();
-+ // RJVB: Mac OS X's Keychain supports multiple keychains, but they can only be accesses by full path, not
-+ // found by name. That makes it cumbersome to map to multiple wallets when using only the wallet name.
-+ // However, it would be perfectly possible to create OS X Keychains called Wallet::LocalWallet() and
-+ // Wallet::NetworkWallet() in the equivalent of ~/.kde/share/apps/kwallet .
-+ QStringList l;
-+ OSXKeychain::KeychainList(l);
-+ return l;
- #endif
- }
-
-
--void Wallet::changePassword(const QString& name, WId w) {
-+/*static*/ void Wallet::changePassword(const QString& name, WId w)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if( w == 0 )
- kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
- walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
-+#else
-+ Q_UNUSED(w);
-+ kWarning() << "Wallet::changePassword unimplemented '" << name << "'";
- #endif
- }
-
-
--bool Wallet::isEnabled() {
-+/*static*/ bool Wallet::isEnabled()
-+{
- //PENDING(frank) check
- return true;
- }
-
-
--bool Wallet::isOpen(const QString& name) {
-+/*static*/ bool Wallet::isOpen(const QString& name)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- return walletLauncher->getInterface().isOpen(name); // default is false
- #else
-- return true;
-+#ifdef USE_KWALLETD
-+ walletLauncher->getInterface().isOpen(name);
-+#endif // USE_KWALLETD
-+ return OSXKeychain::IsOpen(name);
-+#endif
-+}
-+
-+bool Wallet::isOpen() const
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return d->handle != -1;
-+#else
-+ d->handleIdleTiming(__FUNCTION__);
-+
-+#ifdef USE_KWALLETD
-+ QDBusReply<bool> r = walletLauncher->getInterface().isOpen(d->name);
-+#endif // USE_KWALLETD
-+ return d->isOpen();
- #endif
- }
-
-
--int Wallet::closeWallet(const QString& name, bool force) {
-+/*static*/ int Wallet::closeWallet(const QString& name, bool force)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
- return r.isValid() ? r : -1;
- #else
-- return 0;
-+ Q_UNUSED(force);
-+#ifdef USE_KWALLETD
-+ QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
-+#endif // USE_KWALLETD
-+ // emit a signal that we just closed the wallet
-+ Wallet(0, name).slotWalletClosed(0);
-+ return OSXKeychain::IsOpen(name);
- #endif
- }
-
-
--int Wallet::deleteWallet(const QString& name) {
-+/*static*/ int Wallet::deleteWallet(const QString& name)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
- return r.isValid() ? r : -1;
- #else
-- return -1;
-+ return OSXKeychain::Destroy(name);
- #endif
- }
-
-
--Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot) {
-+/*static*/ Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot)
-+{
- Q_UNUSED(w);
- Q_UNUSED(ot);
-- Wallet *wallet = new Wallet(-1, name);
-- QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
-+ Wallet *wallet = new Wallet((int)w, name);
-+ if( wallet ){
-+#ifdef USE_KWALLETD
-+ // connect the daemon's opened signal to the slot filtering the
-+ // signals we need
-+ connect(&walletLauncher->getInterface(), SIGNAL(walletAsyncOpened(int,int)),
-+ wallet, SLOT(walletAsyncOpened(int,int)));
-+#endif
-+ OSStatus err = wallet->d->unLock();
-+ if( !err && wallet->d->isKDEChain && wallet->d->isNew ){
-+ wallet->d->setLockSettings( false, 0 );
-+ }
-+ kDebug() << "Opened wallet '" << name << "': " << wallet << " error=" << err;
-+#ifdef USE_KWALLETD
-+ wallet->emitWalletOpened();
-+#else
-+ QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
-+#endif
-+ }
- return wallet;
- }
-
-
--bool Wallet::disconnectApplication(const QString& wallet, const QString& app) {
-+/*static*/ bool Wallet::disconnectApplication(const QString& wallet, const QString& app)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
- #else
-- return true;
-+ kWarning() << "Wallet::disconnectApplication unimplemented, '" << app << "' from '" << wallet << "'"
-+#ifdef USE_KWALLETD
-+ << walletLauncher->getInterface().disconnectApplication(wallet, app)
-+#endif // USE_KWALLETD
-+ ;
-+ // app disconnect is done/possible only when the app in question closes its wallet.
-+ return false;
- #endif
- }
-
-
--QStringList Wallet::users(const QString& name) {
-+/*static*/ QStringList Wallet::users(const QString& name)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- return walletLauncher->getInterface().users(name); // default is QStringList()
- #else
-- return QStringList();
-+#ifdef USE_KWALLETD
-+ QStringList ul = walletLauncher->getInterface().users(name);
-+ kWarning() << "Wallet::users unimplemented, '" << name << "'" << ul;
-+ return ul;
-+#else
-+ return KWallet::getUsersFromRegistry((QString&)name);
-+#endif // USE_KWALLETD
- #endif
- }
-
-
--int Wallet::sync() {
-+int Wallet::sync()
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return -1;
- }
-
-- walletLauncher->getInterface().sync(d->handle, appid());
- #endif
-+ d->handleIdleTiming(__FUNCTION__);
-+
-+#ifdef USE_KWALLETD
-+ walletLauncher->getInterface().sync(d->handle, appid());
-+#endif // USE_KWALLETD
- return 0;
- }
-
-
--int Wallet::lockWallet() {
-+int Wallet::lockWallet()
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return -1;
-@@ -271,26 +688,25 @@
- if (r.isValid()) {
- return r;
- }
-+#else
-+ d->currentService.clear();
-+ d->handle = -1;
- #endif
-- return -1;
-+ d->lock();
-+ emit walletClosed();
-+ return 1;
- }
-
-
--const QString& Wallet::walletName() const {
-+const QString& Wallet::walletName() const
-+{
-+ d->handleIdleTiming(__FUNCTION__);
- return d->name;
- }
-
-
--bool Wallet::isOpen() const {
--#ifdef OSX_KEYCHAIN_PORT_DISABLED
-- return d->handle != -1;
--#else
-- return true;
--#endif
--}
--
--
--void Wallet::requestChangePassword(WId w) {
-+void Wallet::requestChangePassword(WId w)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if( w == 0 )
- kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
-@@ -299,11 +715,16 @@
- }
-
- walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
-+#else
-+ Q_UNUSED(w);
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::requestChangePassword unimplemented '" << d->name << "'";
- #endif
- }
-
-
--void Wallet::slotWalletClosed(int handle) {
-+void Wallet::slotWalletClosed(int handle)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == handle) {
- d->handle = -1;
-@@ -311,11 +732,25 @@
- d->name.clear();
- emit walletClosed();
- }
-+#else
-+// kWarning() << "Wallet::slotWalletClosed unimplemented '" << d->name << "'";
-+ if( d->handle == handle ){
-+ d->handle = -1;
-+ d->currentService.clear();
-+ kDebug() << "Wallet::slotWalletClosed '" << d->name << "'";
-+ // TODO remove ourselves from the WalletUsersList here!
-+ d->close();
-+ emit walletClosed();
-+ }
-+ else{
-+ qDebug() << "Wallet::slotWalletClosed '" << d->name << "' ignored because handle" << d->handle << "!=" << handle;
-+ }
- #endif
- }
-
-
--QStringList Wallet::folderList() {
-+QStringList Wallet::folderList()
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return QStringList();
-@@ -324,12 +759,14 @@
- QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
- return r;
- #else
-- return QStringList();
-+ d->handleIdleTiming(__FUNCTION__);
-+ return QStringList(d->folderList());
- #endif
- }
-
-
--QStringList Wallet::entryList() {
-+QStringList Wallet::entryList()
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return QStringList();
-@@ -338,12 +775,17 @@
- QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
- return r;
- #else
-- return QStringList();
-+ d->handleIdleTiming(__FUNCTION__);
-+
-+ QStringList r = QStringList();
-+ d->itemList(r);
-+ return r;
- #endif
- }
-
-
--bool Wallet::hasFolder(const QString& f) {
-+bool Wallet::hasFolder(const QString& f)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return false;
-@@ -352,12 +794,15 @@
- QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
- return r; // default is false
- #else
-- return true;
-+ d->handleIdleTiming(__FUNCTION__);
-+ d->folderList();
-+ return d->serviceList.contains(f);
- #endif
- }
-
-
--bool Wallet::createFolder(const QString& f) {
-+bool Wallet::createFolder(const QString& f)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return false;
-@@ -370,12 +815,14 @@
-
- return true; // folder already exists
- #else
-- return true;
-+ d->handleIdleTiming(__FUNCTION__);
-+ return setFolder(f);
- #endif
- }
-
-
--bool Wallet::setFolder(const QString& f) {
-+bool Wallet::setFolder(const QString &f)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- bool rc = false;
-
-@@ -397,12 +844,22 @@
-
- return rc;
- #else
-+ d->handleIdleTiming(__FUNCTION__);
-+ // act as if we just changed folders even if we have no such things; the property
-+ // is stored as the ServiceItemAttr (which shows up as the "Where" field in the Keychain Utility).
-+ if( f.size() == 0 ){
-+ d->currentService.clear();
-+ }
-+ else{
-+ d->currentService = QString(f);
-+ }
- return true;
- #endif
- }
-
-
--bool Wallet::removeFolder(const QString& f) {
-+bool Wallet::removeFolder(const QString& f)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- if (d->handle == -1) {
- return false;
-@@ -415,34 +872,38 @@
-
- return r; // default is false
- #else
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::removeFolder unimplemented (returns true) '" << d->name << "'";
-+ if( d->currentService == f ){
-+ d->currentService.clear();
-+ }
- return true;
- #endif
- }
-
-
--const QString& Wallet::currentFolder() const {
-+const QString& Wallet::currentFolder() const
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
- return d->folder;
-+#else
-+ d->handleIdleTiming(__FUNCTION__);
-+ return d->currentService;
-+#endif
- }
-
-
--int Wallet::readEntry(const QString& key, QByteArray& value) {
-- const QByteArray serviceName( walletName().toUtf8() );
-- const QByteArray accountName( key.toUtf8() );
-- UInt32 passwordSize = 0;
-- void* passwordData = 0;
-- QString errMsg;
-- if ( isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), &passwordSize, &passwordData, NULL ), &errMsg ) ) {
-- qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
-- return -1;
-- }
--
-- value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
-- SecKeychainItemFreeContent( NULL, passwordData );
-- return 0;
-+int Wallet::readEntry(const QString &key, QByteArray &value)
-+{ OSStatus err;
-+ d->handleIdleTiming(__FUNCTION__);
-+ err = d->readItem( key, &value, NULL );
-+ kDebug() << "Wallet::readEntry '" << key << "' from wallet " << d->name << ", error=" << ((err)? -1 : 0);
-+ return (err)? -1 : 0;
- }
-
-
--int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value) {
-+int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- registerTypes();
-
-@@ -464,12 +925,17 @@
-
- return rc;
- #else
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::readEntryList unimplemented (returns -1) '" << d->name << "'";
- return -1;
- #endif
- }
-
-
--int Wallet::renameEntry(const QString& oldName, const QString& newName) {
-+int Wallet::renameEntry(const QString& oldName, const QString& newName)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- int rc = -1;
-
-@@ -484,25 +950,33 @@
-
- return rc;
- #else
-- return -1;
-+ d->handleIdleTiming(__FUNCTION__);
-+ return d->renameItem( oldName, newName );
- #endif
- }
-
-
--int Wallet::readMap(const QString& key, QMap<QString,QString>& value) {
-+int Wallet::readMap(const QString &key, QMap<QString,QString> &value)
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-+
- QByteArray v;
-- const int ret = readEntry( key, v );
-- if ( ret != 0 )
-+ const int ret = (d->readItem( key, &v, NULL ))? -1 : 0;
-+ if( ret != 0 ){
- return ret;
-- if ( !v.isEmpty() ) {
-- QDataStream ds( &v, QIODevice::ReadOnly );
-+ }
-+ if( !v.isEmpty() ){
-+ QByteArray w = QByteArray::fromBase64(v);
-+ QDataStream ds( &w, QIODevice::ReadOnly );
- ds >> value;
- }
-+ kDebug() << "Wallet::readMap '" << key << "' from wallet " << d->name << ", error=0";
- return 0;
- }
-
-
--int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value) {
-+int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- registerTypes();
-
-@@ -530,81 +1004,119 @@
-
- return rc;
- #else
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::readMapList unimplemented (returns -1) '" << d->name << "'";
- return -1;
- #endif
- }
-
-
--int Wallet::readPassword(const QString& key, QString& value) {
-+int Wallet::readPassword(const QString& key, QString& value)
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-+
- QByteArray ba;
-- const int ret = readEntry( key, ba );
-- if ( ret == 0 )
-+ const int ret = (d->readItem( key, &ba, NULL ))? -1 : 0;
-+ if ( ret == 0 ){
- value = QString::fromUtf8( ba.constData() );
-+ }
-+ kDebug() << "Wallet::readPassword '" << key << "' from wallet " << d->name << ", error=" << ret;
- return ret;
- }
-
-
--int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value) {
-+int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value)
-+{
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::readPasswordList unimplemented (returns -1) '" << d->name << "'";
- return -1;
- }
-
--static OSStatus writeEntryImplementation( const QString& walletName, const QString& key, const QByteArray& value ) {
-- const QByteArray serviceName( walletName.toUtf8() );
-- const QByteArray accountName( key.toUtf8() );
-- QString errMsg;
-- OSStatus err = SecKeychainAddGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), value.size(), value.constData(), NULL );
-- if (err == errSecDuplicateItem) {
-- err = removeEntryImplementation( walletName, key );
-- if ( isError( err, &errMsg ) ) {
-- kWarning() << "Could not delete old key in keychain for replacing: " << qPrintable(errMsg);
-- return err;
-- }
-- }
-- if ( isError( err, &errMsg ) ) {
-- kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
-- return err;
-- }
-- kDebug() << "Succesfully written out key:" << key;
-- return err;
--
--}
--
--int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType) {
-- Q_UNUSED( entryType )
-- return writeEntryImplementation( walletName(), key, password );
-+int Wallet::writeEntry(const QString& key, const QByteArray& password )
-+{ int ret;
-+ d->handleIdleTiming(__FUNCTION__);
-+ ret = d->writeItem( key, password );
-+ kDebug() << "wrote entry '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
- }
-
-+int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType)
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-
--int Wallet::writeEntry(const QString& key, const QByteArray& value) {
-- return writeEntryImplementation( walletName(), key, value );
-+ OSXKeychain::EntryType entryCode;
-+ switch( entryType ){
-+ case Wallet::Password:
-+ entryCode = OSXKeychain::Password;
-+ break;
-+ case Wallet::Map:
-+ entryCode = OSXKeychain::Map;
-+ break;
-+ case Wallet::Stream:
-+ entryCode = OSXKeychain::Stream;
-+ break;
-+ default:
-+ entryCode = OSXKeychain::Unknown;
-+ break;
-+ }
-+ int ret = d->writeItem( key, password, &entryCode );
-+ kDebug() << "wrote entry '" << key << "' of type=" << (int) entryType << "to wallet " << d->name << ", error=" << ret;
-+ return ret;
- }
-
-+int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value)
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-
--int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value) {
- QByteArray mapData;
- QDataStream ds(&mapData, QIODevice::WriteOnly);
- ds << value;
-- return writeEntry( key, mapData );
-+ OSXKeychain::EntryType etype = OSXKeychain::Map;
-+ int ret = d->writeItem( key, mapData.toBase64(),
-+ "This is a KDE Wallet::Map item. Its password\n"
-+ "cannot be read in the OS X Keychain Utility.\n"
-+ "Use KDE's own kwalletmanager for that.", &etype );
-+ kDebug() << "wrote map '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
- }
-
-
--int Wallet::writePassword(const QString& key, const QString& value) {
-- return writeEntry( key, value.toUtf8() );
-+int Wallet::writePassword(const QString &key, const QString& value)
-+{ OSXKeychain::EntryType etype;
-+
-+ d->handleIdleTiming(__FUNCTION__);
-+ etype = OSXKeychain::Password;
-+ int ret = d->writeItem( key, value.toUtf8(), &etype );
-+ kDebug() << "wrote password '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
- }
-
-
--bool Wallet::hasEntry(const QString& key) {
-- const QByteArray serviceName( walletName().toUtf8() );
-- const QByteArray accountName( key.toUtf8() );
-- return !isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, NULL ), 0 );
-+bool Wallet::hasEntry(const QString &key)
-+{ bool ret;
-+
-+ d->handleIdleTiming(__FUNCTION__);
-+ ret = d->hasItem( key, NULL );
-+ kDebug() << "wallet '" << d->name << "'" << ((ret)? " has" : " does not have") << " entry '" << key << "'";
-+ return ret;
- }
-
--int Wallet::removeEntry(const QString& key) {
-- return removeEntryImplementation( walletName(), key );
-+int Wallet::removeEntry(const QString& key)
-+{ int ret;
-+
-+ d->handleIdleTiming(__FUNCTION__);
-+ ret = d->removeItem( key );
-+ kDebug() << "removed entry '" << key << "' from wallet " << d->name << ", error=" << ret;
-+ return ret;
- }
-
-
--Wallet::EntryType Wallet::entryType(const QString& key) {
-+Wallet::EntryType Wallet::entryType(const QString& key)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- int rc = 0;
-
-@@ -619,94 +1131,208 @@
-
- return static_cast<EntryType>(rc);
- #else
-+ d->handleIdleTiming(NULL);
-+
-+ // RJVB: a priori, entries are always 'password' on OS X, but since we also do use them for storing
-+ // maps, it may be best to return Wallet::Unknown to leave some uncertainty and not mislead our caller.
-+ OSXKeychain::EntryType etype;
-+ if( !d->itemType( key, &etype ) ){
-+ switch( etype ){
-+ case OSXKeychain::Password:
-+ return Wallet::Password;
-+ break;
-+ case OSXKeychain::Map:
-+ return Wallet::Map;
-+ break;
-+ case OSXKeychain::Stream:
-+ return Wallet::Stream;
-+ break;
-+ }
-+ }
- return Wallet::Unknown;
- #endif
- }
-
-
--void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder) {
-+void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder)
-+{
- if (d->name == wallet) {
-+ kDebug() << "emit folderUpdated" << folder;
- emit folderUpdated(folder);
- }
- }
-
-
--void Wallet::slotFolderListUpdated(const QString& wallet) {
-+void Wallet::slotFolderListUpdated(const QString& wallet)
-+{
- if (d->name == wallet) {
-+ kDebug() << "emit foldeListrUpdated" << wallet;
- emit folderListUpdated();
- }
- }
-
-
--void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application) {
--#ifdef OSX_KEYCHAIN_PORT_DISABLED
-- if (d->handle >= 0
-+void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application)
-+{
-+#ifdef USE_KWALLETD
-+ qDebug() << "slotApplicationDisconnected(" << wallet << "," << application << "); handle="
-+ << d->handle << "name=" << d->name << "appid=" << appid();
-+ if( d->handle >= 0
- && d->name == wallet
-- && application == appid()) {
-+ && application == appid()
-+ ){
- slotWalletClosed(d->handle);
- }
--#endif
-+#else
-+ Q_UNUSED(wallet);
-+ Q_UNUSED(application);
-+#endif //USE_KWALLETD
- }
-
--void Wallet::walletAsyncOpened(int tId, int handle) {
-+void Wallet::walletAsyncOpened(int tId, int handle)
-+{
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- // ignore responses to calls other than ours
- if (d->transactionId != tId || d->handle != -1) {
- return;
- }
--
-+
- // disconnect the async signal
- disconnect(this, SLOT(walletAsyncOpened(int,int)));
--
-+
- d->handle = handle;
- emit walletOpened(handle > 0);
-+#else
-+ Q_UNUSED(tId);
-+ d->handleIdleTiming(__FUNCTION__);
-+#ifdef USE_KWALLETD
-+ // disconnect the async signal
-+ disconnect(this, SLOT(walletAsyncOpened(int,int)));
-+ qDebug() << "walletAsyncOpened: emit walletOpened(true), handle=" << handle;
-+ emit walletOpened(true);
-+#endif // USE_KWALLETD
-+ d->handle = handle;
- #endif
- }
-
--void Wallet::emitWalletAsyncOpenError() {
-+void Wallet::emitWalletAsyncOpenError()
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-+ kDebug() << "emitWalletAsyncOpenError: emit walletOpened(false)";
- emit walletOpened(false);
- }
-
--void Wallet::emitWalletOpened() {
-- emit walletOpened(true);
-+void Wallet::emitWalletOpened()
-+{
-+ d->handleIdleTiming(__FUNCTION__);
-+ kDebug() << "emitWalletOpened: emit walletOpened(true)";
-+ emit walletOpened(true);
- }
-
-
--bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
-+/*static*/ bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
- {
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
- return r;
- #else
-- return false;
-+ bool ret = true;
-+ if( Wallet::walletList().contains(wallet) ){
-+ ret = !Wallet(-1, wallet).hasFolder(folder);
-+ }
-+ return ret;
- #endif
- }
-
-
--bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
-+/*static*/ bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
- {
- #ifdef OSX_KEYCHAIN_PORT_DISABLED
- QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
- return r;
- #else
-- return false;
-+ bool ret = true;
-+ if( Wallet::walletList().contains(wallet) ){
-+ Wallet w(-1, wallet);
-+ if( w.hasFolder(folder) ){
-+ ret = !w.hasEntry(key);
-+ }
-+ }
-+ return ret;
- #endif
- }
-
- void Wallet::slotCollectionStatusChanged(int status)
- {
-+ Q_UNUSED(status);
-+ d->handleIdleTiming(__FUNCTION__);
-+ kWarning() << "Wallet::slotCollectionStatusChanged unimplemented '" << d->name << "' status=" << status;
- }
-
- void Wallet::slotCollectionDeleted()
- {
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
- d->folder.clear();
-- d->name.clear();
-+#else
-+ d->currentService.clear();
-+#endif
-+ kDebug() << "Wallet::slotCollectionDeleted: closing private data '" << d->name;
-+ // TODO remove ourselves from the WalletUsersList here!
-+ d->close();
- emit walletClosed();
- }
-
-
--void Wallet::virtual_hook(int, void*) {
-+void Wallet::virtual_hook(int, void*)
-+{
- //BASE::virtual_hook( id, data );
- }
-
-+#ifdef USE_KWALLETD
-+KWalletDLauncher::KWalletDLauncher()
-+ : m_wallet(0),
-+ m_cgroup(KSharedConfig::openConfig("kwalletrc", KConfig::NoGlobals)->group("Wallet"))
-+{
-+ m_wallet = new org::kde::KWallet(QString::fromLatin1(s_kwalletdServiceName), "/modules/kwalletd", QDBusConnection::sessionBus());
-+}
-+
-+KWalletDLauncher::~KWalletDLauncher()
-+{
-+ delete m_wallet;
-+}
-+
-+org::kde::KWallet &KWalletDLauncher::getInterface()
-+{
-+ Q_ASSERT(m_wallet != 0);
-+
-+ // check if kwalletd is already running
-+ if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName)))
-+ {
-+ // not running! check if it is enabled.
-+ bool walletEnabled = m_cgroup.readEntry("Enabled", true);
-+ if (walletEnabled) {
-+ // wallet is enabled! try launching it
-+ QString error;
-+ int ret = KToolInvocation::startServiceByDesktopPath("kwalletd.desktop", QStringList(), &error);
-+ if (ret > 0){
-+ kError(285) << "Couldn't start kwalletd: " << error << endl;
-+ }
-+
-+ if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1(s_kwalletdServiceName))) {
-+ kDebug(285) << "The kwalletd service is still not registered";
-+ } else {
-+ kDebug(285) << "The kwalletd service has been registered";
-+ }
-+ } else {
-+ kError(285) << "The kwalletd service has been disabled";
-+ }
-+ }
-+
-+ return *m_wallet;
-+}
-+#endif //USE_KWALLETD
-+
-+} // namespace KWallet
-+
-+#include "qosxkeychain.moc"
- #include "kwallet.moc"
-diff -urN kdelibs-4.13.3-orig/kdeui/util/kwallet_mac.cpp.orig kdelibs-4.13.3/kdeui/util/kwallet_mac.cpp.orig
---- kdelibs-4.13.3-orig/kdeui/util/kwallet_mac.cpp.orig 1970-01-01 09:00:00.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/kwallet_mac.cpp.orig 2014-09-22 19:46:10.000000000 +0900
-@@ -0,0 +1,809 @@
-+/* @file kwallet_mac.cpp
-+ * This file is part of the KDE project
-+ *
-+ * Copyright (C) 2002-2004 George Staikos <staikos at kde.org>
-+ * Copyright (C) 2008 Michael Leupold <lemma at confuego.org>
-+ * Copyright (C) 2010 Frank Osterfeld <osterfeld at kde.org>
-+ * Copyright (C) 2014 René Bertin <rjvbertin at gmail.com>
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Library General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Library General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Library General Public License
-+ * along with this library; see the file COPYING.LIB. If not, write to
-+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ * Boston, MA 02110-1301, USA.
-+ */
-+
-+#include "kwallet.h"
-+#include <ksharedconfig.h>
-+#include <kdebug.h>
-+#include <kdeversion.h>
-+#include <QtGui/QApplication>
-+#include <QtCore/QPointer>
-+#include <QtGui/QWidget>
-+#include <ktoolinvocation.h>
-+
-+#include <kglobal.h>
-+#include <kcomponentdata.h>
-+#include <kaboutdata.h>
-+#include <kconfiggroup.h>
-+
-+#include <cassert>
-+
-+#include <sys/param.h>
-+
-+#include "qosxkeychain.h"
-+
-+using namespace KWallet;
-+
-+typedef QMap<QString, QString> StringStringMap;
-+Q_DECLARE_METATYPE(StringStringMap)
-+typedef QMap<QString, StringStringMap> StringToStringStringMapMap;
-+Q_DECLARE_METATYPE(StringToStringStringMapMap)
-+typedef QMap<QString, QByteArray> StringByteArrayMap;
-+Q_DECLARE_METATYPE(StringByteArrayMap)
-+
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+static QString appid()
-+{
-+ KComponentData cData = KGlobal::mainComponent();
-+ if (cData.isValid()) {
-+ const KAboutData* aboutData = cData.aboutData();
-+ if (aboutData) {
-+ return aboutData->programName();
-+ }
-+ return cData.componentName();
-+ }
-+ return qApp->applicationName();
-+}
-+#endif
-+
-+/*static*/ const QString Wallet::LocalWallet()
-+{
-+ KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
-+ if (!cfg.readEntry("Use One Wallet", true)) {
-+ QString tmp = cfg.readEntry("Local Wallet", "localwallet");
-+ if (tmp.isEmpty()) {
-+ return "localwallet";
-+ }
-+ return tmp;
-+ }
-+
-+ QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
-+ if (tmp.isEmpty()) {
-+ return "kdewallet";
-+ }
-+ return tmp;
-+}
-+
-+/*static*/ const QString Wallet::NetworkWallet()
-+{
-+ KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
-+
-+ QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
-+ if (tmp.isEmpty()) {
-+ return "kdewallet";
-+ }
-+ return tmp;
-+}
-+
-+/*static*/ const QString Wallet::PasswordFolder()
-+{
-+ return "Passwords";
-+}
-+
-+/*static*/ const QString Wallet::FormDataFolder()
-+{
-+ return "Form Data";
-+}
-+
-+#pragma mark ==== Wallet::WalletPrivate ====
-+class Wallet::WalletPrivate : public OSXKeychain
-+{
-+public:
-+ explicit WalletPrivate(const QString &n)
-+ : OSXKeychain(n)
-+ {
-+ isKDEChain = ( n == LocalWallet() || n == NetworkWallet() || n.contains( "wallet", Qt::CaseInsensitive ) );
-+ }
-+
-+ // needed for compilation reasons
-+ void walletServiceUnregistered()
-+ {
-+ }
-+};
-+
-+Wallet::Wallet(int handle, const QString& name)
-+ : QObject(0L), d(new WalletPrivate(name))
-+{
-+ Q_UNUSED(handle);
-+}
-+
-+Wallet::~Wallet()
-+{
-+ delete d;
-+}
-+
-+/*static*/ QStringList Wallet::walletList()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return walletLauncher->getInterface().wallets();
-+#else
-+ // RJVB: Mac OS X's Keychain supports multiple keychains, but they can only be accesses by full path, not
-+ // found by name. That makes it cumbersome to map to multiple wallets when using only the wallet name.
-+ // However, it would be perfectly possible to create OS X Keychains called Wallet::LocalWallet() and
-+ // Wallet::NetworkWallet() in the equivalent of ~/.kde/share/apps/kwallet .
-+ QStringList l;
-+ OSXKeychain::KeychainList(l);
-+ return l;
-+#endif
-+}
-+
-+
-+/*static*/ void Wallet::changePassword(const QString& name, WId w)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if( w == 0 )
-+ kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
-+ walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
-+#else
-+ Q_UNUSED(w);
-+ kWarning() << "Wallet::changePassword unimplemented '" << name << "'";
-+#endif
-+}
-+
-+
-+/*static*/ bool Wallet::isEnabled()
-+{
-+ //PENDING(frank) check
-+ return true;
-+}
-+
-+
-+/*static*/ bool Wallet::isOpen(const QString& name)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return walletLauncher->getInterface().isOpen(name); // default is false
-+#else
-+ return OSXKeychain::IsOpen(name);
-+#endif
-+}
-+
-+bool Wallet::isOpen() const
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return d->handle != -1;
-+#else
-+ return d->isOpen();
-+#endif
-+}
-+
-+
-+/*static*/ int Wallet::closeWallet(const QString& name, bool force)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
-+ return r.isValid() ? r : -1;
-+#else
-+ Q_UNUSED(force);
-+ return OSXKeychain::Lock(name);
-+#endif
-+}
-+
-+
-+/*static*/ int Wallet::deleteWallet(const QString& name)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
-+ return r.isValid() ? r : -1;
-+#else
-+ return OSXKeychain::Destroy(name);
-+#endif
-+}
-+
-+
-+/*static*/ Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot)
-+{
-+ Q_UNUSED(w);
-+ Q_UNUSED(ot);
-+ Wallet *wallet = new Wallet(-1, name);
-+ QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
-+ OSStatus err = wallet->d->unLock();
-+ kDebug() << "Opened wallet '" << name << "': " << wallet << " error=" << err;
-+ return wallet;
-+}
-+
-+
-+/*static*/ bool Wallet::disconnectApplication(const QString& wallet, const QString& app)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
-+#else
-+ kWarning() << "Wallet::disconnectApplication unimplemented, '" << app << "' from '" << wallet << "'";
-+ return true;
-+#endif
-+}
-+
-+
-+/*static*/ QStringList Wallet::users(const QString& name)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return walletLauncher->getInterface().users(name); // default is QStringList()
-+#else
-+ kWarning() << "Wallet::users unimplemented, '" << name << "'";
-+ return QStringList();
-+#endif
-+}
-+
-+
-+int Wallet::sync()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return -1;
-+ }
-+
-+ walletLauncher->getInterface().sync(d->handle, appid());
-+#endif
-+ return 0;
-+}
-+
-+
-+int Wallet::lockWallet()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return -1;
-+ }
-+
-+ QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
-+ d->handle = -1;
-+ d->folder.clear();
-+ d->name.clear();
-+ if (r.isValid()) {
-+ return r;
-+ }
-+#else
-+ d->currentService.clear();
-+#endif
-+ return d->lock();
-+}
-+
-+
-+const QString& Wallet::walletName() const
-+{
-+ return d->name;
-+}
-+
-+
-+void Wallet::requestChangePassword(WId w)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if( w == 0 )
-+ kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
-+ if (d->handle == -1) {
-+ return;
-+ }
-+
-+ walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
-+#else
-+ Q_UNUSED(w);
-+ kWarning() << "Wallet::requestChangePassword unimplemented '" << d->name << "'";
-+#endif
-+}
-+
-+
-+void Wallet::slotWalletClosed(int handle)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == handle) {
-+ d->handle = -1;
-+ d->folder.clear();
-+ d->name.clear();
-+ emit walletClosed();
-+ }
-+#else
-+ Q_UNUSED(handle);
-+ kWarning() << "Wallet::slotWalletClosed unimplemented '" << d->name << "'";
-+ d->currentService.clear();
-+#endif
-+}
-+
-+
-+QStringList Wallet::folderList()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return QStringList();
-+ }
-+
-+ QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
-+ return r;
-+#else
-+ return QStringList(d->folderList());
-+#endif
-+}
-+
-+
-+QStringList Wallet::entryList()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return QStringList();
-+ }
-+
-+ QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
-+ return r;
-+#else
-+ QStringList r = QStringList();
-+ d->itemList(r);
-+ return r;
-+#endif
-+}
-+
-+
-+bool Wallet::hasFolder(const QString& f)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return false;
-+ }
-+
-+ QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
-+ return r; // default is false
-+#else
-+ d->folderList();
-+ return d->serviceList.contains(f);
-+#endif
-+}
-+
-+
-+bool Wallet::createFolder(const QString& f)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return false;
-+ }
-+
-+ if (!hasFolder(f)) {
-+ QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
-+ return r;
-+ }
-+
-+ return true; // folder already exists
-+#else
-+ return setFolder(f);
-+#endif
-+}
-+
-+
-+bool Wallet::setFolder(const QString &f)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ bool rc = false;
-+
-+ if (d->handle == -1) {
-+ return rc;
-+ }
-+
-+ // Don't do this - the folder could have disappeared?
-+#if 0
-+ if (f == d->folder) {
-+ return true;
-+ }
-+#endif
-+
-+ if (hasFolder(f)) {
-+ d->folder = f;
-+ rc = true;
-+ }
-+
-+ return rc;
-+#else
-+ // act as if we just changed folders even if we have no such things; the property
-+ // is stored as the ServiceItemAttr (which shows up as the "Where" field in the Keychain Utility).
-+ if( f.size() == 0 ){
-+ d->currentService.clear();
-+ }
-+ else{
-+ d->currentService = QString(f);
-+ }
-+ return true;
-+#endif
-+}
-+
-+
-+bool Wallet::removeFolder(const QString& f)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle == -1) {
-+ return false;
-+ }
-+
-+ QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
-+ if (d->folder == f) {
-+ setFolder(QString());
-+ }
-+
-+ return r; // default is false
-+#else
-+ kWarning() << "Wallet::removeFolder unimplemented (returns true) '" << d->name << "'";
-+ if( d->currentService == f ){
-+ d->currentService.clear();
-+ }
-+ return true;
-+#endif
-+}
-+
-+
-+const QString& Wallet::currentFolder() const
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ return d->folder;
-+#else
-+ return d->currentService;
-+#endif
-+}
-+
-+
-+int Wallet::readEntry(const QString &key, QByteArray &value)
-+{ OSStatus err = d->readItem( key, &value, NULL );
-+ kDebug() << "Wallet::readEntry '" << key << "' from wallet " << d->name << ", error=" << ((err)? -1 : 0);
-+ return (err)? -1 : 0;
-+}
-+
-+
-+int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ registerTypes();
-+
-+ int rc = -1;
-+
-+ if (d->handle == -1) {
-+ return rc;
-+ }
-+
-+ QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
-+ if (r.isValid()) {
-+ rc = 0;
-+ // convert <QString, QVariant> to <QString, QByteArray>
-+ const QVariantMap val = r.value();
-+ for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
-+ value.insert(it.key(), it.value().toByteArray());
-+ }
-+ }
-+
-+ return rc;
-+#else
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ kWarning() << "Wallet::readEntryList unimplemented (returns -1) '" << d->name << "'";
-+ return -1;
-+#endif
-+}
-+
-+
-+int Wallet::renameEntry(const QString& oldName, const QString& newName)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ int rc = -1;
-+
-+ if (d->handle == -1) {
-+ return rc;
-+ }
-+
-+ QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
-+ if (r.isValid()) {
-+ rc = r;
-+ }
-+
-+ return rc;
-+#else
-+ return d->renameItem( oldName, newName );
-+#endif
-+}
-+
-+
-+int Wallet::readMap(const QString &key, QMap<QString,QString> &value)
-+{
-+ QByteArray v;
-+ const int ret = (d->readItem( key, &v, NULL ))? -1 : 0;
-+ if( ret != 0 ){
-+ return ret;
-+ }
-+ if( !v.isEmpty() ){
-+ QByteArray w = QByteArray::fromBase64(v);
-+ QDataStream ds( &w, QIODevice::ReadOnly );
-+ ds >> value;
-+ }
-+ kDebug() << "Wallet::readMap '" << key << "' from wallet " << d->name << ", error=0";
-+ return 0;
-+}
-+
-+
-+int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ registerTypes();
-+
-+ int rc = -1;
-+
-+ if (d->handle == -1) {
-+ return rc;
-+ }
-+
-+ QDBusReply<QVariantMap> r =
-+ walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
-+ if (r.isValid()) {
-+ rc = 0;
-+ const QVariantMap val = r.value();
-+ for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
-+ QByteArray mapData = it.value().toByteArray();
-+ if (!mapData.isEmpty()) {
-+ QDataStream ds(&mapData, QIODevice::ReadOnly);
-+ QMap<QString,QString> v;
-+ ds >> v;
-+ value.insert(it.key(), v);
-+ }
-+ }
-+ }
-+
-+ return rc;
-+#else
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ kWarning() << "Wallet::readMapList unimplemented (returns -1) '" << d->name << "'";
-+ return -1;
-+#endif
-+}
-+
-+
-+int Wallet::readPassword(const QString& key, QString& value)
-+{
-+ QByteArray ba;
-+ const int ret = (d->readItem( key, &ba, NULL ))? -1 : 0;
-+ if ( ret == 0 ){
-+ value = QString::fromUtf8( ba.constData() );
-+ }
-+ kDebug() << "Wallet::readPassword '" << key << "' from wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+
-+int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value)
-+{
-+ Q_UNUSED(key);
-+ Q_UNUSED(value);
-+ kWarning() << "Wallet::readPasswordList unimplemented (returns -1) '" << d->name << "'";
-+ return -1;
-+}
-+
-+int Wallet::writeEntry(const QString& key, const QByteArray& password )
-+{ int ret = d->writeItem( key, password );
-+ kDebug() << "wrote entry '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType)
-+{
-+ OSXKeychain::EntryType entryCode;
-+ switch( entryType ){
-+ case Wallet::Password:
-+ entryCode = OSXKeychain::Password;
-+ break;
-+ case Wallet::Map:
-+ entryCode = OSXKeychain::Map;
-+ break;
-+ case Wallet::Stream:
-+ entryCode = OSXKeychain::Stream;
-+ break;
-+ default:
-+ entryCode = OSXKeychain::Unknown;
-+ break;
-+ }
-+ int ret = d->writeItem( key, password, &entryCode );
-+ kDebug() << "wrote entry '" << key << "' of type=" << (int) entryType << "to wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value)
-+{
-+ QByteArray mapData;
-+ QDataStream ds(&mapData, QIODevice::WriteOnly);
-+ ds << value;
-+ OSXKeychain::EntryType etype = OSXKeychain::Map;
-+ int ret = d->writeItem( key, mapData.toBase64(),
-+ "This is a KDE Wallet::Map item. Its password\n"
-+ "cannot be read in the OS X Keychain Utility.\n"
-+ "Use KDE's own kwalletmanager for that.", &etype );
-+ kDebug() << "wrote map '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+
-+int Wallet::writePassword(const QString &key, const QString& value)
-+{ OSXKeychain::EntryType etype = OSXKeychain::Password;
-+ int ret = d->writeItem( key, value.toUtf8(), &etype );
-+ kDebug() << "wrote password '" << key << "' to wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+
-+bool Wallet::hasEntry(const QString &key)
-+{ bool ret = d->hasItem( key, NULL );
-+ kDebug() << "wallet '" << d->name << "'" << ((ret)? " has" : " does not have") << " entry '" << key << "'";
-+ return ret;
-+}
-+
-+int Wallet::removeEntry(const QString& key)
-+{ int ret = d->removeItem( key );
-+ kDebug() << "removed entry '" << key << "' from wallet " << d->name << ", error=" << ret;
-+ return ret;
-+}
-+
-+
-+Wallet::EntryType Wallet::entryType(const QString& key)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ int rc = 0;
-+
-+ if (d->handle == -1) {
-+ return Wallet::Unknown;
-+ }
-+
-+ QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
-+ if (r.isValid()) {
-+ rc = r;
-+ }
-+
-+ return static_cast<EntryType>(rc);
-+#else
-+ // RJVB: a priori, entries are always 'password' on OS X, but since we also do use them for storing
-+ // maps, it may be best to return Wallet::Unknown to leave some uncertainty and not mislead our caller.
-+ OSXKeychain::EntryType etype;
-+ if( !d->itemType( key, &etype ) ){
-+ switch( etype ){
-+ case OSXKeychain::Password:
-+ return Wallet::Password;
-+ break;
-+ case OSXKeychain::Map:
-+ return Wallet::Map;
-+ break;
-+ case OSXKeychain::Stream:
-+ return Wallet::Stream;
-+ break;
-+ }
-+ }
-+ return Wallet::Unknown;
-+#endif
-+}
-+
-+
-+void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder)
-+{
-+ if (d->name == wallet) {
-+ emit folderUpdated(folder);
-+ }
-+}
-+
-+
-+void Wallet::slotFolderListUpdated(const QString& wallet)
-+{
-+ if (d->name == wallet) {
-+ emit folderListUpdated();
-+ }
-+}
-+
-+
-+void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ if (d->handle >= 0
-+ && d->name == wallet
-+ && application == appid()) {
-+ slotWalletClosed(d->handle);
-+ }
-+#else
-+ Q_UNUSED(wallet);
-+ Q_UNUSED(application);
-+ kWarning() << "Wallet::slotApplicationDisconnected unimplemented '" << d->name << "'";
-+#endif
-+}
-+
-+void Wallet::walletAsyncOpened(int tId, int handle)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ // ignore responses to calls other than ours
-+ if (d->transactionId != tId || d->handle != -1) {
-+ return;
-+ }
-+
-+ // disconnect the async signal
-+ disconnect(this, SLOT(walletAsyncOpened(int,int)));
-+
-+ d->handle = handle;
-+ emit walletOpened(handle > 0);
-+#else
-+ Q_UNUSED(tId);
-+ Q_UNUSED(handle);
-+ kWarning() << "Wallet::walletAsyncOpened unimplemented '" << d->name << "'";
-+#endif
-+}
-+
-+void Wallet::emitWalletAsyncOpenError()
-+{
-+ emit walletOpened(false);
-+}
-+
-+void Wallet::emitWalletOpened()
-+{
-+ emit walletOpened(true);
-+}
-+
-+
-+bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
-+ return r;
-+#else
-+ bool ret = true;
-+ if( Wallet::walletList().contains(wallet) ){
-+ ret = !Wallet(-1, wallet).hasFolder(folder);
-+ }
-+ return ret;
-+#endif
-+}
-+
-+
-+bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
-+ return r;
-+#else
-+ bool ret = true;
-+ if( Wallet::walletList().contains(wallet) ){
-+ Wallet w(-1, wallet);
-+ if( w.hasFolder(folder) ){
-+ ret = !w.hasEntry(key);
-+ }
-+ }
-+ return ret;
-+#endif
-+}
-+
-+void Wallet::slotCollectionStatusChanged(int status)
-+{
-+ Q_UNUSED(status);
-+ kWarning() << "Wallet::slotCollectionStatusChanged unimplemented '" << d->name << "' status=" << status;
-+}
-+
-+void Wallet::slotCollectionDeleted()
-+{
-+#ifdef OSX_KEYCHAIN_PORT_DISABLED
-+ d->folder.clear();
-+#else
-+ d->currentService.clear();
-+#endif
-+ kDebug() << "Wallet::slotCollectionDeleted: closing private data '" << d->name;
-+ d->close();
-+ emit walletClosed();
-+}
-+
-+
-+void Wallet::virtual_hook(int, void*)
-+{
-+ //BASE::virtual_hook( id, data );
-+}
-+
-+#include "kwallet.moc"
-diff -urN kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.cpp kdelibs-4.13.3/kdeui/util/qosxkeychain.cpp
---- kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.cpp 1970-01-01 09:00:00.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/qosxkeychain.cpp 2014-09-22 19:46:57.000000000 +0900
-@@ -0,0 +1,776 @@
-+/*
-+ * @file qosxkeychain.cpp
-+ * This file is part of the KDE project
-+ *
-+ * Created by René J.V. Bertin on 20140809.
-+ * Copyright (C) 2014 René Bertin <rjvbertin at gmail.com>
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Library General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Library General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Library General Public License
-+ * along with this library; see the file COPYING.LIB. If not, write to
-+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ * Boston, MA 02110-1301, USA.
-+ */
-+
-+#include <cassert>
-+#include <sys/param.h>
-+
-+#include <QtGui/QApplication>
-+#include <QtCore/QtCore>
-+#include <QtCore/QPointer>
-+#include <QtGui/QWidget>
-+
-+#include "kwallet.h"
-+#include <kdebug.h>
-+using namespace KWallet;
-+#include "qosxkeychain.h"
-+
-+#include <CoreServices/CoreServices.h>
-+
-+//! Define INTERNET_TOO=1 in order to build read-access to the kSecInternetPasswordItemClass items
-+#define INTERNET_TOO 0
-+
-+// #undef kWarning
-+// #undef kDebug
-+// #define kWarning qWarning
-+// #define kDebug qDebug
-+
-+// returns the textual representation of a FourCharCode (e.g. 'JPEG')
-+static QString OSTStr( FourCharCode etype )
-+{ union OSTStr {
-+ struct {
-+ char startquote;
-+ uint32_t four;
-+ char endquote;
-+ } __attribute__ ((packed)) value;
-+ char representation[7];
-+ } __attribute__ ((packed)) ltype;
-+ ltype.value.four = EndianU32_BtoN(etype);
-+ ltype.representation[0] = ltype.representation[5] = '\'';
-+ ltype.representation[6] = '\0';
-+ return QString::fromAscii(ltype.representation);
-+}
-+
-+static SecKeychainRef defaultChain()
-+{ QString errMsg;
-+ SecKeychainRef keychain;
-+ if( isError( SecKeychainCopyDefault(&keychain), &errMsg ) ){
-+ kWarning() << "Could not retrieve reference to default keychain:" << qPrintable(errMsg);
-+ keychain = NULL;
-+ }
-+ return keychain;
-+}
-+
-+/*! Return a name for @p keychain, and possibly the full path to its file
-+ * The name will be the equivalent of the `basename path .keychain` shell
-+ * command.
-+ */
-+static QString keyChainName( SecKeychainRef keychain, QString *path=NULL )
-+{ QFileInfo keyFile;
-+ QString p = OSXKeychain::Path(keychain);
-+ int ext = p.lastIndexOf(".keychain");
-+ keyFile = QFileInfo( ((ext > 0)? p.left(ext) : p) );
-+ if( path ){
-+ *path = QString(p);
-+ }
-+ return keyFile.fileName();
-+}
-+
-+/*! Open an OS X keychain with name @p n.
-+ * OS X keychains can be created without a full path (say, "kdewallet"), in which case they
-+ * are stored e.g. as ~/Library/Keychains/kdewallet . However, opening a preexisting keychain like "login"
-+ * without using the full path seems to fail even if e.g. ~/Library/Keychains/login exists.
-+ * We try to work around that issue by matching @p n against the known keychain names.
-+ */
-+static OSStatus openKeychain( const QString &n, SecKeychainRef *keychain )
-+{ OSStatus err;
-+ CFArrayRef list = NULL;
-+
-+ *keychain = NULL;
-+ err = SecKeychainCopySearchList( &list );
-+ if( !err && list ){
-+ CFIndex len = CFArrayGetCount(list), i;
-+ for( i = 0 ; i < len && !*keychain ; ++i ){
-+ SecKeychainRef kr = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
-+ QString path, name = keyChainName( kr, &path );
-+ if( name == n ){
-+ // a hit, try to open it!
-+ err = SecKeychainOpen( path.toUtf8(), keychain );
-+ if( err ){
-+ kWarning() << "openKeychain(" << n << ") error" << err << "opening matching" << path;
-+ }
-+ else{
-+ kDebug() << "openKeychain(" << n << ") opened matching" << path;
-+ }
-+ }
-+ }
-+ CFRelease(list);
-+ }
-+ if( !*keychain ){
-+ err = SecKeychainOpen( n.toUtf8(), keychain );
-+ }
-+ // we actually need to query the keychain's status to know if we succeeded
-+ // in opening an existing keychain!
-+ if( !err ){
-+ SecKeychainStatus status;
-+ err = SecKeychainGetStatus( *keychain, &status );
-+ }
-+ return err;
-+}
-+
-+static OSStatus basicWriteItem( const QByteArray *serviceName, const QByteArray &accountName, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL )
-+{ OSStatus err;
-+ QString errMsg;
-+ if( serviceName ){
-+ err = SecKeychainAddGenericPassword( keychain, serviceName->size(), serviceName->constData(),
-+ accountName.size(), accountName.constData(),
-+ value.size(), value.constData(), itemRef );
-+ }
-+ else{
-+ err = SecKeychainAddGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ value.size(), value.constData(), itemRef );
-+ }
-+ if( err != errSecDuplicateItem && isError( err, &errMsg ) ){
-+ kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
-+ }
-+ return err;
-+}
-+
-+OSXKeychain::OSXKeychain()
-+ : name("default")
-+{ QString errMsg;
-+ keyChainRef = defaultChain();
-+ if( keyChainRef ){
-+ keyChainPath = OSXKeychain::Path(keyChainRef);
-+ kDebug() << "Retrieved reference to default keychain" << (void*) keyChainRef << "in " << keyChainPath;
-+ name = keyChainName(keyChainRef);
-+ isDefaultKeychain = true;
-+ }
-+ else{
-+ keyChainPath = QString::fromUtf8("<undefined>");
-+ }
-+ serviceList.clear();
-+ serviceList.append("");
-+}
-+
-+OSXKeychain::OSXKeychain(const QString &n, bool *isNew)
-+ : name(n)
-+{ QString errMsg;
-+ OSStatus err = openKeychain( n, &keyChainRef );
-+
-+ if( err == errSecNoSuchKeychain ){
-+ kWarning() << "Keychain '" << n << "' does not exist: attempting to create it";
-+ err = SecKeychainCreate( n.toUtf8(), 0, NULL, true, NULL, &keyChainRef );
-+ isKDEChain = true;
-+ if( !err && isNew ){
-+ *isNew = true;
-+ }
-+ }
-+ else if( !err && isNew ){
-+ *isNew = false;
-+ }
-+
-+ if( isError( err, &errMsg ) ){
-+ // the protocol cannot handle failure to open a keychain, so we have to return the default.
-+ keyChainRef = defaultChain();
-+ kWarning() << "Error opening keychain '" << n << "' (falling back to default keychain): " << qPrintable(errMsg);
-+ name = keyChainName(keyChainRef);
-+ isDefaultKeychain = true;
-+ }
-+ else{
-+ isDefaultKeychain = false;
-+ }
-+
-+ if( keyChainRef ){
-+ keyChainPath = OSXKeychain::Path(keyChainRef);
-+ kDebug() << "Retrieved reference to keychain" << name << (void*) keyChainRef << "in " << keyChainPath;
-+ }
-+ else{
-+ keyChainPath = QString::fromUtf8("<undefined>");
-+ }
-+ serviceList.clear();
-+ serviceList.append("");
-+}
-+
-+void OSXKeychain::close()
-+{
-+ if( keyChainRef ){
-+ Lock(keyChainRef);
-+ CFRelease(keyChainRef);
-+ keyChainRef = NULL;
-+ serviceList.clear();
-+ }
-+}
-+
-+OSXKeychain::~OSXKeychain()
-+{
-+ if( keyChainRef ){
-+ CFRelease(keyChainRef);
-+ keyChainRef = NULL;
-+ }
-+ serviceList.clear();
-+}
-+
-+OSStatus OSXKeychain::lockSettings(int &closeWhenIdle, unsigned int &idleTimeoutMin)
-+{ QString errMsg;
-+ SecKeychainSettings kcSettings= { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
-+ OSStatus err = SecKeychainCopySettings( keyChainRef, &kcSettings );
-+ if( isError( err, &errMsg ) ){
-+ kWarning() << "Error getting settings for" << name << err << "=" << qPrintable(errMsg);
-+ }
-+ else{
-+ closeWhenIdle = kcSettings.useLockInterval;
-+ idleTimeoutMin = (int)(kcSettings.lockInterval / 60 + 0.5);
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::setLockSettings(int closeWhenIdle, unsigned int idleTimeoutMin)
-+{ QString errMsg;
-+ SecKeychainSettings kcSettings = { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
-+ OSStatus err;
-+
-+ // to switch (or keep) off idle timeout locking set useLockInterval=false and lockInterval=INT_MAX
-+ // if lockInterval has any other value, SecKeychainSetSettings() will force useLockInterval=true
-+ if( closeWhenIdle ){
-+ kcSettings.useLockInterval = 1;
-+ kcSettings.lockInterval = idleTimeoutMin * 60;
-+ }
-+ err = SecKeychainSetSettings( keyChainRef, &kcSettings );
-+// if( !err ){
-+// SecKeychainSettings ks = { SEC_KEYCHAIN_SETTINGS_VERS1, 0, 0, INT_MAX };
-+// ks.useLockInterval = !closeWhenIdle;
-+// SecKeychainCopySettings( keyChainRef, &ks );
-+// qDebug() << "Keychain settings set to useLockInterval=" << ks.useLockInterval << "lockInterval=" << ks.lockInterval;
-+// }
-+// else{
-+// qDebug() << "Error setting keychain settings:" << err;
-+// }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::renameItem(const QString ¤tKey, const QString &newKey)
-+{ OSStatus err;
-+ SecKeychainItemRef itemRef = NULL;
-+ err = ReadItem( currentKey, NULL, keyChainRef, &itemRef, this );
-+ if( !err && itemRef ){
-+ const QByteArray accountName( newKey.toUtf8() );
-+ // store the new key in the account and label attributes
-+ SecKeychainAttribute attr[] = { { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() },
-+ { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() } };
-+ SecKeychainAttributeList attrList = { 2, &attr[0] };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::renameItem(" << currentKey << ") couldn't change name & label to" << accountName
-+ << ":" << err << "=" << qPrintable(errMsg);
-+ }
-+ CFRelease(itemRef);
-+ }
-+ return err;
-+}
-+
-+#pragma mark ========= static member functions =========
-+
-+OSStatus OSXKeychain::KeychainList(QStringList &theList)
-+{ CFArrayRef list = NULL;
-+ OSStatus err = SecKeychainCopySearchList( &list );
-+ theList.clear();
-+ if( !err && list ){
-+ CFIndex len = CFArrayGetCount(list), i;
-+ for( i = 0 ; i < len ; ++i ){
-+ SecKeychainRef keychain = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
-+ QString name = keyChainName(keychain);
-+ if( name.size() > 0 ){
-+ theList.append(name);
-+ }
-+ }
-+ CFRelease(list);
-+ }
-+ return err;
-+}
-+
-+QString OSXKeychain::Path(const SecKeychainRef keychain)
-+{ char pathName[MAXPATHLEN];
-+ UInt32 plen = MAXPATHLEN;
-+ if( SecKeychainGetPath( (keychain)? keychain : OSXKeychain().reference(), &plen, pathName ) == errSecSuccess ){
-+ return QString::fromUtf8(pathName);
-+ }
-+ else{
-+ return QString();
-+ }
-+}
-+
-+bool OSXKeychain::IsOpen(const SecKeychainRef keychain)
-+{ bool isOpen = false;
-+ SecKeychainStatus status;
-+ QString errMsg;
-+ if( isError( SecKeychainGetStatus( keychain, &status ), &errMsg ) ){
-+ if( keychain ){
-+ kDebug() << "Could not get the status of keychain" << OSXKeychain::Path(keychain) << ":" << qPrintable(errMsg);
-+ }
-+ else{
-+ kWarning() << "Could not get the default keychain's status:" << qPrintable(errMsg);
-+ }
-+ }
-+ else{
-+ if( (status & kSecUnlockStateStatus) && (status & kSecReadPermStatus) ){
-+ isOpen = true;
-+ }
-+ else{
-+ kDebug() << "Keychain" << OSXKeychain::Path(keychain) << " has status" << status;
-+ }
-+ }
-+ return isOpen;
-+}
-+
-+bool OSXKeychain::IsOpen(const QString &walletName)
-+{ SecKeychainRef keychain = NULL;
-+ OSStatus err = openKeychain( walletName.toUtf8(), &keychain );
-+ bool ret = false;
-+ if( !err && keychain ){
-+ ret = IsOpen(keychain);
-+ CFRelease(keychain);
-+ }
-+ return ret;
-+}
-+
-+OSStatus OSXKeychain::UnLock(const SecKeychainRef keychain)
-+{ QString errMsg;
-+ OSStatus err;
-+ err = SecKeychainUnlock( keychain, 0, NULL, false );
-+ if( isError( err, &errMsg ) ){
-+ if( keychain ){
-+ kDebug() << "Could not unlock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
-+ }
-+ else{
-+ kDebug() << "Could not unlock the default keychain:" << qPrintable(errMsg);
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Lock(const SecKeychainRef keychain)
-+{ QString errMsg;
-+ OSStatus err;
-+ if( keychain ){
-+ err = SecKeychainLock(keychain);
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Could not lock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
-+ }
-+ }
-+ else{
-+ err = SecKeychainLockAll();
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Could not lock all keychains:" << qPrintable(errMsg);
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Lock(const QString &walletName)
-+{ SecKeychainRef keychain = NULL;
-+ OSStatus err = openKeychain( walletName, &keychain );
-+ if( !err && keychain ){
-+ err = Lock(keychain);
-+ CFRelease(keychain);
-+ }
-+ return err;
-+}
-+
-+/** use the keychain search functions to find the first matching item, if any, @return returning True if found.
-+ The OS X error code is returned through @p errReturn when not NULL, the item itself through @p itemRef.
-+ This reference will have to be released with CFRelease() when done with it (when @p itemRef==NULL the
-+ function does this release itself).
-+ */
-+bool OSXKeychain::HasItem(const QString &key,
-+ const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef)
-+{ const QByteArray accountName( key.toUtf8() );
-+ OSStatus err;
-+ SecKeychainSearchRef searchRef;
-+ SecKeychainAttribute attrs = { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attrs };
-+ err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass,
-+ (const SecKeychainAttributeList*) &attrList, &searchRef );
-+ const CFReleaser<SecKeychainSearchRef> releaseSR(searchRef);
-+ bool found;
-+ SecKeychainItemRef item;
-+ QString errMsg;
-+ if( err ){
-+ found = false;
-+ errMsg = errorString(err);
-+ kDebug() << "OSXKeychain::HasItem(" << key << "," << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed";
-+ }
-+ else{
-+ if( !(err = SecKeychainSearchCopyNext( searchRef, &item )) ){
-+ found = true;
-+ if( itemRef ){
-+ *itemRef = item;
-+ }
-+ else if( item ){
-+ CFRelease(item);
-+ }
-+ errMsg = QString();
-+ }
-+ else{
-+ found = false;
-+ errMsg = errorString(err);
-+ }
-+ if( errReturn ){
-+ *errReturn = err;
-+ }
-+ }
-+ kDebug() << "item '" << key << ((found)? "found" : "not found") << "' in keychain " << (void*) keychain << ", error=" << err << " " << qPrintable(errMsg);
-+ return found;
-+}
-+
-+OSStatus OSXKeychain::ReadItem(const QString &key, QByteArray *value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef, OSXKeychain *osxKeyChain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ UInt32 passwordSize = 0;
-+ void* passwordData = 0;
-+ QString errMsg;
-+ SecKeychainItemRef theItem;
-+ OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ &passwordSize, &passwordData, &theItem );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Error" << err << "retrieving password for '" << accountName << "' :" << qPrintable(errMsg);
-+#if INTERNET_TOO
-+ if( SecKeychainFindInternetPassword( keychain, 0, NULL,
-+ 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ 0, NULL, 0,
-+ kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
-+ &passwordSize, &passwordData, &theItem ) ){
-+ // just to be sure:
-+ theItem = NULL;
-+ }
-+ else{
-+ err = 0;
-+ errMsg = QString();
-+ }
-+#else
-+ theItem = NULL;
-+#endif
-+ }
-+ if( !err && theItem ){
-+ if( value ){
-+ *value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
-+ }
-+ SecKeychainItemFreeContent( NULL, passwordData );
-+ if( osxKeyChain && osxKeyChain->isKDEChain ){
-+ SecKeychainAttribute attr = { kSecServiceItemAttr, 0, NULL };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ UInt32 len = 0;
-+ // try to fetch the item's ServiceItem attribute
-+ if( !SecKeychainItemCopyContent( theItem, NULL, &attrList, &len, NULL ) ){
-+ if( attr.length > 0 ){
-+ osxKeyChain->lastReadService.clear();
-+ osxKeyChain->lastReadService = QString::fromUtf8( (char*)attr.data, attr.length );
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ }
-+ if( itemRef ){
-+ *itemRef = theItem;
-+ }
-+ else if( theItem ){
-+ CFRelease(theItem);
-+ }
-+ }
-+ kDebug() << "OSXKeychain::ReadItem '" << key << "' from keychain " << OSXKeychain::Path(keychain) << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::ItemType(const QString &key, EntryType *entryType,
-+ const SecKeychainRef keychain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ QString errMsg;
-+ EntryType etype = (EntryType) 0;
-+ SecKeychainItemRef itemRef;
-+#if INTERNET_TOO
-+ bool isInternetPW = false;
-+#endif
-+ OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ NULL, NULL, &itemRef );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Error" << err << "retrieving type for '" << accountName << "' :" << qPrintable(errMsg);
-+#if INTERNET_TOO
-+ if( SecKeychainFindInternetPassword( keychain, 0, NULL,
-+ 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ 0, NULL, 0,
-+ kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
-+ 0, NULL, &itemRef ) ){
-+ // just to be sure:
-+ itemRef = NULL;
-+ }
-+ else{
-+ isInternetPW = true;
-+ err = 0;
-+ errMsg = QString();
-+ }
-+#else
-+ itemRef = NULL;
-+#endif
-+ }
-+ if( itemRef ){
-+ UInt32 tags[] = { kSecTypeItemAttr };
-+ UInt32 formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_STRING };
-+ SecKeychainAttributeInfo attrGet = { 1, tags, formats };
-+ SecKeychainAttributeList *attrList = NULL;
-+ err = SecKeychainItemCopyAttributesAndData( itemRef, &attrGet, NULL, &attrList, NULL, NULL );
-+ if( !err ){
-+ if( attrList->attr[0].length == sizeof(EntryType) ){
-+ memcpy( &etype, attrList->attr[0].data, sizeof(EntryType) );
-+ }
-+ else if( attrList->attr[0].length ){
-+ kDebug() << "Error: key" << key << "item type retrieved is of size" << attrList->attr[0].length << "!=" << sizeof(EntryType);
-+ }
-+#if INTERNET_TOO
-+ else if( isInternetPW ){
-+ // this is just a wild guess ...
-+ etype = Password;
-+ }
-+#endif
-+ if( entryType ){
-+ *entryType = etype;
-+ }
-+ }
-+ SecKeychainItemFreeAttributesAndData( attrList, NULL );
-+ CFRelease(itemRef);
-+ }
-+ kDebug() << "OSXKeychain::ItemType '" << key << "' from keychain " << OSXKeychain::Path(keychain) << "=" << OSTStr(etype) << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::RemoveItem(const QString &key, const SecKeychainRef keychain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ SecKeychainItemRef itemRef;
-+ QString errMsg;
-+ OSStatus result = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(), NULL, NULL, &itemRef );
-+ if( isError( result, &errMsg ) ){
-+ kDebug() << "Could not find entry" << key << ":" << qPrintable(errMsg);
-+ }
-+ else{
-+ const CFReleaser<SecKeychainItemRef> itemReleaser(itemRef);
-+ result = SecKeychainItemDelete(itemRef);
-+ if( isError( result, &errMsg ) ){
-+ kWarning() << "Could not delete entry" << key << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ return result;
-+}
-+
-+OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef, EntryType *entryType, OSXKeychain *osxKeyChain )
-+{ const QByteArray accountName( key.toUtf8() );
-+ OSStatus err;
-+ QString errMsg;
-+ SecKeychainItemRef theItem = NULL;
-+ bool saveLabel;
-+ if( osxKeyChain && osxKeyChain->currentService.size() ){
-+ const QByteArray serviceName( osxKeyChain->currentService.toUtf8() );
-+ // save the "GenericPassword" item using the service name, which appears to be the only way to write
-+ // to the "Where" field shown in the Keychain Utility.
-+ err = basicWriteItem( &serviceName, accountName, value, keychain, &theItem );
-+ // the service (folder!) string will also appear on the "Name" field, which however can be changed
-+ // independently, via the Label attribute.
-+ saveLabel = true;
-+ }
-+ else{
-+ err = basicWriteItem( NULL, accountName, value, keychain, &theItem );
-+ saveLabel = false;
-+ }
-+ if( err == errSecDuplicateItem ){
-+ // RJVB: the previous implementation was wrong. errSecDuplicateItem means the write failed because of an existing item.
-+ // So we have to find that item, and modify it.
-+ if( !(err = ReadItem( key, NULL, keychain, &theItem )) ){
-+ err = SecKeychainItemModifyAttributesAndData( theItem, NULL, value.size(), value.constData() );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Key '" << key
-+ << "'already exists in keychain but error modifying the existing item: " << qPrintable(errMsg);
-+ }
-+ }
-+ if( !err ){
-+ kDebug() << "Key '" << key << "'already existed in keychain: modified the existing item";
-+ }
-+ }
-+ if( !err && saveLabel ){
-+ // store the desired text in the label attribute
-+ SecKeychainAttribute attr = { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set the desired name/label" << accountName
-+ << ":" << err << "=" << qPrintable(errMsg);
-+ }
-+ }
-+ if( !err ){
-+ EntryType defType = Stream;
-+ if( !entryType ){
-+ entryType = &defType;
-+ }
-+ SecKeychainAttribute attr = { kSecTypeItemAttr, sizeof(EntryType), (void*) entryType };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set type to" << OSTStr(*entryType)
-+ << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ if( itemRef ){
-+ *itemRef = theItem;
-+ }
-+ else if( theItem ){
-+ CFRelease(theItem);
-+ }
-+ kDebug() << "OSXKeychain::WriteItem '" << key << "' to keychain " << (void*) keychain << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
-+ const QString &comment, const SecKeychainRef keychain, EntryType *entryType, OSXKeychain *osxKeyChain )
-+{ SecKeychainItemRef itemRef = NULL;
-+ OSStatus err = WriteItem( key, value, keychain, &itemRef, entryType, osxKeyChain );
-+ if( !err && itemRef ){
-+ const QByteArray commentString(comment.toUtf8());
-+ if( commentString.size() ){
-+ SecKeychainAttribute attr = { kSecCommentItemAttr, commentString.size(), (void*) commentString.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't add comment" << comment
-+ << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ CFRelease(itemRef);
-+ }
-+ return err;
-+}
-+
-+// returns the kSecAccountItemAttr's of all items in the keychain
-+OSStatus OSXKeychain::ItemList( SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain )
-+{ OSStatus err;
-+ SecKeychainSearchRef searchRef[2];
-+ bool generateFolderList = ( osxKeyChain && osxKeyChain->isKDEChain && osxKeyChain->generateFolderList );
-+
-+ keyList.clear();
-+ if( generateFolderList ){
-+ osxKeyChain->serviceList.clear();
-+ if( osxKeyChain->currentService.size() > 0 ){
-+ osxKeyChain->serviceList.append(osxKeyChain->currentService);
-+ }
-+ }
-+
-+ err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass, NULL, &searchRef[0] );
-+#if INTERNET_TOO
-+ if( SecKeychainSearchCreateFromAttributes( keychain, kSecInternetPasswordItemClass, NULL, &searchRef[1] ) ){
-+ searchRef[1] = NULL;
-+ }
-+#else
-+ searchRef[1] = NULL;
-+#endif
-+ SecKeychainItemRef item;
-+ QString errMsg;
-+ if( isError(err, &errMsg) ){
-+ kDebug() << "OSXKeychain::ItemList(" << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed" << qPrintable(errMsg);
-+ }
-+ else{
-+ for( size_t i = 0 ; i < sizeof(searchRef)/sizeof(SecKeychainSearchRef) && !err ; ++i ){
-+ if( searchRef[i] ){
-+ while( !(err = SecKeychainSearchCopyNext( searchRef[i], &item )) ){
-+ if( item ){
-+ // whether the item will be listed in the keyList we return: by default it is
-+ // (better an item shows up multiple times than not at all).
-+ bool listItem = true;
-+ SecKeychainAttribute attr = { kSecAccountItemAttr, 0, NULL };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ UInt32 len = 0;
-+ if( osxKeyChain && osxKeyChain->isKDEChain ){
-+ // try to fetch the item's ServiceItem attribute
-+ attr.tag = kSecServiceItemAttr;
-+ if( !SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL ) ){
-+ QString lbl = QString::fromUtf8( (char*)attr.data, attr.length );
-+ // we got a service item attribute, which is where we store the kwallet folder info.
-+ // If we disallow empty attributes, keychain items without service item attribute will
-+ // appear in each folder that has a non-empty name. In other words, we allow a folder without name.
-+ if( generateFolderList ){
-+ // add the "folder" to the list if not already listed
-+ if( !osxKeyChain->serviceList.contains(lbl) ){
-+ osxKeyChain->serviceList.append(lbl);
-+ }
-+ }
-+ else{
-+ // only list the item if it's in the current "folder"
-+ listItem = (lbl == osxKeyChain->currentService);
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ }
-+ else{
-+ // errors retrieving the service item attribute are ignored
-+ }
-+ if( listItem ){
-+ attr.tag = kSecAccountItemAttr;
-+ if( !(err = SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL )) ){
-+ if( attr.length > 0 ){
-+ keyList.append(QString::fromUtf8( (char*)attr.data, attr.length ));
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ else{
-+ errMsg = errorString(err);
-+ kDebug() << "SecKeychainItemCopyContent returned" << err << "=" << qPrintable(errMsg);
-+ }
-+ }
-+ CFRelease(item);
-+ }
-+ }
-+ if( err ){
-+ errMsg = errorString(err);
-+ }
-+ CFRelease(searchRef[i]);
-+ }
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Destroy( SecKeychainRef *keychain )
-+{ OSStatus err = SecKeychainDelete(*keychain);
-+ QString errMsg;
-+ if( isError( err, &errMsg ) ){
-+ kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error " << qPrintable(errMsg);
-+ }
-+ else{
-+ kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error=" << err;
-+ }
-+ if( keychain ){
-+ CFRelease(*keychain);
-+ *keychain = NULL;
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Destroy( const QString &walletName )
-+{ SecKeychainRef keychain;
-+ OSStatus err = openKeychain( walletName, &keychain );
-+ if( !err && keychain ){
-+ err = Destroy(&keychain);
-+ }
-+ return err;
-+}
-diff -urN kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.cpp.orig kdelibs-4.13.3/kdeui/util/qosxkeychain.cpp.orig
---- kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.cpp.orig 1970-01-01 09:00:00.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/qosxkeychain.cpp.orig 2014-09-22 19:46:10.000000000 +0900
-@@ -0,0 +1,726 @@
-+/*
-+ * @file qosxkeychain.cpp
-+ * This file is part of the KDE project
-+ *
-+ * Created by René J.V. Bertin on 20140809.
-+ * Copyright (C) 2014 René Bertin <rjvbertin at gmail.com>
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Library General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Library General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Library General Public License
-+ * along with this library; see the file COPYING.LIB. If not, write to
-+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ * Boston, MA 02110-1301, USA.
-+ */
-+
-+#include <cassert>
-+#include <sys/param.h>
-+
-+#include <QtGui/QApplication>
-+#include <QtCore/QtCore>
-+#include <QtCore/QPointer>
-+#include <QtGui/QWidget>
-+
-+#include "kwallet.h"
-+#include <kdebug.h>
-+using namespace KWallet;
-+#include "qosxkeychain.h"
-+
-+#include <CoreServices/CoreServices.h>
-+
-+//! Define INTERNET_TOO=1 in order to build read-access to the kSecInternetPasswordItemClass items
-+#define INTERNET_TOO 0
-+
-+// #undef kWarning
-+// #undef kDebug
-+// #define kWarning qWarning
-+// #define kDebug qDebug
-+
-+// returns the textual representation of a FourCharCode (e.g. 'JPEG')
-+static QString OSTStr( FourCharCode etype )
-+{ union OSTStr {
-+ struct {
-+ char startquote;
-+ uint32_t four;
-+ char endquote;
-+ } __attribute__ ((packed)) value;
-+ char representation[7];
-+ } __attribute__ ((packed)) ltype;
-+ ltype.value.four = EndianU32_BtoN(etype);
-+ ltype.representation[0] = ltype.representation[5] = '\'';
-+ ltype.representation[6] = '\0';
-+ return QString::fromAscii(ltype.representation);
-+}
-+
-+static SecKeychainRef defaultChain()
-+{ QString errMsg;
-+ SecKeychainRef keychain;
-+ if( isError( SecKeychainCopyDefault(&keychain), &errMsg ) ){
-+ kWarning() << "Could not retrieve reference to default keychain:" << qPrintable(errMsg);
-+ keychain = NULL;
-+ }
-+ return keychain;
-+}
-+
-+/*! Return a name for @p keychain, and possibly the full path to its file
-+ * The name will be the equivalent of the `basename path .keychain` shell
-+ * command.
-+ */
-+static QString keyChainName( SecKeychainRef keychain, QString *path=NULL )
-+{ QFileInfo keyFile;
-+ QString p = OSXKeychain::Path(keychain);
-+ int ext = p.lastIndexOf(".keychain");
-+ keyFile = QFileInfo( ((ext > 0)? p.left(ext) : p) );
-+ if( path ){
-+ *path = QString(p);
-+ }
-+ return keyFile.fileName();
-+}
-+
-+/*! Open an OS X keychain with name @p n.
-+ * OS X keychains can be created without a full path (say, "kdewallet"), in which case they
-+ * are stored e.g. as ~/Library/Keychains/kdewallet . However, opening a preexisting keychain like "login"
-+ * without using the full path seems to fail even if e.g. ~/Library/Keychains/login exists.
-+ * We try to work around that issue by matching @p n against the known keychain names.
-+ */
-+static OSStatus openKeychain( const QString &n, SecKeychainRef *keychain )
-+{ OSStatus err;
-+ CFArrayRef list = NULL;
-+
-+ *keychain = NULL;
-+ err = SecKeychainCopySearchList( &list );
-+ if( !err && list ){
-+ CFIndex len = CFArrayGetCount(list), i;
-+ for( i = 0 ; i < len && !*keychain ; ++i ){
-+ SecKeychainRef kr = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
-+ QString path, name = keyChainName( kr, &path );
-+ if( name == n ){
-+ // a hit, try to open it!
-+ err = SecKeychainOpen( path.toUtf8(), keychain );
-+ if( err ){
-+ kWarning() << "openKeychain(" << n << ") error" << err << "opening matching" << path;
-+ }
-+ else{
-+ kDebug() << "openKeychain(" << n << ") opened matching" << path;
-+ }
-+ }
-+ }
-+ CFRelease(list);
-+ }
-+ if( !*keychain ){
-+ err = SecKeychainOpen( n.toUtf8(), keychain );
-+ }
-+ // we actually need to query the keychain's status to know if we succeeded
-+ // in opening an existing keychain!
-+ if( !err ){
-+ SecKeychainStatus status;
-+ err = SecKeychainGetStatus( *keychain, &status );
-+ }
-+ return err;
-+}
-+
-+static OSStatus basicWriteItem( const QByteArray *serviceName, const QByteArray &accountName, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL )
-+{ OSStatus err;
-+ QString errMsg;
-+ if( serviceName ){
-+ err = SecKeychainAddGenericPassword( keychain, serviceName->size(), serviceName->constData(),
-+ accountName.size(), accountName.constData(),
-+ value.size(), value.constData(), itemRef );
-+ }
-+ else{
-+ err = SecKeychainAddGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ value.size(), value.constData(), itemRef );
-+ }
-+ if( err != errSecDuplicateItem && isError( err, &errMsg ) ){
-+ kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
-+ }
-+ return err;
-+}
-+
-+OSXKeychain::OSXKeychain()
-+ : name("default")
-+{ QString errMsg;
-+ keyChainRef = defaultChain();
-+ if( keyChainRef ){
-+ keyChainPath = OSXKeychain::Path(keyChainRef);
-+ kDebug() << "Retrieved reference to default keychain" << (void*) keyChainRef << "in " << keyChainPath;
-+ name = keyChainName(keyChainRef);
-+ isDefaultKeychain = true;
-+ }
-+ else{
-+ keyChainPath = QString::fromUtf8("<undefined>");
-+ }
-+ serviceList.clear();
-+ serviceList.append("");
-+}
-+
-+OSXKeychain::OSXKeychain(const QString &n)
-+ : name(n)
-+{ QString errMsg;
-+ OSStatus err = openKeychain( n, &keyChainRef );
-+
-+ if( err == errSecNoSuchKeychain ){
-+ kWarning() << "Keychain '" << n << "' does not exist: attempting to create it";
-+ err = SecKeychainCreate( n.toUtf8(), 0, NULL, true, NULL, &keyChainRef );
-+ isKDEChain = true;
-+ }
-+
-+ if( isError( err, &errMsg ) ){
-+ // the protocol cannot handle failure to open a keychain, so we have to return the default.
-+ keyChainRef = defaultChain();
-+ kWarning() << "Error opening keychain '" << n << "' (falling back to default keychain): " << qPrintable(errMsg);
-+ name = keyChainName(keyChainRef);
-+ isDefaultKeychain = true;
-+ }
-+ else{
-+ isDefaultKeychain = false;
-+ }
-+
-+ if( keyChainRef ){
-+ keyChainPath = OSXKeychain::Path(keyChainRef);
-+ kDebug() << "Retrieved reference to keychain" << name << (void*) keyChainRef << "in " << keyChainPath;
-+ }
-+ else{
-+ keyChainPath = QString::fromUtf8("<undefined>");
-+ }
-+ serviceList.clear();
-+ serviceList.append("");
-+}
-+
-+void OSXKeychain::close()
-+{
-+ if( keyChainRef ){
-+ CFRelease(keyChainRef);
-+ keyChainRef = NULL;
-+ }
-+}
-+
-+OSXKeychain::~OSXKeychain()
-+{
-+ close();
-+}
-+
-+OSStatus OSXKeychain::renameItem(const QString ¤tKey, const QString &newKey)
-+{ OSStatus err;
-+ SecKeychainItemRef itemRef = NULL;
-+ err = ReadItem( currentKey, NULL, keyChainRef, &itemRef, this );
-+ if( !err && itemRef ){
-+ const QByteArray accountName( newKey.toUtf8() );
-+ // store the new key in the account and label attributes
-+ SecKeychainAttribute attr[] = { { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() },
-+ { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() } };
-+ SecKeychainAttributeList attrList = { 2, &attr[0] };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::renameItem(" << currentKey << ") couldn't change name & label to" << accountName
-+ << ":" << err << "=" << qPrintable(errMsg);
-+ }
-+ CFRelease(itemRef);
-+ }
-+ return err;
-+}
-+
-+#pragma mark ========= static member functions =========
-+
-+OSStatus OSXKeychain::KeychainList(QStringList &theList)
-+{ CFArrayRef list = NULL;
-+ OSStatus err = SecKeychainCopySearchList( &list );
-+ theList.clear();
-+ if( !err && list ){
-+ CFIndex len = CFArrayGetCount(list), i;
-+ for( i = 0 ; i < len ; ++i ){
-+ SecKeychainRef keychain = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
-+ QString name = keyChainName(keychain);
-+ if( name.size() > 0 ){
-+ theList.append(name);
-+ }
-+ }
-+ CFRelease(list);
-+ }
-+ return err;
-+}
-+
-+QString OSXKeychain::Path(const SecKeychainRef keychain)
-+{ char pathName[MAXPATHLEN];
-+ UInt32 plen = MAXPATHLEN;
-+ if( SecKeychainGetPath( (keychain)? keychain : OSXKeychain().reference(), &plen, pathName ) == errSecSuccess ){
-+ return QString::fromUtf8(pathName);
-+ }
-+ else{
-+ return QString();
-+ }
-+}
-+
-+bool OSXKeychain::IsOpen(const SecKeychainRef keychain)
-+{ bool isOpen = false;
-+ SecKeychainStatus status;
-+ QString errMsg;
-+ if( isError( SecKeychainGetStatus( keychain, &status ), &errMsg ) ){
-+ if( keychain ){
-+ kDebug() << "Could not get the status of keychain" << OSXKeychain::Path(keychain) << ":" << qPrintable(errMsg);
-+ }
-+ else{
-+ kWarning() << "Could not get the default keychain's status:" << qPrintable(errMsg);
-+ }
-+ }
-+ else{
-+ if( (status & kSecUnlockStateStatus) && (status & kSecReadPermStatus) ){
-+ isOpen = true;
-+ }
-+ else{
-+ kDebug() << "Keychain" << OSXKeychain::Path(keychain) << " has status" << status;
-+ }
-+ }
-+ return isOpen;
-+}
-+
-+bool OSXKeychain::IsOpen(const QString &walletName)
-+{ SecKeychainRef keychain = NULL;
-+ OSStatus err = openKeychain( walletName.toUtf8(), &keychain );
-+ bool ret = false;
-+ if( !err && keychain ){
-+ ret = IsOpen(keychain);
-+ CFRelease(keychain);
-+ }
-+ return ret;
-+}
-+
-+OSStatus OSXKeychain::UnLock(const SecKeychainRef keychain)
-+{ QString errMsg;
-+ OSStatus err;
-+ err = SecKeychainUnlock( keychain, 0, NULL, false );
-+ if( isError( err, &errMsg ) ){
-+ if( keychain ){
-+ kDebug() << "Could not unlock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
-+ }
-+ else{
-+ kDebug() << "Could not unlock the default keychain:" << qPrintable(errMsg);
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Lock(const SecKeychainRef keychain)
-+{ QString errMsg;
-+ OSStatus err;
-+ if( keychain ){
-+ err = SecKeychainLock(keychain);
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Could not lock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
-+ }
-+ }
-+ else{
-+ err = SecKeychainLockAll();
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Could not lock all keychains:" << qPrintable(errMsg);
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Lock(const QString &walletName)
-+{ SecKeychainRef keychain = NULL;
-+ OSStatus err = openKeychain( walletName, &keychain );
-+ if( !err && keychain ){
-+ err = Lock(keychain);
-+ CFRelease(keychain);
-+ }
-+ return err;
-+}
-+
-+/** use the keychain search functions to find the first matching item, if any, @return returning True if found.
-+ The OS X error code is returned through @p errReturn when not NULL, the item itself through @p itemRef.
-+ This reference will have to be released with CFRelease() when done with it (when @p itemRef==NULL the
-+ function does this release itself).
-+ */
-+bool OSXKeychain::HasItem(const QString &key,
-+ const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef)
-+{ const QByteArray accountName( key.toUtf8() );
-+ OSStatus err;
-+ SecKeychainSearchRef searchRef;
-+ SecKeychainAttribute attrs = { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attrs };
-+ err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass,
-+ (const SecKeychainAttributeList*) &attrList, &searchRef );
-+ const CFReleaser<SecKeychainSearchRef> releaseSR(searchRef);
-+ bool found;
-+ SecKeychainItemRef item;
-+ QString errMsg;
-+ if( err ){
-+ found = false;
-+ errMsg = errorString(err);
-+ kDebug() << "OSXKeychain::HasItem(" << key << "," << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed";
-+ }
-+ else{
-+ if( !(err = SecKeychainSearchCopyNext( searchRef, &item )) ){
-+ found = true;
-+ if( itemRef ){
-+ *itemRef = item;
-+ }
-+ else if( item ){
-+ CFRelease(item);
-+ }
-+ errMsg = QString();
-+ }
-+ else{
-+ found = false;
-+ errMsg = errorString(err);
-+ }
-+ if( errReturn ){
-+ *errReturn = err;
-+ }
-+ }
-+ kDebug() << ((found)? "Found" : "Did not find") << "item '" << key << "' in keychain " << (void*) keychain << ", error=" << err << " " << qPrintable(errMsg);
-+ return found;
-+}
-+
-+OSStatus OSXKeychain::ReadItem(const QString &key, QByteArray *value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef, OSXKeychain *osxKeyChain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ UInt32 passwordSize = 0;
-+ void* passwordData = 0;
-+ QString errMsg;
-+ SecKeychainItemRef theItem;
-+ OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ &passwordSize, &passwordData, &theItem );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Error" << err << "retrieving password for '" << accountName << "' :" << qPrintable(errMsg);
-+#if INTERNET_TOO
-+ if( SecKeychainFindInternetPassword( keychain, 0, NULL,
-+ 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ 0, NULL, 0,
-+ kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
-+ &passwordSize, &passwordData, &theItem ) ){
-+ // just to be sure:
-+ theItem = NULL;
-+ }
-+ else{
-+ err = 0;
-+ errMsg = QString();
-+ }
-+#else
-+ theItem = NULL;
-+#endif
-+ }
-+ if( !err && theItem ){
-+ if( value ){
-+ *value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
-+ }
-+ SecKeychainItemFreeContent( NULL, passwordData );
-+ if( osxKeyChain && osxKeyChain->isKDEChain ){
-+ SecKeychainAttribute attr = { kSecServiceItemAttr, 0, NULL };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ UInt32 len = 0;
-+ // try to fetch the item's ServiceItem attribute
-+ if( !SecKeychainItemCopyContent( theItem, NULL, &attrList, &len, NULL ) ){
-+ if( attr.length > 0 ){
-+ osxKeyChain->lastReadService.clear();
-+ osxKeyChain->lastReadService = QString::fromUtf8( (char*)attr.data, attr.length );
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ }
-+ if( itemRef ){
-+ *itemRef = theItem;
-+ }
-+ else if( theItem ){
-+ CFRelease(theItem);
-+ }
-+ }
-+ kDebug() << "OSXKeychain::ReadItem '" << key << "' from keychain " << OSXKeychain::Path(keychain) << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::ItemType(const QString &key, EntryType *entryType,
-+ const SecKeychainRef keychain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ QString errMsg;
-+ EntryType etype = (EntryType) 0;
-+ SecKeychainItemRef itemRef;
-+#if INTERNET_TOO
-+ bool isInternetPW = false;
-+#endif
-+ OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ NULL, NULL, &itemRef );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Error" << err << "retrieving type for '" << accountName << "' :" << qPrintable(errMsg);
-+#if INTERNET_TOO
-+ if( SecKeychainFindInternetPassword( keychain, 0, NULL,
-+ 0, NULL,
-+ accountName.size(), accountName.constData(),
-+ 0, NULL, 0,
-+ kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
-+ 0, NULL, &itemRef ) ){
-+ // just to be sure:
-+ itemRef = NULL;
-+ }
-+ else{
-+ isInternetPW = true;
-+ err = 0;
-+ errMsg = QString();
-+ }
-+#else
-+ itemRef = NULL;
-+#endif
-+ }
-+ if( itemRef ){
-+ UInt32 tags[] = { kSecTypeItemAttr };
-+ UInt32 formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_STRING };
-+ SecKeychainAttributeInfo attrGet = { 1, tags, formats };
-+ SecKeychainAttributeList *attrList = NULL;
-+ err = SecKeychainItemCopyAttributesAndData( itemRef, &attrGet, NULL, &attrList, NULL, NULL );
-+ if( !err ){
-+ if( attrList->attr[0].length == sizeof(EntryType) ){
-+ memcpy( &etype, attrList->attr[0].data, sizeof(EntryType) );
-+ }
-+ else if( attrList->attr[0].length ){
-+ kDebug() << "Error: key" << key << "item type retrieved is of size" << attrList->attr[0].length << "!=" << sizeof(EntryType);
-+ }
-+#if INTERNET_TOO
-+ else if( isInternetPW ){
-+ // this is just a wild guess ...
-+ etype = Password;
-+ }
-+#endif
-+ if( entryType ){
-+ *entryType = etype;
-+ }
-+ }
-+ SecKeychainItemFreeAttributesAndData( attrList, NULL );
-+ CFRelease(itemRef);
-+ }
-+ kDebug() << "OSXKeychain::ItemType '" << key << "' from keychain " << OSXKeychain::Path(keychain) << "=" << OSTStr(etype) << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::RemoveItem(const QString &key, const SecKeychainRef keychain)
-+{ const QByteArray accountName( key.toUtf8() );
-+ SecKeychainItemRef itemRef;
-+ QString errMsg;
-+ OSStatus result = SecKeychainFindGenericPassword( keychain, 0, NULL,
-+ accountName.size(), accountName.constData(), NULL, NULL, &itemRef );
-+ if( isError( result, &errMsg ) ){
-+ kDebug() << "Could not find entry" << key << ":" << qPrintable(errMsg);
-+ }
-+ else{
-+ const CFReleaser<SecKeychainItemRef> itemReleaser(itemRef);
-+ result = SecKeychainItemDelete(itemRef);
-+ if( isError( result, &errMsg ) ){
-+ kWarning() << "Could not delete entry" << key << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ return result;
-+}
-+
-+OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef, EntryType *entryType, OSXKeychain *osxKeyChain )
-+{ const QByteArray accountName( key.toUtf8() );
-+ OSStatus err;
-+ QString errMsg;
-+ SecKeychainItemRef theItem = NULL;
-+ bool saveLabel;
-+ if( osxKeyChain && osxKeyChain->currentService.size() ){
-+ const QByteArray serviceName( osxKeyChain->currentService.toUtf8() );
-+ // save the "GenericPassword" item using the service name, which appears to be the only way to write
-+ // to the "Where" field shown in the Keychain Utility.
-+ err = basicWriteItem( &serviceName, accountName, value, keychain, &theItem );
-+ // the service (folder!) string will also appear on the "Name" field, which however can be changed
-+ // independently, via the Label attribute.
-+ saveLabel = true;
-+ }
-+ else{
-+ err = basicWriteItem( NULL, accountName, value, keychain, &theItem );
-+ saveLabel = false;
-+ }
-+ if( err == errSecDuplicateItem ){
-+ // RJVB: the previous implementation was wrong. errSecDuplicateItem means the write failed because of an existing item.
-+ // So we have to find that item, and modify it.
-+ if( !(err = ReadItem( key, NULL, keychain, &theItem )) ){
-+ err = SecKeychainItemModifyAttributesAndData( theItem, NULL, value.size(), value.constData() );
-+ if( isError( err, &errMsg ) ){
-+ kDebug() << "Key '" << key
-+ << "'already exists in keychain but error modifying the existing item: " << qPrintable(errMsg);
-+ }
-+ }
-+ if( !err ){
-+ kDebug() << "Key '" << key << "'already existed in keychain: modified the existing item";
-+ }
-+ }
-+ if( !err && saveLabel ){
-+ // store the desired text in the label attribute
-+ SecKeychainAttribute attr = { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set the desired name/label" << accountName
-+ << ":" << err << "=" << qPrintable(errMsg);
-+ }
-+ }
-+ if( !err ){
-+ EntryType defType = Stream;
-+ if( !entryType ){
-+ entryType = &defType;
-+ }
-+ SecKeychainAttribute attr = { kSecTypeItemAttr, sizeof(EntryType), (void*) entryType };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set type to" << OSTStr(*entryType)
-+ << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ if( itemRef ){
-+ *itemRef = theItem;
-+ }
-+ else if( theItem ){
-+ CFRelease(theItem);
-+ }
-+ kDebug() << "OSXKeychain::WriteItem '" << key << "' to keychain " << (void*) keychain << ", error=" << err;
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
-+ const QString &comment, const SecKeychainRef keychain, EntryType *entryType, OSXKeychain *osxKeyChain )
-+{ SecKeychainItemRef itemRef = NULL;
-+ OSStatus err = WriteItem( key, value, keychain, &itemRef, entryType, osxKeyChain );
-+ if( !err && itemRef ){
-+ const QByteArray commentString(comment.toUtf8());
-+ if( commentString.size() ){
-+ SecKeychainAttribute attr = { kSecCommentItemAttr, commentString.size(), (void*) commentString.constData() };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ QString errMsg;
-+ if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
-+ kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't add comment" << comment
-+ << ":" << qPrintable(errMsg);
-+ }
-+ }
-+ CFRelease(itemRef);
-+ }
-+ return err;
-+}
-+
-+// returns the kSecAccountItemAttr's of all items in the keychain
-+OSStatus OSXKeychain::ItemList( SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain )
-+{ OSStatus err;
-+ SecKeychainSearchRef searchRef[2];
-+ bool generateFolderList = ( osxKeyChain && osxKeyChain->isKDEChain && osxKeyChain->generateFolderList );
-+
-+ keyList.clear();
-+ if( generateFolderList ){
-+ osxKeyChain->serviceList.clear();
-+ if( osxKeyChain->currentService.size() > 0 ){
-+ osxKeyChain->serviceList.append(osxKeyChain->currentService);
-+ }
-+ }
-+
-+ err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass, NULL, &searchRef[0] );
-+#if INTERNET_TOO
-+ if( SecKeychainSearchCreateFromAttributes( keychain, kSecInternetPasswordItemClass, NULL, &searchRef[1] ) ){
-+ searchRef[1] = NULL;
-+ }
-+#else
-+ searchRef[1] = NULL;
-+#endif
-+ SecKeychainItemRef item;
-+ QString errMsg;
-+ if( isError(err, &errMsg) ){
-+ kDebug() << "OSXKeychain::ItemList(" << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed" << qPrintable(errMsg);
-+ }
-+ else{
-+ for( size_t i = 0 ; i < sizeof(searchRef)/sizeof(SecKeychainSearchRef) && !err ; ++i ){
-+ if( searchRef[i] ){
-+ while( !(err = SecKeychainSearchCopyNext( searchRef[i], &item )) ){
-+ if( item ){
-+ // whether the item will be listed in the keyList we return: by default it is
-+ // (better an item shows up multiple times than not at all).
-+ bool listItem = true;
-+ SecKeychainAttribute attr = { kSecAccountItemAttr, 0, NULL };
-+ SecKeychainAttributeList attrList = { 1, &attr };
-+ UInt32 len = 0;
-+ if( osxKeyChain && osxKeyChain->isKDEChain ){
-+ // try to fetch the item's ServiceItem attribute
-+ attr.tag = kSecServiceItemAttr;
-+ if( !SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL ) ){
-+ QString lbl = QString::fromUtf8( (char*)attr.data, attr.length );
-+ // we got a service item attribute, which is where we store the kwallet folder info.
-+ // If we disallow empty attributes, keychain items without service item attribute will
-+ // appear in each folder that has a non-empty name. In other words, we allow a folder without name.
-+ if( generateFolderList ){
-+ // add the "folder" to the list if not already listed
-+ if( !osxKeyChain->serviceList.contains(lbl) ){
-+ osxKeyChain->serviceList.append(lbl);
-+ }
-+ }
-+ else{
-+ // only list the item if it's in the current "folder"
-+ listItem = (lbl == osxKeyChain->currentService);
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ }
-+ else{
-+ // errors retrieving the service item attribute are ignored
-+ }
-+ if( listItem ){
-+ attr.tag = kSecAccountItemAttr;
-+ if( !(err = SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL )) ){
-+ if( attr.length > 0 ){
-+ keyList.append(QString::fromUtf8( (char*)attr.data, attr.length ));
-+ }
-+ SecKeychainItemFreeContent( &attrList, NULL );
-+ }
-+ else{
-+ errMsg = errorString(err);
-+ kDebug() << "SecKeychainItemCopyContent returned" << err << "=" << qPrintable(errMsg);
-+ }
-+ }
-+ CFRelease(item);
-+ }
-+ }
-+ if( err ){
-+ errMsg = errorString(err);
-+ }
-+ CFRelease(searchRef[i]);
-+ }
-+ }
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Destroy( SecKeychainRef *keychain )
-+{ OSStatus err = SecKeychainDelete(*keychain);
-+ QString errMsg;
-+ if( isError( err, &errMsg ) ){
-+ kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error " << qPrintable(errMsg);
-+ }
-+ else{
-+ kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error=" << err;
-+ }
-+ if( keychain ){
-+ CFRelease(*keychain);
-+ *keychain = NULL;
-+ }
-+ return err;
-+}
-+
-+OSStatus OSXKeychain::Destroy( const QString &walletName )
-+{ SecKeychainRef keychain;
-+ OSStatus err = openKeychain( walletName, &keychain );
-+ if( !err && keychain ){
-+ err = Destroy(&keychain);
-+ }
-+ return err;
-+}
-diff -urN kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.h kdelibs-4.13.3/kdeui/util/qosxkeychain.h
---- kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.h 1970-01-01 09:00:00.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/qosxkeychain.h 2014-09-22 19:47:04.000000000 +0900
-@@ -0,0 +1,278 @@
-+/*
-+ * @file qosxkeychain.h
-+ * This file is part of the KDE project
-+ *
-+ * Created by René J.V. Bertin on 20140809.
-+ * Copyright 2014 RJVB.
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Library General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Library General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Library General Public License
-+ * along with this library; see the file COPYING.LIB. If not, write to
-+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ * Boston, MA 02110-1301, USA.
-+ */
-+
-+#ifndef _QOSXKEYCHAIN_H
-+
-+#include <Security/Security.h>
-+#include <Security/SecKeychain.h>
-+
-+namespace {
-+ template <typename T>
-+ struct CFReleaser {
-+ explicit CFReleaser( const T& r ) : ref( r ) {}
-+ ~CFReleaser() { if( ref ){ CFRelease( ref ); } }
-+ T ref;
-+ };
-+
-+ template <typename T>
-+ struct CPPDeleter {
-+ explicit CPPDeleter( const T& r ) : ptr( r ) {}
-+ ~CPPDeleter() { if( ptr ){ delete ptr; } }
-+ T ptr;
-+ };
-+
-+ template <typename T>
-+ struct CPPArrayDeleter {
-+ explicit CPPArrayDeleter( const T& r ) : ptr( r ) {}
-+ ~CPPArrayDeleter() { if( ptr ){ delete[] ptr; } }
-+ T ptr;
-+ };
-+
-+ template <typename T>
-+ struct CacheOldValue {
-+ explicit CacheOldValue( T &var, const T newVal )
-+ : oldVal(var), varRef(var)
-+ {
-+ var = newVal;
-+ }
-+ ~CacheOldValue()
-+ {
-+ varRef = oldVal;
-+ }
-+ T oldVal, &varRef;
-+ };
-+}
-+
-+static inline QString asQString( CFStringRef sr )
-+{
-+ if( sr ){
-+ CFIndex len = CFStringGetLength(sr)*2;
-+ const CPPArrayDeleter<char*> buff(new char[len]);
-+ if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingUTF8 ) ){
-+ return QString::fromUtf8(buff.ptr); //RJVB: use UTF8
-+ }
-+ else if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingNonLossyASCII ) ){
-+ return QString::fromLocal8Bit(buff.ptr);
-+ }
-+ else{
-+ CFStringGetCString( sr, buff.ptr, len, NULL );
-+ return QString::fromLatin1(buff.ptr);
-+ }
-+ }
-+ else{
-+ return QString();
-+ }
-+}
-+
-+static inline QString errorString( OSStatus s )
-+{
-+ const CFReleaser<CFStringRef> ref( SecCopyErrorMessageString( s, NULL ) );
-+ return asQString( ref.ref );
-+}
-+
-+static inline bool isError( OSStatus s, QString *errMsg )
-+{
-+ if( errMsg ){
-+ *errMsg = errorString(s);
-+ }
-+ return s != 0;
-+}
-+
-+class OSXKeychain : public QObject
-+{
-+ Q_OBJECT
-+private:
-+ SecKeychainRef keyChainRef;
-+ QString keyChainPath;
-+ bool isDefaultKeychain, generateFolderList;
-+
-+public:
-+ enum EntryType { Unknown='K\?\?\?', Password='KPWD', Map='KMAP', Stream='KSTR' };
-+ QString name;
-+ QString currentService, lastReadService;
-+ QStringList serviceList;
-+ bool isKDEChain;
-+
-+ OSXKeychain();
-+ OSXKeychain(const QString &name, bool *isNew=NULL);
-+ virtual ~OSXKeychain();
-+
-+ inline SecKeychainRef reference()
-+ {
-+ return keyChainRef;
-+ }
-+ inline QString &path()
-+ {
-+ return keyChainPath;
-+ }
-+ inline bool isDefault()
-+ {
-+ return isDefaultKeychain;
-+ }
-+ inline bool isOpen()
-+ {
-+ // we're either a KDE wallet/keychain and we have a valid keyChainRef,
-+ // or we're not KDE and IsOpen will return the state of the default
-+ // keychain if keyChainRef==NULL.
-+ if( !isKDEChain || keyChainRef ){
-+ return IsOpen(keyChainRef);
-+ }
-+ else{
-+ return false;
-+ }
-+ }
-+ inline OSStatus lock()
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return Lock(keyChainRef);
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus unLock()
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return UnLock(keyChainRef);
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ virtual void close();
-+ OSStatus lockSettings(int &closeWhenIdle, unsigned int &idleTimeoutMin);
-+ OSStatus setLockSettings(int closeWhenIdle, unsigned int idleTimeoutMin);
-+ inline bool hasItem(const QString &key, OSStatus *errReturn, SecKeychainItemRef *itemRef=NULL)
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return OSXKeychain::HasItem( key, keyChainRef, errReturn, itemRef );
-+ }
-+ else{
-+ return false;
-+ }
-+ }
-+ inline OSStatus readItem(const QString &key, QByteArray *value, SecKeychainItemRef *itemRef=NULL)
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return ReadItem( key, value, keyChainRef, itemRef, this );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus itemType(const QString &key, EntryType *entryType)
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return ItemType( key, entryType, keyChainRef );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus removeItem(const QString &key)
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return RemoveItem( key, keyChainRef );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus writeItem( const QString &key, const QByteArray &value, EntryType *entryType=NULL )
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return WriteItem( key, value, keyChainRef, NULL, entryType, this );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus writeItem( const QString &key, const QByteArray &value, const QString &comment,
-+ EntryType *entryType=NULL )
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return WriteItem( key, value, comment, keyChainRef, entryType, this );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline OSStatus itemList( QStringList &keyList )
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ return ItemList( keyChainRef, keyList, this );
-+ }
-+ else{
-+ return 0;
-+ }
-+ }
-+ inline QStringList folderList()
-+ {
-+ if( !isKDEChain || keyChainRef ){
-+ QStringList r;
-+ CacheOldValue<bool> gFL(generateFolderList, true);
-+ ItemList( keyChainRef, r, this );
-+ r.clear();
-+ return serviceList;
-+ }
-+ else{
-+ return QStringList();
-+ }
-+ }
-+ OSStatus renameItem(const QString ¤tKey, const QString &newKey);
-+
-+#pragma mark ==== class methods aka static member functions ====
-+ static OSStatus KeychainList(QStringList &theList);
-+ static QString Path(const SecKeychainRef keychain);
-+ static bool IsOpen(const SecKeychainRef keychain);
-+ static bool IsOpen(const QString& name);
-+ static OSStatus UnLock(const SecKeychainRef keychain);
-+ static OSStatus Lock(const SecKeychainRef keychain);
-+ static OSStatus Lock(const QString &walletName);
-+ /** use the keychain search functions to find the first matching item, if any, returning True if found.
-+ The OS X error code is returned through @p errReturn when not NULL, the item itself through @p itemRef.
-+ This reference will have to be released with CFRelease() when done with it (when @p itemRef==NULL the
-+ function does this release itself).
-+ */
-+ static bool HasItem(const QString &key,
-+ const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef);
-+ static OSStatus ReadItem(const QString &key, QByteArray *value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, OSXKeychain *osxKeyChain=NULL);
-+ static OSStatus ItemType(const QString &key, EntryType *entryType,
-+ const SecKeychainRef keychain);
-+ static OSStatus RemoveItem(const QString &key, const SecKeychainRef keychain);
-+ static OSStatus WriteItem( const QString &key, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, EntryType *entryType=NULL, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus WriteItem( const QString& key, const QByteArray& value,
-+ const QString& comment, const SecKeychainRef keychain, EntryType *entryType, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus ItemList( const SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus Destroy( SecKeychainRef *keychain );
-+ static OSStatus Destroy( const QString &walletName );
-+
-+private Q_SLOTS:
-+ virtual void slotIdleTimedOut()
-+ {}
-+};
-+
-+#define _QOSXKEYCHAIN_H
-+#endif
-\ No newline at end of file
-diff -urN kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.h.orig kdelibs-4.13.3/kdeui/util/qosxkeychain.h.orig
---- kdelibs-4.13.3-orig/kdeui/util/qosxkeychain.h.orig 1970-01-01 09:00:00.000000000 +0900
-+++ kdelibs-4.13.3/kdeui/util/qosxkeychain.h.orig 2014-09-22 19:46:10.000000000 +0900
-@@ -0,0 +1,203 @@
-+/*
-+ * @file qosxkeychain.h
-+ * This file is part of the KDE project
-+ *
-+ * Created by René J.V. Bertin on 20140809.
-+ * Copyright 2014 RJVB.
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Library General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Library General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Library General Public License
-+ * along with this library; see the file COPYING.LIB. If not, write to
-+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ * Boston, MA 02110-1301, USA.
-+ */
-+
-+#include <Security/Security.h>
-+#include <Security/SecKeychain.h>
-+
-+namespace {
-+ template <typename T>
-+ struct CFReleaser {
-+ explicit CFReleaser( const T& r ) : ref( r ) {}
-+ ~CFReleaser() { if( ref ){ CFRelease( ref ); } }
-+ T ref;
-+ };
-+
-+ template <typename T>
-+ struct CPPDeleter {
-+ explicit CPPDeleter( const T& r ) : ptr( r ) {}
-+ ~CPPDeleter() { if( ptr ){ delete ptr; } }
-+ T ptr;
-+ };
-+
-+ template <typename T>
-+ struct CPPArrayDeleter {
-+ explicit CPPArrayDeleter( const T& r ) : ptr( r ) {}
-+ ~CPPArrayDeleter() { if( ptr ){ delete[] ptr; } }
-+ T ptr;
-+ };
-+
-+ template <typename T>
-+ struct CacheOldValue {
-+ explicit CacheOldValue( T &var, const T newVal )
-+ : oldVal(var), varRef(var)
-+ {
-+ var = newVal;
-+ }
-+ ~CacheOldValue()
-+ {
-+ varRef = oldVal;
-+ }
-+ T oldVal, &varRef;
-+ };
-+}
-+
-+static inline QString asQString( CFStringRef sr )
-+{ CFIndex len = CFStringGetLength(sr)*2;
-+ const CPPArrayDeleter<char*> buff(new char[len]);
-+ if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingUTF8 ) ){
-+ return QString::fromUtf8(buff.ptr); //RJVB: use UTF8
-+ }
-+ else if( CFStringGetCString( sr, buff.ptr, len, kCFStringEncodingNonLossyASCII ) ){
-+ return QString::fromLocal8Bit(buff.ptr);
-+ }
-+ else{
-+ CFStringGetCString( sr, buff.ptr, len, NULL );
-+ return QString::fromLatin1(buff.ptr);
-+ }
-+}
-+
-+static inline QString errorString( OSStatus s )
-+{
-+ const CFReleaser<CFStringRef> ref( SecCopyErrorMessageString( s, NULL ) );
-+ return asQString( ref.ref );
-+}
-+
-+static inline bool isError( OSStatus s, QString *errMsg )
-+{
-+ if( errMsg ){
-+ *errMsg = errorString(s);
-+ }
-+ return s != 0;
-+}
-+
-+class OSXKeychain
-+{
-+private:
-+ SecKeychainRef keyChainRef;
-+ QString keyChainPath;
-+ bool isDefaultKeychain, generateFolderList;
-+
-+public:
-+ enum EntryType { Unknown='K\?\?\?', Password='KPWD', Map='KMAP', Stream='KSTR' };
-+ QString name;
-+ QString currentService, lastReadService;
-+ QStringList serviceList;
-+ bool isKDEChain;
-+
-+ OSXKeychain();
-+ OSXKeychain(const QString &name);
-+ virtual ~OSXKeychain();
-+
-+ inline SecKeychainRef reference()
-+ {
-+ return keyChainRef;
-+ }
-+ inline QString &path()
-+ {
-+ return keyChainPath;
-+ }
-+ inline bool isDefault()
-+ {
-+ return isDefaultKeychain;
-+ }
-+ inline bool isOpen()
-+ {
-+ return IsOpen(keyChainRef);
-+ }
-+ inline OSStatus lock()
-+ {
-+ return Lock(keyChainRef);
-+ }
-+ inline OSStatus unLock()
-+ {
-+ return UnLock(keyChainRef);
-+ }
-+ void close();
-+ inline bool hasItem(const QString &key, OSStatus *errReturn, SecKeychainItemRef *itemRef=NULL)
-+ {
-+ // qDebug() << "OSXKeychain::hasItem(" << key << "): scanning '" << name << "'=" << (void*) keyChainRef;
-+ return OSXKeychain::HasItem( key, keyChainRef, errReturn, itemRef );
-+ }
-+ inline OSStatus readItem(const QString &key, QByteArray *value, SecKeychainItemRef *itemRef=NULL)
-+ {
-+ return ReadItem( key, value, keyChainRef, itemRef, this );
-+ }
-+ inline OSStatus itemType(const QString &key, EntryType *entryType)
-+ {
-+ return ItemType( key, entryType, keyChainRef );
-+ }
-+ inline OSStatus removeItem(const QString &key)
-+ {
-+ return RemoveItem( key, keyChainRef );
-+ }
-+ inline OSStatus writeItem( const QString &key, const QByteArray &value, EntryType *entryType=NULL )
-+ {
-+ return WriteItem( key, value, keyChainRef, NULL, entryType, this );
-+ }
-+ inline OSStatus writeItem( const QString &key, const QByteArray &value, const QString &comment,
-+ EntryType *entryType=NULL )
-+ {
-+ return WriteItem( key, value, comment, keyChainRef, entryType, this );
-+ }
-+ inline OSStatus itemList( QStringList &keyList )
-+ {
-+ return ItemList( keyChainRef, keyList, this );
-+ }
-+ inline QStringList folderList()
-+ {
-+ QStringList r;
-+ CacheOldValue<bool> gFL(generateFolderList, true);
-+ ItemList( keyChainRef, r, this );
-+ r.clear();
-+ return serviceList;
-+ }
-+ OSStatus renameItem(const QString ¤tKey, const QString &newKey);
-+
-+#pragma mark ==== class methods aka static member functions ====
-+ static OSStatus KeychainList(QStringList &theList);
-+ static QString Path(const SecKeychainRef keychain);
-+ static bool IsOpen(const SecKeychainRef keychain);
-+ static bool IsOpen(const QString& name);
-+ static OSStatus UnLock(const SecKeychainRef keychain);
-+ static OSStatus Lock(const SecKeychainRef keychain);
-+ static OSStatus Lock(const QString &walletName);
-+ /** use the keychain search functions to find the first matching item, if any, returning True if found.
-+ The OS X error code is returned through @p errReturn when not NULL, the item itself through @p itemRef.
-+ This reference will have to be released with CFRelease() when done with it (when @p itemRef==NULL the
-+ function does this release itself).
-+ */
-+ static bool HasItem(const QString &key,
-+ const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef);
-+ static OSStatus ReadItem(const QString &key, QByteArray *value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, OSXKeychain *osxKeyChain=NULL);
-+ static OSStatus ItemType(const QString &key, EntryType *entryType,
-+ const SecKeychainRef keychain);
-+ static OSStatus RemoveItem(const QString &key, const SecKeychainRef keychain);
-+ static OSStatus WriteItem( const QString &key, const QByteArray &value,
-+ const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, EntryType *entryType=NULL, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus WriteItem( const QString& key, const QByteArray& value,
-+ const QString& comment, const SecKeychainRef keychain, EntryType *entryType, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus ItemList( const SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain=NULL );
-+ static OSStatus Destroy( SecKeychainRef *keychain );
-+ static OSStatus Destroy( const QString &walletName );
-+};
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20141220/78e84864/attachment-0001.html>
More information about the macports-changes
mailing list