00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kwallet.h"
00023 #include <ksharedconfig.h>
00024 #include <kdebug.h>
00025 #include <kdeversion.h>
00026 #include <QtGui/QApplication>
00027 #include <QtCore/QPointer>
00028 #include <QtGui/QWidget>
00029 #include <QtDBus/QtDBus>
00030 #include <ktoolinvocation.h>
00031
00032 #include <assert.h>
00033 #include <kglobal.h>
00034 #include <kcomponentdata.h>
00035 #include <kaboutdata.h>
00036 #include <kconfiggroup.h>
00037
00038 #include "kwallet_interface.h"
00039
00040 using namespace KWallet;
00041
00042 typedef QMap<QString, QString> StringStringMap;
00043 Q_DECLARE_METATYPE(StringStringMap)
00044 typedef QMap<QString, StringStringMap> StringToStringStringMapMap;
00045 Q_DECLARE_METATYPE(StringToStringStringMapMap)
00046 typedef QMap<QString, QByteArray> StringByteArrayMap;
00047 Q_DECLARE_METATYPE(StringByteArrayMap)
00048
00049 static QString appid()
00050 {
00051 KComponentData cData = KGlobal::mainComponent();
00052 if (cData.isValid()) {
00053 const KAboutData* aboutData = cData.aboutData();
00054 if (aboutData) {
00055 return aboutData->programName();
00056 }
00057 return cData.componentName();
00058 }
00059 return qApp->applicationName();
00060 }
00061
00062 static void registerTypes()
00063 {
00064 static bool registered = false;
00065 if (!registered) {
00066 qDBusRegisterMetaType<StringStringMap>();
00067 qDBusRegisterMetaType<StringToStringStringMapMap>();
00068 qDBusRegisterMetaType<StringByteArrayMap>();
00069 registered = true;
00070 }
00071 }
00072
00073 const QString Wallet::LocalWallet() {
00074 KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
00075 if (!cfg.readEntry("Use One Wallet", true)) {
00076 QString tmp = cfg.readEntry("Local Wallet", "localwallet");
00077 if (tmp.isEmpty()) {
00078 return "localwallet";
00079 }
00080 return tmp;
00081 }
00082
00083 QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
00084 if (tmp.isEmpty()) {
00085 return "kdewallet";
00086 }
00087 return tmp;
00088 }
00089
00090 const QString Wallet::NetworkWallet() {
00091 KConfigGroup cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
00092
00093 QString tmp = cfg.readEntry("Default Wallet", "kdewallet");
00094 if (tmp.isEmpty()) {
00095 return "kdewallet";
00096 }
00097 return tmp;
00098 }
00099
00100 const QString Wallet::PasswordFolder() {
00101 return "Passwords";
00102 }
00103
00104 const QString Wallet::FormDataFolder() {
00105 return "Form Data";
00106 }
00107
00108 class Wallet::WalletPrivate
00109 {
00110 public:
00111 WalletPrivate(int h, const QString &n)
00112 : name(n), handle(h)
00113 {}
00114 QString name;
00115 QString folder;
00116 int handle;
00117 int transactionId;
00118 QPointer<QEventLoop> loop;
00119 };
00120
00121 class KWalletDLauncher
00122 {
00123 public:
00124 KWalletDLauncher();
00125 ~KWalletDLauncher();
00126 org::kde::KWallet &getInterface();
00127 private:
00128 org::kde::KWallet m_wallet;
00129 KConfigGroup m_cgroup;
00130 };
00131
00132 K_GLOBAL_STATIC(KWalletDLauncher, walletLauncher)
00133
00134 Wallet::Wallet(int handle, const QString& name)
00135 : QObject(0L), d(new WalletPrivate(handle, name)) {
00136
00137 connect(QDBusConnection::sessionBus().interface(),
00138 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00139 this,
00140 SLOT(slotServiceOwnerChanged(QString,QString,QString)));
00141
00142 connect(&walletLauncher->getInterface(), SIGNAL(walletClosed(int)), SLOT(slotWalletClosed(int)));
00143 connect(&walletLauncher->getInterface(), SIGNAL(folderListUpdated(QString)), SLOT(slotFolderListUpdated(QString)));
00144 connect(&walletLauncher->getInterface(), SIGNAL(folderUpdated(QString,QString)), SLOT(slotFolderUpdated(QString, QString)));
00145 connect(&walletLauncher->getInterface(), SIGNAL(applicationDisconnected(QString, QString)), SLOT(slotApplicationDisconnected(QString, QString)));
00146
00147
00148 if (d->handle != -1) {
00149 QDBusReply<bool> r = walletLauncher->getInterface().isOpen(d->handle);
00150 if (r.isValid() && !r) {
00151 d->handle = -1;
00152 d->name.clear();
00153 }
00154 }
00155 }
00156
00157
00158 Wallet::~Wallet() {
00159 if (d->handle != -1) {
00160 if (!walletLauncher.isDestroyed()) {
00161 walletLauncher->getInterface().close(d->handle, false, appid());
00162 } else {
00163 kDebug(285) << "Problem with static destruction sequence."
00164 "Destroy any static Wallet before the event-loop exits.";
00165 }
00166 d->handle = -1;
00167 d->folder.clear();
00168 d->name.clear();
00169 }
00170 delete d;
00171 }
00172
00173
00174 QStringList Wallet::walletList() {
00175 return walletLauncher->getInterface().wallets();
00176 }
00177
00178
00179 void Wallet::changePassword(const QString& name, WId w) {
00180 if( w == 0 )
00181 kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
00182 walletLauncher->getInterface().changePassword(name, (qlonglong)w, appid());
00183 }
00184
00185
00186 bool Wallet::isEnabled() {
00187 QDBusReply<bool> r = walletLauncher->getInterface().isEnabled();
00188 return (r.isValid() && r);
00189 }
00190
00191
00192 bool Wallet::isOpen(const QString& name) {
00193 return walletLauncher->getInterface().isOpen(name);
00194 }
00195
00196
00197 int Wallet::closeWallet(const QString& name, bool force) {
00198 QDBusReply<int> r = walletLauncher->getInterface().close(name, force);
00199 return r.isValid() ? r : -1;
00200 }
00201
00202
00203 int Wallet::deleteWallet(const QString& name) {
00204 QDBusReply<int> r = walletLauncher->getInterface().deleteWallet(name);
00205 return r.isValid() ? r : -1;
00206 }
00207
00208
00209 Wallet *Wallet::openWallet(const QString& name, WId w, OpenType ot) {
00210 if( w == 0 )
00211 kDebug(285) << "Pass a valid window to KWallet::Wallet::openWallet().";
00212
00213 Wallet *wallet = new Wallet(-1, name);
00214
00215
00216
00217 connect(&walletLauncher->getInterface(), SIGNAL(walletAsyncOpened(int, int)),
00218 wallet, SLOT(walletAsyncOpened(int, int)));
00219
00220
00221 QEventLoop loop;
00222 if (ot == Synchronous || ot == Path) {
00223 connect(wallet, SIGNAL(walletOpened(bool)), &loop, SLOT(quit()));
00224 }
00225
00226
00227 QDBusReply<int> r;
00228 if (ot == Synchronous || ot == Asynchronous) {
00229 r = walletLauncher->getInterface().openAsync(name, (qlonglong)w, appid(), true);
00230 } else if (ot == Path) {
00231 r = walletLauncher->getInterface().openPathAsync(name, (qlonglong)w, appid(), true);
00232 } else {
00233 delete wallet;
00234 return 0;
00235 }
00236
00237 if (!r.isValid()) {
00238 delete wallet;
00239 return 0;
00240 }
00241 wallet->d->transactionId = r.value();
00242
00243 if (ot == Synchronous || ot == Path) {
00244
00245 if (wallet->d->transactionId < 0) {
00246 delete wallet;
00247 wallet = 0;
00248 } else {
00249
00250
00251 wallet->d->loop = &loop;
00252 loop.exec();
00253 if (wallet->d->handle < 0) {
00254 delete wallet;
00255 return 0;
00256 }
00257 }
00258 } else if (ot == Asynchronous) {
00259 if (wallet->d->transactionId < 0) {
00260 QTimer::singleShot(0, wallet, SLOT(emitWalletAsyncOpenError()));
00261
00262 }
00263 }
00264
00265 return wallet;
00266 }
00267
00268
00269 bool Wallet::disconnectApplication(const QString& wallet, const QString& app) {
00270 return walletLauncher->getInterface().disconnectApplication(wallet, app);
00271 }
00272
00273
00274 QStringList Wallet::users(const QString& name) {
00275 return walletLauncher->getInterface().users(name);
00276 }
00277
00278
00279 int Wallet::sync() {
00280 if (d->handle == -1) {
00281 return -1;
00282 }
00283
00284 walletLauncher->getInterface().sync(d->handle, appid());
00285 return 0;
00286 }
00287
00288
00289 int Wallet::lockWallet() {
00290 if (d->handle == -1) {
00291 return -1;
00292 }
00293
00294 QDBusReply<int> r = walletLauncher->getInterface().close(d->handle, true, appid());
00295 d->handle = -1;
00296 d->folder.clear();
00297 d->name.clear();
00298 if (r.isValid()) {
00299 return r;
00300 }
00301 return -1;
00302 }
00303
00304
00305 const QString& Wallet::walletName() const {
00306 return d->name;
00307 }
00308
00309
00310 bool Wallet::isOpen() const {
00311 return d->handle != -1;
00312 }
00313
00314
00315 void Wallet::requestChangePassword(WId w) {
00316 if( w == 0 )
00317 kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
00318 if (d->handle == -1) {
00319 return;
00320 }
00321
00322 walletLauncher->getInterface().changePassword(d->name, (qlonglong)w, appid());
00323 }
00324
00325
00326 void Wallet::slotWalletClosed(int handle) {
00327 if (d->handle == handle) {
00328 d->handle = -1;
00329 d->folder.clear();
00330 d->name.clear();
00331 emit walletClosed();
00332 }
00333 }
00334
00335
00336 QStringList Wallet::folderList() {
00337 if (d->handle == -1) {
00338 return QStringList();
00339 }
00340
00341 QDBusReply<QStringList> r = walletLauncher->getInterface().folderList(d->handle, appid());
00342 return r;
00343 }
00344
00345
00346 QStringList Wallet::entryList() {
00347 if (d->handle == -1) {
00348 return QStringList();
00349 }
00350
00351 QDBusReply<QStringList> r = walletLauncher->getInterface().entryList(d->handle, d->folder, appid());
00352 return r;
00353 }
00354
00355
00356 bool Wallet::hasFolder(const QString& f) {
00357 if (d->handle == -1) {
00358 return false;
00359 }
00360
00361 QDBusReply<bool> r = walletLauncher->getInterface().hasFolder(d->handle, f, appid());
00362 return r;
00363 }
00364
00365
00366 bool Wallet::createFolder(const QString& f) {
00367 if (d->handle == -1) {
00368 return false;
00369 }
00370
00371 if (!hasFolder(f)) {
00372 QDBusReply<bool> r = walletLauncher->getInterface().createFolder(d->handle, f, appid());
00373 return r;
00374 }
00375
00376 return true;
00377 }
00378
00379
00380 bool Wallet::setFolder(const QString& f) {
00381 bool rc = false;
00382
00383 if (d->handle == -1) {
00384 return rc;
00385 }
00386
00387
00388 #if 0
00389 if (f == d->folder) {
00390 return true;
00391 }
00392 #endif
00393
00394 if (hasFolder(f)) {
00395 d->folder = f;
00396 rc = true;
00397 }
00398
00399 return rc;
00400 }
00401
00402
00403 bool Wallet::removeFolder(const QString& f) {
00404 if (d->handle == -1) {
00405 return false;
00406 }
00407
00408 QDBusReply<bool> r = walletLauncher->getInterface().removeFolder(d->handle, f, appid());
00409 if (d->folder == f) {
00410 setFolder(QString());
00411 }
00412
00413 return r;
00414 }
00415
00416
00417 const QString& Wallet::currentFolder() const {
00418 return d->folder;
00419 }
00420
00421
00422 int Wallet::readEntry(const QString& key, QByteArray& value) {
00423 int rc = -1;
00424
00425 if (d->handle == -1) {
00426 return rc;
00427 }
00428
00429 QDBusReply<QByteArray> r = walletLauncher->getInterface().readEntry(d->handle, d->folder, key, appid());
00430 if (r.isValid()) {
00431 value = r;
00432 rc = 0;
00433 }
00434
00435 return rc;
00436 }
00437
00438
00439 int Wallet::readEntryList(const QString& key, QMap<QString, QByteArray>& value) {
00440 registerTypes();
00441
00442 int rc = -1;
00443
00444 if (d->handle == -1) {
00445 return rc;
00446 }
00447
00448 QDBusReply<QVariantMap> r = walletLauncher->getInterface().readEntryList(d->handle, d->folder, key, appid());
00449 if (r.isValid()) {
00450 rc = 0;
00451
00452 const QVariantMap val = r.value();
00453 for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
00454 value.insert(it.key(), it.value().toByteArray());
00455 }
00456 }
00457
00458 return rc;
00459 }
00460
00461
00462 int Wallet::renameEntry(const QString& oldName, const QString& newName) {
00463 int rc = -1;
00464
00465 if (d->handle == -1) {
00466 return rc;
00467 }
00468
00469 QDBusReply<int> r = walletLauncher->getInterface().renameEntry(d->handle, d->folder, oldName, newName, appid());
00470 if (r.isValid()) {
00471 rc = r;
00472 }
00473
00474 return rc;
00475 }
00476
00477
00478 int Wallet::readMap(const QString& key, QMap<QString,QString>& value) {
00479 registerTypes();
00480
00481 int rc = -1;
00482
00483 if (d->handle == -1) {
00484 return rc;
00485 }
00486
00487 QDBusReply<QByteArray> r = walletLauncher->getInterface().readMap(d->handle, d->folder, key, appid());
00488 if (r.isValid()) {
00489 rc = 0;
00490 QByteArray v = r;
00491 if (!v.isEmpty()) {
00492 QDataStream ds(&v, QIODevice::ReadOnly);
00493 ds >> value;
00494 }
00495 }
00496
00497 return rc;
00498 }
00499
00500
00501 int Wallet::readMapList(const QString& key, QMap<QString, QMap<QString, QString> >& value) {
00502 registerTypes();
00503
00504 int rc = -1;
00505
00506 if (d->handle == -1) {
00507 return rc;
00508 }
00509
00510 QDBusReply<QVariantMap> r =
00511 walletLauncher->getInterface().readMapList(d->handle, d->folder, key, appid());
00512 if (r.isValid()) {
00513 rc = 0;
00514 const QVariantMap val = r.value();
00515 for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
00516 QByteArray mapData = it.value().toByteArray();
00517 if (!mapData.isEmpty()) {
00518 QDataStream ds(&mapData, QIODevice::ReadOnly);
00519 QMap<QString,QString> v;
00520 ds >> v;
00521 value.insert(it.key(), v);
00522 }
00523 }
00524 }
00525
00526 return rc;
00527 }
00528
00529
00530 int Wallet::readPassword(const QString& key, QString& value) {
00531 int rc = -1;
00532
00533 if (d->handle == -1) {
00534 return rc;
00535 }
00536
00537 QDBusReply<QString> r = walletLauncher->getInterface().readPassword(d->handle, d->folder, key, appid());
00538 if (r.isValid()) {
00539 value = r;
00540 rc = 0;
00541 }
00542
00543 return rc;
00544 }
00545
00546
00547 int Wallet::readPasswordList(const QString& key, QMap<QString, QString>& value) {
00548 registerTypes();
00549
00550 int rc = -1;
00551
00552 if (d->handle == -1) {
00553 return rc;
00554 }
00555
00556 QDBusReply<QVariantMap> r = walletLauncher->getInterface().readPasswordList(d->handle, d->folder, key, appid());
00557 if (r.isValid()) {
00558 rc = 0;
00559 const QVariantMap val = r.value();
00560 for( QVariantMap::const_iterator it = val.begin(); it != val.end(); ++it ) {
00561 value.insert(it.key(), it.value().toString());
00562 }
00563 }
00564
00565 return rc;
00566 }
00567
00568
00569 int Wallet::writeEntry(const QString& key, const QByteArray& value, EntryType entryType) {
00570 int rc = -1;
00571
00572 if (d->handle == -1) {
00573 return rc;
00574 }
00575
00576 QDBusReply<int> r = walletLauncher->getInterface().writeEntry(d->handle, d->folder, key, value, int(entryType), appid());
00577 if (r.isValid()) {
00578 rc = r;
00579 }
00580
00581 return rc;
00582 }
00583
00584
00585 int Wallet::writeEntry(const QString& key, const QByteArray& value) {
00586 int rc = -1;
00587
00588 if (d->handle == -1) {
00589 return rc;
00590 }
00591
00592 QDBusReply<int> r = walletLauncher->getInterface().writeEntry(d->handle, d->folder, key, value, appid());
00593 if (r.isValid()) {
00594 rc = r;
00595 }
00596
00597 return rc;
00598 }
00599
00600
00601 int Wallet::writeMap(const QString& key, const QMap<QString,QString>& value) {
00602 registerTypes();
00603
00604 int rc = -1;
00605
00606 if (d->handle == -1) {
00607 return rc;
00608 }
00609
00610 QByteArray mapData;
00611 QDataStream ds(&mapData, QIODevice::WriteOnly);
00612 ds << value;
00613 QDBusReply<int> r = walletLauncher->getInterface().writeMap(d->handle, d->folder, key, mapData, appid());
00614 if (r.isValid()) {
00615 rc = r;
00616 }
00617
00618 return rc;
00619 }
00620
00621
00622 int Wallet::writePassword(const QString& key, const QString& value) {
00623 int rc = -1;
00624
00625 if (d->handle == -1) {
00626 return rc;
00627 }
00628
00629 QDBusReply<int> r = walletLauncher->getInterface().writePassword(d->handle, d->folder, key, value, appid());
00630 if (r.isValid()) {
00631 rc = r;
00632 }
00633
00634 return rc;
00635 }
00636
00637
00638 bool Wallet::hasEntry(const QString& key) {
00639 if (d->handle == -1) {
00640 return false;
00641 }
00642
00643 QDBusReply<bool> r = walletLauncher->getInterface().hasEntry(d->handle, d->folder, key, appid());
00644 return r;
00645 }
00646
00647
00648 int Wallet::removeEntry(const QString& key) {
00649 int rc = -1;
00650
00651 if (d->handle == -1) {
00652 return rc;
00653 }
00654
00655 QDBusReply<int> r = walletLauncher->getInterface().removeEntry(d->handle, d->folder, key, appid());
00656 if (r.isValid()) {
00657 rc = r;
00658 }
00659
00660 return rc;
00661 }
00662
00663
00664 Wallet::EntryType Wallet::entryType(const QString& key) {
00665 int rc = 0;
00666
00667 if (d->handle == -1) {
00668 return Wallet::Unknown;
00669 }
00670
00671 QDBusReply<int> r = walletLauncher->getInterface().entryType(d->handle, d->folder, key, appid());
00672 if (r.isValid()) {
00673 rc = r;
00674 }
00675
00676 return static_cast<EntryType>(rc);
00677 }
00678
00679
00680 void Wallet::slotServiceOwnerChanged(const QString& name,const QString& oldOwner,const QString& newOwner) {
00681 Q_UNUSED(oldOwner);
00682 if (newOwner.isEmpty() && name == "org.kde.kwalletd") {
00683
00684 if ( d->loop )
00685 d->loop->quit();
00686 if( d->handle >= 0 )
00687 slotWalletClosed(d->handle);
00688 }
00689 }
00690
00691
00692 void Wallet::slotFolderUpdated(const QString& wallet, const QString& folder) {
00693 if (d->name == wallet) {
00694 emit folderUpdated(folder);
00695 }
00696 }
00697
00698
00699 void Wallet::slotFolderListUpdated(const QString& wallet) {
00700 if (d->name == wallet) {
00701 emit folderListUpdated();
00702 }
00703 }
00704
00705
00706 void Wallet::slotApplicationDisconnected(const QString& wallet, const QString& application) {
00707 if (d->handle >= 0
00708 && d->name == wallet
00709 && application == appid()) {
00710 slotWalletClosed(d->handle);
00711 }
00712 }
00713
00714 void Wallet::walletAsyncOpened(int tId, int handle) {
00715
00716 if (d->transactionId != tId || d->handle != -1) {
00717 return;
00718 }
00719
00720
00721 disconnect(this, SLOT(walletAsyncOpened(int, int)));
00722
00723 d->handle = handle;
00724 emit walletOpened(handle > 0);
00725 }
00726
00727 void Wallet::emitWalletAsyncOpenError() {
00728 emit walletOpened(false);
00729 }
00730
00731 bool Wallet::folderDoesNotExist(const QString& wallet, const QString& folder)
00732 {
00733 QDBusReply<bool> r = walletLauncher->getInterface().folderDoesNotExist(wallet, folder);
00734 return r;
00735 }
00736
00737
00738 bool Wallet::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key)
00739 {
00740 QDBusReply<bool> r = walletLauncher->getInterface().keyDoesNotExist(wallet, folder, key);
00741 return r;
00742 }
00743
00744 void Wallet::virtual_hook(int, void*) {
00745
00746 }
00747
00748 KWalletDLauncher::KWalletDLauncher()
00749 : m_wallet("org.kde.kwalletd", "/modules/kwalletd", QDBusConnection::sessionBus()),
00750 m_cgroup(KSharedConfig::openConfig("kwalletrc", KConfig::NoGlobals)->group("Wallet"))
00751 {
00752 }
00753
00754 KWalletDLauncher::~KWalletDLauncher()
00755 {
00756 }
00757
00758 org::kde::KWallet &KWalletDLauncher::getInterface()
00759 {
00760
00761 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwalletd"))
00762 {
00763
00764 bool walletEnabled = m_cgroup.readEntry("Enabled", true);
00765 if (walletEnabled) {
00766
00767 QString error;
00768 int ret = KToolInvocation::startServiceByDesktopPath("kwalletd.desktop", QStringList(), &error);
00769 if (ret > 0)
00770 {
00771 kError(285) << "Couldn't start kwalletd: " << error << endl;
00772 }
00773
00774 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwalletd")) {
00775 kDebug(285) << "The kwalletd service is still not registered";
00776 } else {
00777 kDebug(285) << "The kwalletd service has been registered";
00778 }
00779 } else {
00780 kError(285) << "The kwalletd service has been disabled";
00781 }
00782 }
00783
00784 return m_wallet;
00785 }
00786
00787 #include "kwallet.moc"