• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

kwallet_mac.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2002-2004 George Staikos <staikos@kde.org>
00004  * Copyright (C) 2008 Michael Leupold <lemma@confuego.org>
00005  * Copyright (C) 2010 Frank Osterfeld <osterfeld@kde.org>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public License
00018  * along with this library; see the file COPYING.LIB.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include "kwallet.h"
00024 #include <ksharedconfig.h>
00025 #include <kdebug.h>
00026 #include <kdeversion.h>
00027 #include <QtGui/QApplication>
00028 #include <QtCore/QPointer>
00029 #include <QtGui/QWidget>
00030 #include <ktoolinvocation.h>
00031 
00032 #include <kglobal.h>
00033 #include <kcomponentdata.h>
00034 #include <kaboutdata.h>
00035 #include <kconfiggroup.h>
00036 
00037 #include <cassert>
00038 
00039 #include <Carbon/Carbon.h>
00040 #include <Security/Security.h>
00041 #include <Security/SecKeychain.h>
00042 
00043 using namespace KWallet;
00044 
00045 typedef QMap<QString, QString> StringStringMap;
00046 Q_DECLARE_METATYPE(StringStringMap)
00047 typedef QMap<QString, StringStringMap> StringToStringStringMapMap;
00048 Q_DECLARE_METATYPE(StringToStringStringMapMap)
00049 typedef QMap<QString, QByteArray> StringByteArrayMap;
00050 Q_DECLARE_METATYPE(StringByteArrayMap)
00051 
00052 namespace {
00053     template <typename T>
00054     struct CFReleaser {
00055         explicit CFReleaser( const T& r ) : ref( r ) {}
00056         ~CFReleaser() { CFRelease( ref ); }
00057         T ref;
00058     };
00059 }
00060 
00061 static QString asQString( CFStringRef sr ) {
00062     return QString::fromLatin1( CFStringGetCStringPtr( sr, NULL ) ); //TODO Latin1 correct?
00063 }
00064 
00065 static QString errorString( OSStatus s ) {
00066     const CFReleaser<CFStringRef> ref( SecCopyErrorMessageString( s, NULL ) );
00067     return asQString( ref.ref );
00068 }
00069 
00070 static bool isError( OSStatus s, QString* errMsg ) {
00071     if ( errMsg )
00072         *errMsg = errorString( s );
00073     return s != 0;
00074 }
00075 
00076 static QString appid()
00077 {
00078     KComponentData cData = KGlobal::mainComponent();
00079     if (cData.isValid()) {
00080         const KAboutData* aboutData = cData.aboutData();
00081         if (aboutData) {
00082             return aboutData->programName();
00083         }
00084         return cData.componentName();
00085     }
00086     return qApp->applicationName();
00087 }
00088 
00089 
00090 const QString Wallet::LocalWallet() {
00091     KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
00092     if (!cfg.readEntry("Use One Wallet", true)) {
00093         QString tmp = cfg.readEntry("Local Wallet", "localwallet");
00094         if (tmp.isEmpty()) {
00095             return "localwallet";
00096         }
00097         return tmp;
00098     }
00099 
00100     QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
00101     if (tmp.isEmpty()) {
00102         return "kdewallet";
00103     }
00104     return tmp;
00105 }
00106 
00107 const QString Wallet::NetworkWallet() {
00108     KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
00109 
00110     QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
00111     if (tmp.isEmpty()) {
00112         return "kdewallet";
00113     }
00114     return tmp;
00115 }
00116 
00117 const QString Wallet::PasswordFolder() {
00118     return "Passwords";
00119 }
00120 
00121 const QString Wallet::FormDataFolder() {
00122     return "Form Data";
00123 }
00124 
00125 class Wallet::WalletPrivate
00126 {
00127 public:
00128     explicit WalletPrivate(const QString &n)
00129      : name(n)
00130     {}
00131 
00132     // needed for compilation reasons
00133     void walletServiceUnregistered() {
00134     }
00135 
00136     QString name;
00137     QString folder;
00138 };
00139 
00140 Wallet::Wallet(int handle, const QString& name)
00141     : QObject(0L), d(new WalletPrivate(name)) {
00142     Q_UNUSED(handle);
00143 }
00144 
00145 Wallet::~Wallet() {
00146     delete d;
00147 }
00148 
00149 
00150 QStringList Wallet::walletList() {
00151 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00152     return walletLauncher->getInterface().wallets();
00153 #else
00154     return QStringList();
00155 #endif
00156 }
00157 
00158 
00159 void Wallet::changePassword(const QString& name, WId w) {
00160 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00161     if( w == 0 )
00162         kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
00163     walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
00164 #endif
00165 }
00166 
00167 
00168 bool Wallet::isEnabled() {
00169     //PENDING(frank) check
00170     return true;
00171 }
00172 
00173 
00174 bool Wallet::isOpen(const QString& name) {
00175 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00176     return walletLauncher->getInterface().isOpen(name); // default is false
00177 #else
00178     return true;
00179 #endif
00180 }
00181 
00182 
00183 int Wallet::closeWallet(const QString& name, bool force) {
00184 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00185     QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
00186     return r.isValid() ? r : -1;
00187 #else
00188     return 0;
00189 #endif
00190 }
00191 
00192 
00193 int Wallet::deleteWallet(const QString& name) {
00194 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00195     QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
00196     return r.isValid() ? r : -1;
00197 #else
00198     return -1;
00199 #endif
00200 }
00201 
00202 
00203 Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot) {
00204     Q_UNUSED(w);
00205     Q_UNUSED(ot);
00206     Wallet *wallet = new Wallet(-1, name);
00207     QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
00208     return wallet;
00209 }
00210 
00211 
00212 bool Wallet::disconnectApplication(const QString& wallet, const QString& app) {
00213 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00214     return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
00215 #else
00216     return true;
00217 #endif
00218 }
00219 
00220 
00221 QStringList Wallet::users(const QString& name) {
00222 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00223     return walletLauncher->getInterface().users(name); // default is QStringList()
00224 #else
00225     return QStringList();
00226 #endif
00227 }
00228 
00229 
00230 int Wallet::sync() {
00231 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00232     if (d->handle == -1) {
00233         return -1;
00234     }
00235 
00236     walletLauncher->getInterface().sync(d->handle, appid());
00237 #endif
00238     return 0;
00239 }
00240 
00241 
00242 int Wallet::lockWallet() {
00243 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00244     if (d->handle == -1) {
00245         return -1;
00246     }
00247 
00248     QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
00249     d->handle = -1;
00250     d->folder.clear();
00251     d->name.clear();
00252     if (r.isValid()) {
00253         return r;
00254     }
00255 #endif
00256     return -1;
00257 }
00258 
00259 
00260 const QString& Wallet::walletName() const {
00261     return d->name;
00262 }
00263 
00264 
00265 bool Wallet::isOpen() const {
00266 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00267     return d->handle != -1;
00268 #else
00269     return true;
00270 #endif
00271 }
00272 
00273 
00274 void Wallet::requestChangePassword(WId w) {
00275 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00276     if( w == 0 )
00277         kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
00278     if (d->handle == -1) {
00279         return;
00280     }
00281 
00282     walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
00283 #endif
00284 }
00285 
00286 
00287 void Wallet::slotWalletClosed(int handle) {
00288 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00289     if (d->handle == handle) {
00290         d->handle = -1;
00291         d->folder.clear();
00292         d->name.clear();
00293         emit walletClosed();
00294     }
00295 #endif
00296 }
00297 
00298 
00299 QStringList Wallet::folderList() {
00300 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00301     if (d->handle == -1) {
00302         return QStringList();
00303     }
00304 
00305     QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
00306     return r;
00307 #else
00308     return QStringList();
00309 #endif
00310 }
00311 
00312 
00313 QStringList Wallet::entryList() {
00314 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00315     if (d->handle == -1) {
00316         return QStringList();
00317     }
00318 
00319     QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
00320     return r;
00321 #else
00322     return QStringList();
00323 #endif
00324 }
00325 
00326 
00327 bool Wallet::hasFolder(const QString& f) {
00328 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00329     if (d->handle == -1) {
00330         return false;
00331     }
00332 
00333     QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
00334     return r; // default is false
00335 #else
00336     return true;
00337 #endif
00338 }
00339 
00340 
00341 bool Wallet::createFolder(const QString& f) {
00342 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00343     if (d->handle == -1) {
00344         return false;
00345     }
00346 
00347     if (!hasFolder(f)) {
00348         QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
00349         return r;
00350     }
00351 
00352     return true;                // folder already exists
00353 #else
00354     return true;
00355 #endif
00356 }
00357 
00358 
00359 bool Wallet::setFolder(const QString& f) {
00360 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00361     bool rc = false;
00362 
00363     if (d->handle == -1) {
00364         return rc;
00365     }
00366 
00367     // Don't do this - the folder could have disappeared?
00368 #if 0
00369     if (f == d->folder) {
00370         return true;
00371     }
00372 #endif
00373 
00374     if (hasFolder(f)) {
00375         d->folder = f;
00376         rc = true;
00377     }
00378 
00379     return rc;
00380 #else
00381     return true;
00382 #endif
00383 }
00384 
00385 
00386 bool Wallet::removeFolder(const QString& f) {
00387 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00388     if (d->handle == -1) {
00389         return false;
00390     }
00391 
00392     QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
00393     if (d->folder == f) {
00394         setFolder(QString());
00395     }
00396 
00397     return r;                   // default is false
00398 #else
00399     return true;
00400 #endif
00401 }
00402 
00403 
00404 const QString& Wallet::currentFolder() const {
00405     return d->folder;
00406 }
00407 
00408 
00409 int Wallet::readEntry(const QString& key, QByteArray& value) {
00410     const QByteArray serviceName( walletName().toUtf8() );
00411     const QByteArray accountName( key.toUtf8() );
00412     UInt32 passwordSize = 0;
00413     void* passwordData = 0;
00414     QString errMsg;
00415     if ( isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), &passwordSize, &passwordData, NULL ), &errMsg ) ) {
00416         qWarning() << "Could not retrieve password:"  << qPrintable(errMsg);
00417         return -1;
00418     }
00419 
00420     value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
00421     SecKeychainItemFreeContent( NULL, passwordData );
00422     return 0;
00423 }
00424 
00425 
00426 int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value) {
00427 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00428     registerTypes();
00429 
00430     int rc = -1;
00431 
00432     if (d->handle == -1) {
00433         return rc;
00434     }
00435 
00436     QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
00437     if (r.isValid()) {
00438         rc = 0;
00439         // convert <QString, QVariant> to <QString, QByteArray>
00440         const QVariantMap val = r.value();
00441         for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
00442             value.insert(it.key(), it.value().toByteArray());
00443         }
00444     }
00445 
00446     return rc;
00447 #else
00448     return -1;
00449 #endif
00450 }
00451 
00452 
00453 int Wallet::renameEntry(const QString& oldName, const QString& newName) {
00454 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00455     int rc = -1;
00456 
00457     if (d->handle == -1) {
00458         return rc;
00459     }
00460 
00461     QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
00462     if (r.isValid()) {
00463         rc = r;
00464     }
00465 
00466     return rc;
00467 #else
00468     return -1;
00469 #endif
00470 }
00471 
00472 
00473 int Wallet::readMap(const QString& key, QMap<QString,QString>& value) {
00474     QByteArray v;
00475     const int ret = readEntry( key, v );
00476     if ( ret != 0 )
00477         return ret;
00478     if ( !v.isEmpty() ) {
00479         QDataStream ds( &v, QIODevice::ReadOnly );
00480         ds >> value;
00481     }
00482     return 0;
00483 }
00484 
00485 
00486 int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value) {
00487 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00488     registerTypes();
00489 
00490     int rc = -1;
00491 
00492     if (d->handle == -1) {
00493         return rc;
00494     }
00495 
00496     QDBusReply<QVariantMap> r =
00497         walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
00498     if (r.isValid()) {
00499         rc = 0;
00500         const QVariantMap val = r.value();
00501         for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
00502             QByteArray mapData = it.value().toByteArray();
00503             if (!mapData.isEmpty()) {
00504                 QDataStream ds(&mapData, QIODevice::ReadOnly);
00505                 QMap<QString,QString> v;
00506                 ds >> v;
00507                 value.insert(it.key(), v);
00508             }
00509         }
00510     }
00511 
00512     return rc;
00513 #else
00514     return -1;
00515 #endif
00516 }
00517 
00518 
00519 int Wallet::readPassword(const QString& key, QString& value) {
00520     QByteArray ba;
00521     const int ret = readEntry( key, ba );
00522     if ( ret == 0 )
00523         value = QString::fromUtf8( ba.constData() );
00524     return ret;
00525 }
00526 
00527 
00528 int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value) {
00529     return -1;
00530 }
00531 
00532 
00533 int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType) {
00534     const QByteArray serviceName( walletName().toUtf8() );
00535     const QByteArray accountName( key.toUtf8() );
00536     QString errMsg;
00537     if ( isError( SecKeychainAddGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), password.size(), password.constData(), NULL ), &errMsg ) ) {
00538         kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
00539         return -1;
00540     }
00541     return 0;
00542 }
00543 
00544 
00545 int Wallet::writeEntry(const QString& key, const QByteArray& value) {
00546     const QByteArray serviceName( walletName().toUtf8() );
00547     const QByteArray accountName( key.toUtf8() );
00548     QString errMsg;
00549     if ( isError( SecKeychainAddGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), value.size(), value.constData(), NULL ), &errMsg ) ) {
00550         kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
00551         return -1;
00552     }
00553     return 0;
00554 }
00555 
00556 
00557 int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value) {
00558     QByteArray mapData;
00559     QDataStream ds(&mapData, QIODevice::WriteOnly);
00560     ds << value;
00561     return writeEntry( key, mapData );
00562 }
00563 
00564 
00565 int Wallet::writePassword(const QString& key, const QString& value) {
00566     return writeEntry( key, value.toUtf8() );
00567 }
00568 
00569 
00570 bool Wallet::hasEntry(const QString& key) {
00571     const QByteArray serviceName( walletName().toUtf8() );
00572     const QByteArray accountName( key.toUtf8() );
00573     return !isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, NULL ), 0 );
00574 }
00575 
00576 
00577 int Wallet::removeEntry(const QString& key) {
00578     const QByteArray serviceName( walletName().toUtf8() );
00579     const QByteArray accountName( key.toUtf8() );
00580     SecKeychainItemRef itemRef;
00581     QString errMsg;
00582     if ( isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, &itemRef ), &errMsg ) ) {
00583         qWarning() << "Could not retrieve password:"  << qPrintable(errMsg);
00584         return -1;
00585     }
00586     const CFReleaser<SecKeychainItemRef> itemReleaser( itemRef );
00587     if ( isError( SecKeychainItemDelete( itemRef ), &errMsg ) ) {
00588         qWarning() << "Could not delete password:"  << qPrintable(errMsg);
00589         return -1;
00590     }
00591     return 0;
00592 }
00593 
00594 
00595 Wallet::EntryType Wallet::entryType(const QString& key) {
00596 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00597     int rc = 0;
00598 
00599     if (d->handle == -1) {
00600         return Wallet::Unknown;
00601     }
00602 
00603     QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
00604     if (r.isValid()) {
00605         rc = r;
00606     }
00607 
00608     return static_cast<EntryType>(rc);
00609 #else
00610     return Wallet::Unknown;
00611 #endif
00612 }
00613 
00614 
00615 void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder) {
00616     if (d->name == wallet) {
00617         emit folderUpdated(folder);
00618     }
00619 }
00620 
00621 
00622 void Wallet::slotFolderListUpdated(const QString& wallet) {
00623     if (d->name == wallet) {
00624         emit folderListUpdated();
00625     }
00626 }
00627 
00628 
00629 void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application) {
00630 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00631     if (d->handle >= 0
00632         && d->name == wallet
00633         && application == appid()) {
00634         slotWalletClosed(d->handle);
00635     }
00636 #endif
00637 }
00638 
00639 void Wallet::walletAsyncOpened(int tId, int handle) {
00640 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00641     // ignore responses to calls other than ours
00642     if (d->transactionId != tId || d->handle != -1) {
00643         return;
00644     }
00645     
00646     // disconnect the async signal
00647     disconnect(this, SLOT(walletAsyncOpened(int, int)));
00648     
00649     d->handle = handle;
00650     emit walletOpened(handle > 0);
00651 #endif
00652 }
00653 
00654 void Wallet::emitWalletAsyncOpenError() {
00655     emit walletOpened(false);
00656 }
00657 
00658 void Wallet::emitWalletOpened() {
00659   emit walletOpened(true);
00660 }
00661 
00662 
00663 bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
00664 {
00665 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00666     QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
00667     return r;
00668 #else
00669     return false;
00670 #endif
00671 }
00672 
00673 
00674 bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
00675 {
00676 #ifdef OSX_KEYCHAIN_PORT_DISABLED
00677     QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
00678     return r;
00679 #else
00680     return false;
00681 #endif
00682 }
00683 
00684 void Wallet::virtual_hook(int, void*) {
00685     //BASE::virtual_hook( id, data );
00686 }
00687 
00688 #include "kwallet.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal