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

KDEUI

  • kdeui
  • util
kwallet_mac.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2002-2004 George Staikos <staikos@kde.org>
4  * Copyright (C) 2008 Michael Leupold <lemma@confuego.org>
5  * Copyright (C) 2010 Frank Osterfeld <osterfeld@kde.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "kwallet.h"
24 #include <ksharedconfig.h>
25 #include <kdebug.h>
26 #include <kdeversion.h>
27 #include <QtGui/QApplication>
28 #include <QtCore/QPointer>
29 #include <QtGui/QWidget>
30 #include <ktoolinvocation.h>
31 
32 #include <kglobal.h>
33 #include <kcomponentdata.h>
34 #include <kaboutdata.h>
35 #include <kconfiggroup.h>
36 
37 #include <cassert>
38 
39 #include <Carbon/Carbon.h>
40 #include <Security/Security.h>
41 #include <Security/SecKeychain.h>
42 
43 using namespace KWallet;
44 
45 typedef QMap<QString, QString> StringStringMap;
46 Q_DECLARE_METATYPE(StringStringMap)
47 typedef QMap<QString, StringStringMap> StringToStringStringMapMap;
48 Q_DECLARE_METATYPE(StringToStringStringMapMap)
49 typedef QMap<QString, QByteArray> StringByteArrayMap;
50 Q_DECLARE_METATYPE(StringByteArrayMap)
51 
52 namespace {
53  template <typename T>
54  struct CFReleaser {
55  explicit CFReleaser( const T& r ) : ref( r ) {}
56  ~CFReleaser() { CFRelease( ref ); }
57  T ref;
58  };
59 }
60 
61 static QString asQString( CFStringRef sr ) {
62  return QString::fromLatin1( CFStringGetCStringPtr( sr, NULL ) ); //TODO Latin1 correct?
63 }
64 
65 static QString errorString( OSStatus s ) {
66  const CFReleaser<CFStringRef> ref( SecCopyErrorMessageString( s, NULL ) );
67  return asQString( ref.ref );
68 }
69 
70 static bool isError( OSStatus s, QString* errMsg ) {
71  if ( errMsg )
72  *errMsg = errorString( s );
73  return s != 0;
74 }
75 
76 static QString appid()
77 {
78  KComponentData cData = KGlobal::mainComponent();
79  if (cData.isValid()) {
80  const KAboutData* aboutData = cData.aboutData();
81  if (aboutData) {
82  return aboutData->programName();
83  }
84  return cData.componentName();
85  }
86  return qApp->applicationName();
87 }
88 
89 
90 const QString Wallet::LocalWallet() {
91  KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
92  if (!cfg.readEntry("Use One Wallet", true)) {
93  QString tmp = cfg.readEntry("Local Wallet", "localwallet");
94  if (tmp.isEmpty()) {
95  return "localwallet";
96  }
97  return tmp;
98  }
99 
100  QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
101  if (tmp.isEmpty()) {
102  return "kdewallet";
103  }
104  return tmp;
105 }
106 
107 const QString Wallet::NetworkWallet() {
108  KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
109 
110  QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
111  if (tmp.isEmpty()) {
112  return "kdewallet";
113  }
114  return tmp;
115 }
116 
117 const QString Wallet::PasswordFolder() {
118  return "Passwords";
119 }
120 
121 const QString Wallet::FormDataFolder() {
122  return "Form Data";
123 }
124 
125 class Wallet::WalletPrivate
126 {
127 public:
128  explicit WalletPrivate(const QString &n)
129  : name(n)
130  {}
131 
132  // needed for compilation reasons
133  void walletServiceUnregistered() {
134  }
135 
136  QString name;
137  QString folder;
138 };
139 
140 Wallet::Wallet(int handle, const QString& name)
141  : QObject(0L), d(new WalletPrivate(name)) {
142  Q_UNUSED(handle);
143 }
144 
145 Wallet::~Wallet() {
146  delete d;
147 }
148 
149 
150 QStringList Wallet::walletList() {
151 #ifdef OSX_KEYCHAIN_PORT_DISABLED
152  return walletLauncher->getInterface().wallets();
153 #else
154  return QStringList();
155 #endif
156 }
157 
158 
159 void Wallet::changePassword(const QString& name, WId w) {
160 #ifdef OSX_KEYCHAIN_PORT_DISABLED
161  if( w == 0 )
162  kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
163  walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
164 #endif
165 }
166 
167 
168 bool Wallet::isEnabled() {
169  //PENDING(frank) check
170  return true;
171 }
172 
173 
174 bool Wallet::isOpen(const QString& name) {
175 #ifdef OSX_KEYCHAIN_PORT_DISABLED
176  return walletLauncher->getInterface().isOpen(name); // default is false
177 #else
178  return true;
179 #endif
180 }
181 
182 
183 int Wallet::closeWallet(const QString& name, bool force) {
184 #ifdef OSX_KEYCHAIN_PORT_DISABLED
185  QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
186  return r.isValid() ? r : -1;
187 #else
188  return 0;
189 #endif
190 }
191 
192 
193 int Wallet::deleteWallet(const QString& name) {
194 #ifdef OSX_KEYCHAIN_PORT_DISABLED
195  QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
196  return r.isValid() ? r : -1;
197 #else
198  return -1;
199 #endif
200 }
201 
202 
203 Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot) {
204  Q_UNUSED(w);
205  Q_UNUSED(ot);
206  Wallet *wallet = new Wallet(-1, name);
207  QMetaObject::invokeMethod( wallet, "emitWalletOpened", Qt::QueuedConnection );
208  return wallet;
209 }
210 
211 
212 bool Wallet::disconnectApplication(const QString& wallet, const QString& app) {
213 #ifdef OSX_KEYCHAIN_PORT_DISABLED
214  return walletLauncher->getInterface().disconnectApplication(wallet, app); // default is false
215 #else
216  return true;
217 #endif
218 }
219 
220 
221 QStringList Wallet::users(const QString& name) {
222 #ifdef OSX_KEYCHAIN_PORT_DISABLED
223  return walletLauncher->getInterface().users(name); // default is QStringList()
224 #else
225  return QStringList();
226 #endif
227 }
228 
229 
230 int Wallet::sync() {
231 #ifdef OSX_KEYCHAIN_PORT_DISABLED
232  if (d->handle == -1) {
233  return -1;
234  }
235 
236  walletLauncher->getInterface().sync(d->handle, appid());
237 #endif
238  return 0;
239 }
240 
241 
242 int Wallet::lockWallet() {
243 #ifdef OSX_KEYCHAIN_PORT_DISABLED
244  if (d->handle == -1) {
245  return -1;
246  }
247 
248  QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
249  d->handle = -1;
250  d->folder.clear();
251  d->name.clear();
252  if (r.isValid()) {
253  return r;
254  }
255 #endif
256  return -1;
257 }
258 
259 
260 const QString& Wallet::walletName() const {
261  return d->name;
262 }
263 
264 
265 bool Wallet::isOpen() const {
266 #ifdef OSX_KEYCHAIN_PORT_DISABLED
267  return d->handle != -1;
268 #else
269  return true;
270 #endif
271 }
272 
273 
274 void Wallet::requestChangePassword(WId w) {
275 #ifdef OSX_KEYCHAIN_PORT_DISABLED
276  if( w == 0 )
277  kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
278  if (d->handle == -1) {
279  return;
280  }
281 
282  walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
283 #endif
284 }
285 
286 
287 void Wallet::slotWalletClosed(int handle) {
288 #ifdef OSX_KEYCHAIN_PORT_DISABLED
289  if (d->handle == handle) {
290  d->handle = -1;
291  d->folder.clear();
292  d->name.clear();
293  emit walletClosed();
294  }
295 #endif
296 }
297 
298 
299 QStringList Wallet::folderList() {
300 #ifdef OSX_KEYCHAIN_PORT_DISABLED
301  if (d->handle == -1) {
302  return QStringList();
303  }
304 
305  QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
306  return r;
307 #else
308  return QStringList();
309 #endif
310 }
311 
312 
313 QStringList Wallet::entryList() {
314 #ifdef OSX_KEYCHAIN_PORT_DISABLED
315  if (d->handle == -1) {
316  return QStringList();
317  }
318 
319  QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
320  return r;
321 #else
322  return QStringList();
323 #endif
324 }
325 
326 
327 bool Wallet::hasFolder(const QString& f) {
328 #ifdef OSX_KEYCHAIN_PORT_DISABLED
329  if (d->handle == -1) {
330  return false;
331  }
332 
333  QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
334  return r; // default is false
335 #else
336  return true;
337 #endif
338 }
339 
340 
341 bool Wallet::createFolder(const QString& f) {
342 #ifdef OSX_KEYCHAIN_PORT_DISABLED
343  if (d->handle == -1) {
344  return false;
345  }
346 
347  if (!hasFolder(f)) {
348  QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
349  return r;
350  }
351 
352  return true; // folder already exists
353 #else
354  return true;
355 #endif
356 }
357 
358 
359 bool Wallet::setFolder(const QString& f) {
360 #ifdef OSX_KEYCHAIN_PORT_DISABLED
361  bool rc = false;
362 
363  if (d->handle == -1) {
364  return rc;
365  }
366 
367  // Don't do this - the folder could have disappeared?
368 #if 0
369  if (f == d->folder) {
370  return true;
371  }
372 #endif
373 
374  if (hasFolder(f)) {
375  d->folder = f;
376  rc = true;
377  }
378 
379  return rc;
380 #else
381  return true;
382 #endif
383 }
384 
385 
386 bool Wallet::removeFolder(const QString& f) {
387 #ifdef OSX_KEYCHAIN_PORT_DISABLED
388  if (d->handle == -1) {
389  return false;
390  }
391 
392  QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
393  if (d->folder == f) {
394  setFolder(QString());
395  }
396 
397  return r; // default is false
398 #else
399  return true;
400 #endif
401 }
402 
403 
404 const QString& Wallet::currentFolder() const {
405  return d->folder;
406 }
407 
408 
409 int Wallet::readEntry(const QString& key, QByteArray& value) {
410  const QByteArray serviceName( walletName().toUtf8() );
411  const QByteArray accountName( key.toUtf8() );
412  UInt32 passwordSize = 0;
413  void* passwordData = 0;
414  QString errMsg;
415  if ( isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), &passwordSize, &passwordData, NULL ), &errMsg ) ) {
416  qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
417  return -1;
418  }
419 
420  value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
421  SecKeychainItemFreeContent( NULL, passwordData );
422  return 0;
423 }
424 
425 
426 int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value) {
427 #ifdef OSX_KEYCHAIN_PORT_DISABLED
428  registerTypes();
429 
430  int rc = -1;
431 
432  if (d->handle == -1) {
433  return rc;
434  }
435 
436  QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
437  if (r.isValid()) {
438  rc = 0;
439  // convert <QString, QVariant> to <QString, QByteArray>
440  const QVariantMap val = r.value();
441  for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
442  value.insert(it.key(), it.value().toByteArray());
443  }
444  }
445 
446  return rc;
447 #else
448  return -1;
449 #endif
450 }
451 
452 
453 int Wallet::renameEntry(const QString& oldName, const QString& newName) {
454 #ifdef OSX_KEYCHAIN_PORT_DISABLED
455  int rc = -1;
456 
457  if (d->handle == -1) {
458  return rc;
459  }
460 
461  QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
462  if (r.isValid()) {
463  rc = r;
464  }
465 
466  return rc;
467 #else
468  return -1;
469 #endif
470 }
471 
472 
473 int Wallet::readMap(const QString& key, QMap<QString,QString>& value) {
474  QByteArray v;
475  const int ret = readEntry( key, v );
476  if ( ret != 0 )
477  return ret;
478  if ( !v.isEmpty() ) {
479  QDataStream ds( &v, QIODevice::ReadOnly );
480  ds >> value;
481  }
482  return 0;
483 }
484 
485 
486 int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value) {
487 #ifdef OSX_KEYCHAIN_PORT_DISABLED
488  registerTypes();
489 
490  int rc = -1;
491 
492  if (d->handle == -1) {
493  return rc;
494  }
495 
496  QDBusReply<QVariantMap> r =
497  walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
498  if (r.isValid()) {
499  rc = 0;
500  const QVariantMap val = r.value();
501  for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
502  QByteArray mapData = it.value().toByteArray();
503  if (!mapData.isEmpty()) {
504  QDataStream ds(&mapData, QIODevice::ReadOnly);
505  QMap<QString,QString> v;
506  ds >> v;
507  value.insert(it.key(), v);
508  }
509  }
510  }
511 
512  return rc;
513 #else
514  return -1;
515 #endif
516 }
517 
518 
519 int Wallet::readPassword(const QString& key, QString& value) {
520  QByteArray ba;
521  const int ret = readEntry( key, ba );
522  if ( ret == 0 )
523  value = QString::fromUtf8( ba.constData() );
524  return ret;
525 }
526 
527 
528 int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value) {
529  return -1;
530 }
531 
532 
533 int Wallet::writeEntry(const QString& key, const QByteArray& password, EntryType entryType) {
534  const QByteArray serviceName( walletName().toUtf8() );
535  const QByteArray accountName( key.toUtf8() );
536  QString errMsg;
537  if ( isError( SecKeychainAddGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), password.size(), password.constData(), NULL ), &errMsg ) ) {
538  kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
539  return -1;
540  }
541  return 0;
542 }
543 
544 
545 int Wallet::writeEntry(const QString& key, const QByteArray& value) {
546  const QByteArray serviceName( walletName().toUtf8() );
547  const QByteArray accountName( key.toUtf8() );
548  QString errMsg;
549  if ( isError( SecKeychainAddGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), value.size(), value.constData(), NULL ), &errMsg ) ) {
550  kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
551  return -1;
552  }
553  return 0;
554 }
555 
556 
557 int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value) {
558  QByteArray mapData;
559  QDataStream ds(&mapData, QIODevice::WriteOnly);
560  ds << value;
561  return writeEntry( key, mapData );
562 }
563 
564 
565 int Wallet::writePassword(const QString& key, const QString& value) {
566  return writeEntry( key, value.toUtf8() );
567 }
568 
569 
570 bool Wallet::hasEntry(const QString& key) {
571  const QByteArray serviceName( walletName().toUtf8() );
572  const QByteArray accountName( key.toUtf8() );
573  return !isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, NULL ), 0 );
574 }
575 
576 
577 int Wallet::removeEntry(const QString& key) {
578  const QByteArray serviceName( walletName().toUtf8() );
579  const QByteArray accountName( key.toUtf8() );
580  SecKeychainItemRef itemRef;
581  QString errMsg;
582  if ( isError( SecKeychainFindGenericPassword( NULL, serviceName.size(), serviceName.constData(), accountName.size(), accountName.constData(), NULL, NULL, &itemRef ), &errMsg ) ) {
583  qWarning() << "Could not retrieve password:" << qPrintable(errMsg);
584  return -1;
585  }
586  const CFReleaser<SecKeychainItemRef> itemReleaser( itemRef );
587  if ( isError( SecKeychainItemDelete( itemRef ), &errMsg ) ) {
588  qWarning() << "Could not delete password:" << qPrintable(errMsg);
589  return -1;
590  }
591  return 0;
592 }
593 
594 
595 Wallet::EntryType Wallet::entryType(const QString& key) {
596 #ifdef OSX_KEYCHAIN_PORT_DISABLED
597  int rc = 0;
598 
599  if (d->handle == -1) {
600  return Wallet::Unknown;
601  }
602 
603  QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
604  if (r.isValid()) {
605  rc = r;
606  }
607 
608  return static_cast<EntryType>(rc);
609 #else
610  return Wallet::Unknown;
611 #endif
612 }
613 
614 
615 void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder) {
616  if (d->name == wallet) {
617  emit folderUpdated(folder);
618  }
619 }
620 
621 
622 void Wallet::slotFolderListUpdated(const QString& wallet) {
623  if (d->name == wallet) {
624  emit folderListUpdated();
625  }
626 }
627 
628 
629 void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application) {
630 #ifdef OSX_KEYCHAIN_PORT_DISABLED
631  if (d->handle >= 0
632  && d->name == wallet
633  && application == appid()) {
634  slotWalletClosed(d->handle);
635  }
636 #endif
637 }
638 
639 void Wallet::walletAsyncOpened(int tId, int handle) {
640 #ifdef OSX_KEYCHAIN_PORT_DISABLED
641  // ignore responses to calls other than ours
642  if (d->transactionId != tId || d->handle != -1) {
643  return;
644  }
645 
646  // disconnect the async signal
647  disconnect(this, SLOT(walletAsyncOpened(int,int)));
648 
649  d->handle = handle;
650  emit walletOpened(handle > 0);
651 #endif
652 }
653 
654 void Wallet::emitWalletAsyncOpenError() {
655  emit walletOpened(false);
656 }
657 
658 void Wallet::emitWalletOpened() {
659  emit walletOpened(true);
660 }
661 
662 
663 bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
664 {
665 #ifdef OSX_KEYCHAIN_PORT_DISABLED
666  QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
667  return r;
668 #else
669  return false;
670 #endif
671 }
672 
673 
674 bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
675 {
676 #ifdef OSX_KEYCHAIN_PORT_DISABLED
677  QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
678  return r;
679 #else
680  return false;
681 #endif
682 }
683 
684 void Wallet::slotCollectionStatusChanged(int status)
685 {
686 }
687 
688 void Wallet::slotCollectionDeleted()
689 {
690  d->folder.clear();
691  d->name.clear();
692  emit walletClosed();
693 }
694 
695 
696 void Wallet::virtual_hook(int, void*) {
697  //BASE::virtual_hook( id, data );
698 }
699 
700 #include "kwallet.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:04:47 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

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-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal