[126340] trunk/dports/kde/kdelibs4

nicos at macports.org nicos at macports.org
Wed Oct 8 04:03:41 PDT 2014


Revision: 126340
          https://trac.macports.org/changeset/126340
Author:   nicos at macports.org
Date:     2014-10-08 04:03:41 -0700 (Wed, 08 Oct 2014)
Log Message:
-----------
kdelibs4: update to 4.13.3
add patches
review dependencies

Modified Paths:
--------------
    trunk/dports/kde/kdelibs4/Portfile

Added Paths:
-----------
    trunk/dports/kde/kdelibs4/files/patch-KdePreferences.diff
    trunk/dports/kde/kdelibs4/files/patch-authBackends.diff
    trunk/dports/kde/kdelibs4/files/patch-fixKCrash.diff
    trunk/dports/kde/kdelibs4/files/patch-nativeDialogs.diff

Removed Paths:
-------------
    trunk/dports/kde/kdelibs4/files/patch-cmake-modules-KDE4Macros.cmake.diff

Modified: trunk/dports/kde/kdelibs4/Portfile
===================================================================
--- trunk/dports/kde/kdelibs4/Portfile	2014-10-08 10:38:21 UTC (rev 126339)
+++ trunk/dports/kde/kdelibs4/Portfile	2014-10-08 11:03:41 UTC (rev 126340)
@@ -5,8 +5,7 @@
 PortGroup           kde4   1.1
 
 name                kdelibs4
-version             4.12.5
-revision            3
+version             4.13.3
 categories          kde kde4
 maintainers         nicos
 license             LGPL-2+ GPL-2+ BSD
@@ -18,8 +17,8 @@
 use_xz              yes
 distname            kdelibs-${version}
 
-checksums           rmd160  aa0bb8fb44d6c49ddd8787c4cb79c1f1bdd331b8 \
-                    sha256  9711c3a3d29387dc8b40425cc2957e9f1f2d747d83e9e0213bb8ff6638e68e09
+checksums           rmd160  8db76ec77ed09d180223fb3a37b38e8ca8798d75 \
+                    sha256  d291b4bc159a3f686ad93ff3dfbe90a0a7e33600357e8390c84154ec050efc82
 
 #No binary links to openssl libraries, apart from libkio.dylib at
 #runtime if required. As libkio.dylib code is purely LGPL, there is no
@@ -29,14 +28,12 @@
 depends_build-append port:flex port:gmake port:docbook-xsl-ns
 
 depends_lib-append  port:bzip2 port:zlib \
-                    port:soprano port:cyrus-sasl2 \
+                    port:soprano \
                     port:strigi port:gettext \
                     port:pcre port:shared-mime-info \
-                    lib:libgif:giflib port:tiff \
+                    lib:libgif:giflib \
                     port:jpeg port:libpng \
                     port:jasper port:openexr \
-                    port:expat port:libart_lgpl \
-                    port:libidn port:libiconv \
                     path:lib/pkgconfig/glib-2.0.pc:glib2 \
                     port:openssl port:enchant \
                     port:aspell port:aspell-dict-en \
@@ -45,8 +42,9 @@
                     port:libxml2 port:libxslt \
                     port:dbusmenu-qt port:docbook-xml \
                     port:docbook-xsl port:grantlee \
-                    port:kerberos5 \
-                    port:shared-desktop-ontologies
+                    port:kerberos5 port:bison \
+                    port:shared-desktop-ontologies \
+                    port:perl5
 
 # the aspell dictionaries are just files
 depends_skip_archcheck aspell-dict-en
@@ -59,8 +57,10 @@
 #add-bundles-to-path: improve support for KIO slaves by adding a search path
 #kapplications-raster: ensures that kde applications start in raster (faster) mode, but also provides a switch for non-working applications
 #removeFindFlex: remove FindFlex.cmake which may hide the working one of cmake (ticket #44119)
-#patch-cmake-modules-FindKDE4-Internal.cmake: Fixes zlib detection (see ticket #24128)
-#patch-cmake-modules-KDE4Macros.cmake: Ensures that compiled objects are properly detected during build (see ticket #43720)
+#cmake-modules-FindKDE4-Internal.cmake: Fixes zlib detection (see ticket #24128)
+#fixKCrash: Fix issues in the KDE reporting system on OSX (see https://git.reviewboard.kde.org/r/119497/, committed upstream)
+#nativeDialogs: Use native mac dialogs (see https://reviewboard.kde.org/r/119243/)
+#KdePreferences: Handles menus to be closer to standard Mac layout (see https://reviewboard.kde.org/r/120149/)
 
 patchfiles           workaround-kdeinit4-crash.patch \
                      avoid-kwindowinfo-destructor.patch \
@@ -69,7 +69,9 @@
                      patch-kapplications-raster.diff \
                      patch-removeFindFlex.diff \
                      patch-cmake-modules-FindKDE4-Internal.cmake.diff \
-                     patch-cmake-modules-KDE4Macros.cmake.diff
+                     patch-fixKCrash.diff \
+                     patch-nativeDialogs.diff \
+                     patch-KdePreferences.diff
 
 patch.pre_args      -p1
 
@@ -144,6 +146,12 @@
 To start it run the following command:
  launchctl load -w ${startup_root}/Library/LaunchAgents/org.macports.kdecache.plist"
 
+#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.} {
     pre-fetch {
         if { ${install.user}=="root" || ${install.group}=="wheel" } {

Added: trunk/dports/kde/kdelibs4/files/patch-KdePreferences.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-KdePreferences.diff	                        (rev 0)
+++ trunk/dports/kde/kdelibs4/files/patch-KdePreferences.diff	2014-10-08 11:03:41 UTC (rev 126340)
@@ -0,0 +1,113 @@
+diff -ur kdelibs-4.13.3-orig/kdeui/actions/kaction.cpp kdelibs-4.13.3/kdeui/actions/kaction.cpp
+--- kdelibs-4.13.3-orig/kdeui/actions/kaction.cpp	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kdeui/actions/kaction.cpp	2014-09-20 23:58:07.000000000 +0900
+@@ -142,11 +142,52 @@
+   d->init(this);
+ }
+ 
++#ifdef Q_OS_MAC
++
++#include <QMenuBar>
++#include <kaboutdata.h>
++
++static void setTextWithCorrectMenuRole( KAction *action, const QString &text )
++{
++    // texts containing "config, options, setup, settings or preferences" will get PreferencesRole
++    // from Qt unless they have a role set. We prevent that, because KDE has its own way of
++    // defining a the application preferences menu ("Configure <appName>") which should go under the OS X Preferences menu.
++    // But when a KAction is created with the standard preferences title ("Configure <appName>..."), this action
++    // is set to PreferencesRole .
++    // The compare actions using QMenuBar::tr are copied from Qt's own qmenu_mac.mm :
++    action->setText(text);
++    const KAboutData *aboutData = KGlobal::mainComponent().aboutData();
++    QString appName = i18n( "%1...", (aboutData) ? aboutData->programName() : qApp->applicationName() );
++    if( text.startsWith(QMenuBar::tr("Config").toLower()) ||  text.startsWith( "&" % QMenuBar::tr("Config").toLower()) ){
++        if( text.endsWith(appName) ){
++            kDebug() << "### Setting QAction::PreferencesRole from" << action->menuRole() << "for menuAction with text" << text;
++            action->setMenuRole(QAction::PreferencesRole);
++        }
++        else{
++            kDebug() << "### Setting QAction::NoRole from" << action->menuRole() << "for menuAction with text" << text;
++            action->setMenuRole(QAction::NoRole);
++        }
++    }
++    else if( text.contains(QMenuBar::tr("Options").toLower())
++        || text.contains(QMenuBar::tr("Setup").toLower())
++        || text.contains(QMenuBar::tr("Settings").toLower())
++        || text.contains(QMenuBar::tr("Preferences").toLower())
++    ){
++        kDebug() << "### Setting QAction::NoRole from" << action->menuRole() << "for menuAction with text" << text;
++        action->setMenuRole(QAction::NoRole);
++    }
++}
++#endif //Q_OS_MAC
++
+ KAction::KAction(const QString &text, QObject *parent)
+   : QWidgetAction(parent), d(new KActionPrivate)
+ {
+   d->init(this);
++#ifdef Q_OS_MAC
++  setTextWithCorrectMenuRole(this, text);
++#else
+   setText(text);
++#endif
+ }
+ 
+ KAction::KAction(const KIcon &icon, const QString &text, QObject *parent)
+@@ -154,7 +195,11 @@
+ {
+   d->init(this);
+   setIcon(icon);
++#ifdef Q_OS_MAC
++  setTextWithCorrectMenuRole(this, text);
++#else
+   setText(text);
++#endif
+ }
+ 
+ KAction::~KAction()
+diff -ur kdelibs-4.13.3-orig/kdeui/notifications/kstatusnotifieritem.cpp kdelibs-4.13.3/kdeui/notifications/kstatusnotifieritem.cpp
+--- kdelibs-4.13.3-orig/kdeui/notifications/kstatusnotifieritem.cpp	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kdeui/notifications/kstatusnotifieritem.cpp	2014-09-20 23:58:14.000000000 +0900
+@@ -683,6 +683,9 @@
+ 
+         return false;
+     }
++#else
++    Q_UNUSED(pos);
++    Q_UNUSED(perform);
+ #endif
+ 
+     return true;
+@@ -722,6 +725,10 @@
+ {
+ }
+ 
++#ifdef Q_OS_MAC
++#   include <kconfiggroup.h>
++#endif
++
+ void KStatusNotifierItemPrivate::init(const QString &extraId)
+ {
+     // Ensure that closing the last KMainWindow doesn't exit the application
+@@ -745,8 +752,20 @@
+ 
+     //create a default menu, just like in KSystemtrayIcon
+     KMenu *m = new KMenu(associatedWidget);
++#ifdef Q_OS_MAC
++    // emulate addTitle/setTitle by adding an inactive menu item.
++    titleAction = m->addAction( qApp->windowIcon(), KGlobal::mainComponent().aboutData()->programName() );
++    titleAction->setEnabled(false);
++    titleAction->setIconVisibleInMenu(true);
++    m->addAction( titleAction );
++    m->addSeparator();
++    kDebug() << "### Added SystemTray titleAction=" << titleAction;
++    kDebug() << "### SystemTray for app" << qApp << "=" << KGlobal::mainComponent().aboutData()->programName()
++        << "/" << KGlobal::caption() << "with icon" << qApp->windowIcon().name();
++#else
+     titleAction = m->addTitle(qApp->windowIcon(), KGlobal::caption());
+     m->setTitle(KGlobal::mainComponent().aboutData()->programName());
++#endif
+     q->setContextMenu(m);
+ 
+     KStandardAction::quit(q, SLOT(maybeQuit()), actionCollection);

Added: trunk/dports/kde/kdelibs4/files/patch-authBackends.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-authBackends.diff	                        (rev 0)
+++ trunk/dports/kde/kdelibs4/files/patch-authBackends.diff	2014-10-08 11:03:41 UTC (rev 126340)
@@ -0,0 +1,4535 @@
+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 &currentKey, 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 &currentKey, 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 &currentKey, 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 &currentKey, 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 );
++};

Deleted: trunk/dports/kde/kdelibs4/files/patch-cmake-modules-KDE4Macros.cmake.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-cmake-modules-KDE4Macros.cmake.diff	2014-10-08 10:38:21 UTC (rev 126339)
+++ trunk/dports/kde/kdelibs4/files/patch-cmake-modules-KDE4Macros.cmake.diff	2014-10-08 11:03:41 UTC (rev 126340)
@@ -1,14 +0,0 @@
---- kdelibs-4.12.5/cmake/modules/KDE4Macros.cmake.orig	2014-04-28 13:37:51.000000000 +0900
-+++ kdelibs-4.12.5/cmake/modules/KDE4Macros.cmake	2014-05-16 21:32:41.000000000 +0900
-@@ -829,9 +829,9 @@
- 
-       if (Q_WS_MAC)
- 	      list(FIND _SRCS *.icns _icon_position)
--	      if(NOT _res_position EQUAL -1)
-+	      if(NOT _icon_position EQUAL -1)
- 		      list(GET _SRCS ${_icon_position} _resourcefile)
--	      endif(NOT _res_position EQUAL -1)
-+	      endif(NOT _icon_position EQUAL -1)
-       endif (Q_WS_MAC)
-       kde4_add_executable(${_target_NAME} "${_nogui}" ${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}_dummy.cpp ${_resourcefile})
-       target_link_libraries(${_target_NAME} kdeinit_${_target_NAME})

Added: trunk/dports/kde/kdelibs4/files/patch-fixKCrash.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-fixKCrash.diff	                        (rev 0)
+++ trunk/dports/kde/kdelibs4/files/patch-fixKCrash.diff	2014-10-08 11:03:41 UTC (rev 126340)
@@ -0,0 +1,41 @@
+diff -ur kdelibs-4.13.3-orig/kdeui/util/kcrash.cpp kdelibs-4.13.3/kdeui/util/kcrash.cpp
+--- kdelibs-4.13.3-orig/kdeui/util/kcrash.cpp	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kdeui/util/kcrash.cpp	2014-09-20 15:20:58.000000000 +0900
+@@ -313,7 +313,13 @@
+         crashRecursionCounter++;
+     }
+ 
+-#if !defined(Q_OS_WIN)
++    // On Apple OS X, closing all FDs now will cause a second (SIGILL) crash,
++    // ending with "Unable to start Dr. Konqi". This is because the libdispatch
++    // library, which can manage multi-threading, has some FDs of its own.
++    //
++    // Note: KCrash closes FDs unconditionally later on if it forks to Dr Konqi
++    //       and this program's FDs do not matter if kdeinit starts Dr Konqi.
++#if !defined(Q_OS_WIN) and !defined(Q_OS_MAC)
+     if (!(s_flags & KeepFDs))
+         closeAllFDs();
+ # if defined(Q_WS_X11)
+@@ -520,9 +526,12 @@
+     // This is done because it is dangerous to use fork() in the crash handler
+     // (there can be functions registered to be performed before fork(), for example handling
+     // of malloc locking, which doesn't work when malloc crashes because of heap corruption).
++#ifndef Q_OS_MAC
++    // Fails on Apple OSX+KDE4, because kdeinit4 is using the wrong socket name.
+     if (!(s_flags & AlwaysDirectly)) {
+         startDirectly = !startProcessInternal(argc, argv, waitAndExit, false);
+     }
++#endif
+ 
+     // If we can't reach kdeinit, we can still at least try to fork()
+     if (startDirectly) {
+@@ -805,7 +814,8 @@
+ 
+   server.sun_family = AF_UNIX;
+   strcpy(server.sun_path, sock_file);
+-  printf("sock_file=%s\n", sock_file);
++  // Use stderr, to make the message visible on the Apple OS X Console log.
++  fprintf(stderr, "KCrash: Connect sock_file=%s\n", sock_file);
+   socklen = sizeof(server);
+   if(connect(s, (struct sockaddr *)&server, socklen) == -1)
+   {

Added: trunk/dports/kde/kdelibs4/files/patch-nativeDialogs.diff
===================================================================
--- trunk/dports/kde/kdelibs4/files/patch-nativeDialogs.diff	                        (rev 0)
+++ trunk/dports/kde/kdelibs4/files/patch-nativeDialogs.diff	2014-10-08 11:03:41 UTC (rev 126340)
@@ -0,0 +1,77 @@
+diff -ur kdelibs-4.13.3-orig/kdeui/widgets/kmainwindow.cpp kdelibs-4.13.3/kdeui/widgets/kmainwindow.cpp
+--- kdelibs-4.13.3-orig/kdeui/widgets/kmainwindow.cpp	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kdeui/widgets/kmainwindow.cpp	2014-09-20 18:52:54.000000000 +0900
+@@ -241,6 +241,8 @@
+ 
+     q->setAttribute( Qt::WA_DeleteOnClose );
+ 
++    q->setUnifiedTitleAndToolBarOnMac(true);
++
+     // We handle this functionality (quitting the app) ourselves, with KGlobal::ref/deref.
+     // This makes apps stay alive even if they only have a systray icon visible, or
+     // a progress widget with "keep open" checked, for instance.
+diff -ur kdelibs-4.13.3-orig/kio/kfile/kfiledialog.cpp kdelibs-4.13.3/kio/kfile/kfiledialog.cpp
+--- kdelibs-4.13.3-orig/kio/kfile/kfiledialog.cpp	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kio/kfile/kfiledialog.cpp	2014-09-20 18:52:54.000000000 +0900
+@@ -44,8 +44,8 @@
+ #include "krecentdirs.h"
+ #include "kservice.h"
+ 
+-/** File dialogs are native by default on Windows. */
+-#if defined(Q_WS_WIN) || defined(Q_WS_MAEMO_5)
++/** File dialogs are native by default on Windows and Mac. */
++#if defined(Q_WS_WIN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAC)
+ const bool NATIVE_FILEDIALOGS_BY_DEFAULT = true;
+ #else
+ const bool NATIVE_FILEDIALOGS_BY_DEFAULT = false;
+@@ -252,7 +252,7 @@
+ 
+ KFileDialog::KFileDialog( const KUrl& startDir, const QString& filter,
+                           QWidget *parent, QWidget* customWidget)
+-#ifdef Q_WS_WIN
++#if (defined Q_WS_WIN || defined Q_WS_MAC )
+     : KDialog( parent , Qt::WindowMinMaxButtonsHint),
+ #else
+     : KDialog( parent ),
+@@ -312,8 +312,8 @@
+     connect(fileQWidget, SIGNAL(accepted()), SLOT(accept()));
+     //connect(fileQWidget, SIGNAL(canceled()), SLOT(slotCancel()));
+ 
+-    if (customWidget)
+-     d->w->setCustomWidget(QString(), customWidget);
++    if (customWidget){}
++     //d->w->setCustomWidget(QString(), customWidget);
+ }
+ 
+ 
+@@ -961,7 +961,7 @@
+     return d->w;
+ }
+ 
+-#ifdef Q_WS_WIN
++#if (defined Q_WS_WIN || defined Q_WS_MAC)
+ int KFileDialog::exec()
+ {
+     if (!d->native || !KFileDialogPrivate::Native::s_allowNative) {
+@@ -1051,7 +1051,7 @@
+ 
+     return res;
+ }
+-#endif // Q_WS_WIN
++#endif // Q_WS_WIN || Q_WS_MAC
+ 
+ #ifdef Q_WS_WIN
+ #define KF_EXTERN extern __declspec(dllimport)
+diff -ur kdelibs-4.13.3-orig/kio/kfile/kfiledialog.h kdelibs-4.13.3/kio/kfile/kfiledialog.h
+--- kdelibs-4.13.3-orig/kio/kfile/kfiledialog.h	2014-07-11 15:42:13.000000000 +0900
++++ kdelibs-4.13.3/kio/kfile/kfiledialog.h	2014-09-20 18:52:54.000000000 +0900
+@@ -749,7 +749,8 @@
+      */
+     static void setStartDir( const KUrl& directory );
+ 
+-#ifdef Q_WS_WIN
++#if (defined Q_WS_WIN || defined Q_WS_MAC )
++    /** File dialogs are native by default on Windows and MAC. */
+ public Q_SLOTS:
+     int exec();
+ #endif
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20141008/fd6083ce/attachment-0001.html>


More information about the macports-changes mailing list