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