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