1 /* This file is part of the KDE project
3 * Copyright (C) 2002-2004 George Staikos <staikos@kde.org>
4 * Copyright (C) 2008 Michael Leupold <lemma@confuego.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 #include <ksharedconfig.h>
25 #include <kdeversion.h>
26 #include <QtGui/QApplication>
27 #include <QtCore/QPointer>
28 #include <QtGui/QWidget>
29 #include <QtDBus/QtDBus>
30 #include <ktoolinvocation.h>
34 #include <kcomponentdata.h>
35 #include <kaboutdata.h>
36 #include <kconfiggroup.h>
38 #include "kwallet_interface.h"
40 using namespace KWallet
;
42 typedef QMap
<QString
, QString
> StringStringMap
;
43 Q_DECLARE_METATYPE(StringStringMap
)
44 typedef QMap
<QString
, StringStringMap
> StringToStringStringMapMap
;
45 Q_DECLARE_METATYPE(StringToStringStringMapMap
)
46 typedef QMap
<QString
, QByteArray
> StringByteArrayMap
;
47 Q_DECLARE_METATYPE(StringByteArrayMap
)
49 static QString
appid()
51 KComponentData cData
= KGlobal::mainComponent();
52 if (cData
.isValid()) {
53 const KAboutData
* aboutData
= cData
.aboutData();
55 return aboutData
->programName();
57 return cData
.componentName();
59 return qApp
->applicationName();
62 static void registerTypes()
64 static bool registered
= false;
66 qDBusRegisterMetaType
<StringStringMap
>();
67 qDBusRegisterMetaType
<StringToStringStringMapMap
>();
68 qDBusRegisterMetaType
<StringByteArrayMap
>();
73 const QString
Wallet::LocalWallet() {
74 KConfigGroup
cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
75 if (!cfg
.readEntry("Use One Wallet", true)) {
76 QString tmp
= cfg
.readEntry("Local Wallet", "localwallet");
83 QString tmp
= cfg
.readEntry("Default Wallet", "kdewallet");
90 const QString
Wallet::NetworkWallet() {
91 KConfigGroup
cfg(KSharedConfig::openConfig("kwalletrc")->group("Wallet"));
93 QString tmp
= cfg
.readEntry("Default Wallet", "kdewallet");
100 const QString
Wallet::PasswordFolder() {
104 const QString
Wallet::FormDataFolder() {
108 class Wallet::WalletPrivate
111 WalletPrivate(int h
, const QString
&n
)
118 QPointer
<QEventLoop
> loop
;
121 class KWalletDLauncher
126 org::kde::KWallet
&getInterface();
128 org::kde::KWallet m_wallet
;
129 KConfigGroup m_cgroup
;
132 K_GLOBAL_STATIC(KWalletDLauncher
, walletLauncher
)
134 Wallet::Wallet(int handle
, const QString
& name
)
135 : QObject(0L), d(new WalletPrivate(handle
, name
)) {
137 connect(QDBusConnection::sessionBus().interface(),
138 SIGNAL(serviceOwnerChanged(QString
,QString
,QString
)),
140 SLOT(slotServiceOwnerChanged(QString
,QString
,QString
)));
142 connect(&walletLauncher
->getInterface(), SIGNAL(walletClosed(int)), SLOT(slotWalletClosed(int)));
143 connect(&walletLauncher
->getInterface(), SIGNAL(folderListUpdated(QString
)), SLOT(slotFolderListUpdated(QString
)));
144 connect(&walletLauncher
->getInterface(), SIGNAL(folderUpdated(QString
,QString
)), SLOT(slotFolderUpdated(QString
, QString
)));
145 connect(&walletLauncher
->getInterface(), SIGNAL(applicationDisconnected(QString
, QString
)), SLOT(slotApplicationDisconnected(QString
, QString
)));
147 // Verify that the wallet is still open
148 if (d
->handle
!= -1) {
149 QDBusReply
<bool> r
= walletLauncher
->getInterface().isOpen(d
->handle
);
150 if (r
.isValid() && !r
) {
159 if (d
->handle
!= -1) {
160 if (!walletLauncher
.isDestroyed()) {
161 walletLauncher
->getInterface().close(d
->handle
, false, appid());
163 kDebug(285) << "Problem with static destruction sequence."
164 "Destroy any static Wallet before the event-loop exits.";
174 QStringList
Wallet::walletList() {
175 return walletLauncher
->getInterface().wallets();
179 void Wallet::changePassword(const QString
& name
, WId w
) {
181 kDebug(285) << "Pass a valid window to KWallet::Wallet::changePassword().";
182 walletLauncher
->getInterface().changePassword(name
, (qlonglong
)w
, appid());
186 bool Wallet::isEnabled() {
187 QDBusReply
<bool> r
= walletLauncher
->getInterface().isEnabled();
188 return (r
.isValid() && r
);
192 bool Wallet::isOpen(const QString
& name
) {
193 return walletLauncher
->getInterface().isOpen(name
); // default is false
197 int Wallet::closeWallet(const QString
& name
, bool force
) {
198 QDBusReply
<int> r
= walletLauncher
->getInterface().close(name
, force
);
199 return r
.isValid() ? r
: -1;
203 int Wallet::deleteWallet(const QString
& name
) {
204 QDBusReply
<int> r
= walletLauncher
->getInterface().deleteWallet(name
);
205 return r
.isValid() ? r
: -1;
209 Wallet
*Wallet::openWallet(const QString
& name
, WId w
, OpenType ot
) {
211 kDebug(285) << "Pass a valid window to KWallet::Wallet::openWallet().";
213 Wallet
*wallet
= new Wallet(-1, name
);
215 // connect the daemon's opened signal to the slot filtering the
217 connect(&walletLauncher
->getInterface(), SIGNAL(walletAsyncOpened(int, int)),
218 wallet
, SLOT(walletAsyncOpened(int, int)));
220 // Use an eventloop for synchronous calls
222 if (ot
== Synchronous
|| ot
== Path
) {
223 connect(wallet
, SIGNAL(walletOpened(bool)), &loop
, SLOT(quit()));
228 if (ot
== Synchronous
|| ot
== Asynchronous
) {
229 r
= walletLauncher
->getInterface().openAsync(name
, (qlonglong
)w
, appid(), true);
230 } else if (ot
== Path
) {
231 r
= walletLauncher
->getInterface().openPathAsync(name
, (qlonglong
)w
, appid(), true);
236 // error communicating with the daemon (maybe not running)
241 wallet
->d
->transactionId
= r
.value();
243 if (ot
== Synchronous
|| ot
== Path
) {
244 // check for an immediate error
245 if (wallet
->d
->transactionId
< 0) {
249 // wait for the daemon's reply
250 // store a pointer to the event loop so it can be quit in error case
251 wallet
->d
->loop
= &loop
;
253 if (wallet
->d
->handle
< 0) {
258 } else if (ot
== Asynchronous
) {
259 if (wallet
->d
->transactionId
< 0) {
260 QTimer::singleShot(0, wallet
, SLOT(emitWalletAsyncOpenError()));
261 // client code is responsible for deleting the wallet
269 bool Wallet::disconnectApplication(const QString
& wallet
, const QString
& app
) {
270 return walletLauncher
->getInterface().disconnectApplication(wallet
, app
); // default is false
274 QStringList
Wallet::users(const QString
& name
) {
275 return walletLauncher
->getInterface().users(name
); // default is QStringList()
280 if (d
->handle
== -1) {
284 walletLauncher
->getInterface().sync(d
->handle
, appid());
289 int Wallet::lockWallet() {
290 if (d
->handle
== -1) {
294 QDBusReply
<int> r
= walletLauncher
->getInterface().close(d
->handle
, true, appid());
305 const QString
& Wallet::walletName() const {
310 bool Wallet::isOpen() const {
311 return d
->handle
!= -1;
315 void Wallet::requestChangePassword(WId w
) {
317 kDebug(285) << "Pass a valid window to KWallet::Wallet::requestChangePassword().";
318 if (d
->handle
== -1) {
322 walletLauncher
->getInterface().changePassword(d
->name
, (qlonglong
)w
, appid());
326 void Wallet::slotWalletClosed(int handle
) {
327 if (d
->handle
== handle
) {
336 QStringList
Wallet::folderList() {
337 if (d
->handle
== -1) {
338 return QStringList();
341 QDBusReply
<QStringList
> r
= walletLauncher
->getInterface().folderList(d
->handle
, appid());
346 QStringList
Wallet::entryList() {
347 if (d
->handle
== -1) {
348 return QStringList();
351 QDBusReply
<QStringList
> r
= walletLauncher
->getInterface().entryList(d
->handle
, d
->folder
, appid());
356 bool Wallet::hasFolder(const QString
& f
) {
357 if (d
->handle
== -1) {
361 QDBusReply
<bool> r
= walletLauncher
->getInterface().hasFolder(d
->handle
, f
, appid());
362 return r
; // default is false
366 bool Wallet::createFolder(const QString
& f
) {
367 if (d
->handle
== -1) {
372 QDBusReply
<bool> r
= walletLauncher
->getInterface().createFolder(d
->handle
, f
, appid());
376 return true; // folder already exists
380 bool Wallet::setFolder(const QString
& f
) {
383 if (d
->handle
== -1) {
387 // Don't do this - the folder could have disappeared?
389 if (f
== d
->folder
) {
403 bool Wallet::removeFolder(const QString
& f
) {
404 if (d
->handle
== -1) {
408 QDBusReply
<bool> r
= walletLauncher
->getInterface().removeFolder(d
->handle
, f
, appid());
409 if (d
->folder
== f
) {
410 setFolder(QString());
413 return r
; // default is false
417 const QString
& Wallet::currentFolder() const {
422 int Wallet::readEntry(const QString
& key
, QByteArray
& value
) {
425 if (d
->handle
== -1) {
429 QDBusReply
<QByteArray
> r
= walletLauncher
->getInterface().readEntry(d
->handle
, d
->folder
, key
, appid());
439 int Wallet::readEntryList(const QString
& key
, QMap
<QString
, QByteArray
>& value
) {
444 if (d
->handle
== -1) {
448 QDBusReply
<QVariantMap
> r
= walletLauncher
->getInterface().readEntryList(d
->handle
, d
->folder
, key
, appid());
451 // convert <QString, QVariant> to <QString, QByteArray>
452 const QVariantMap val
= r
.value();
453 for( QVariantMap::const_iterator it
= val
.begin(); it
!= val
.end(); ++it
) {
454 value
.insert(it
.key(), it
.value().toByteArray());
462 int Wallet::renameEntry(const QString
& oldName
, const QString
& newName
) {
465 if (d
->handle
== -1) {
469 QDBusReply
<int> r
= walletLauncher
->getInterface().renameEntry(d
->handle
, d
->folder
, oldName
, newName
, appid());
478 int Wallet::readMap(const QString
& key
, QMap
<QString
,QString
>& value
) {
483 if (d
->handle
== -1) {
487 QDBusReply
<QByteArray
> r
= walletLauncher
->getInterface().readMap(d
->handle
, d
->folder
, key
, appid());
492 QDataStream
ds(&v
, QIODevice::ReadOnly
);
501 int Wallet::readMapList(const QString
& key
, QMap
<QString
, QMap
<QString
, QString
> >& value
) {
506 if (d
->handle
== -1) {
510 QDBusReply
<QVariantMap
> r
=
511 walletLauncher
->getInterface().readMapList(d
->handle
, d
->folder
, key
, appid());
514 const QVariantMap val
= r
.value();
515 for( QVariantMap::const_iterator it
= val
.begin(); it
!= val
.end(); ++it
) {
516 QByteArray mapData
= it
.value().toByteArray();
517 if (!mapData
.isEmpty()) {
518 QDataStream
ds(&mapData
, QIODevice::ReadOnly
);
519 QMap
<QString
,QString
> v
;
521 value
.insert(it
.key(), v
);
530 int Wallet::readPassword(const QString
& key
, QString
& value
) {
533 if (d
->handle
== -1) {
537 QDBusReply
<QString
> r
= walletLauncher
->getInterface().readPassword(d
->handle
, d
->folder
, key
, appid());
547 int Wallet::readPasswordList(const QString
& key
, QMap
<QString
, QString
>& value
) {
552 if (d
->handle
== -1) {
556 QDBusReply
<QVariantMap
> r
= walletLauncher
->getInterface().readPasswordList(d
->handle
, d
->folder
, key
, appid());
559 const QVariantMap val
= r
.value();
560 for( QVariantMap::const_iterator it
= val
.begin(); it
!= val
.end(); ++it
) {
561 value
.insert(it
.key(), it
.value().toString());
569 int Wallet::writeEntry(const QString
& key
, const QByteArray
& value
, EntryType entryType
) {
572 if (d
->handle
== -1) {
576 QDBusReply
<int> r
= walletLauncher
->getInterface().writeEntry(d
->handle
, d
->folder
, key
, value
, int(entryType
), appid());
585 int Wallet::writeEntry(const QString
& key
, const QByteArray
& value
) {
588 if (d
->handle
== -1) {
592 QDBusReply
<int> r
= walletLauncher
->getInterface().writeEntry(d
->handle
, d
->folder
, key
, value
, appid());
601 int Wallet::writeMap(const QString
& key
, const QMap
<QString
,QString
>& value
) {
606 if (d
->handle
== -1) {
611 QDataStream
ds(&mapData
, QIODevice::WriteOnly
);
613 QDBusReply
<int> r
= walletLauncher
->getInterface().writeMap(d
->handle
, d
->folder
, key
, mapData
, appid());
622 int Wallet::writePassword(const QString
& key
, const QString
& value
) {
625 if (d
->handle
== -1) {
629 QDBusReply
<int> r
= walletLauncher
->getInterface().writePassword(d
->handle
, d
->folder
, key
, value
, appid());
638 bool Wallet::hasEntry(const QString
& key
) {
639 if (d
->handle
== -1) {
643 QDBusReply
<bool> r
= walletLauncher
->getInterface().hasEntry(d
->handle
, d
->folder
, key
, appid());
644 return r
; // default is false
648 int Wallet::removeEntry(const QString
& key
) {
651 if (d
->handle
== -1) {
655 QDBusReply
<int> r
= walletLauncher
->getInterface().removeEntry(d
->handle
, d
->folder
, key
, appid());
664 Wallet::EntryType
Wallet::entryType(const QString
& key
) {
667 if (d
->handle
== -1) {
668 return Wallet::Unknown
;
671 QDBusReply
<int> r
= walletLauncher
->getInterface().entryType(d
->handle
, d
->folder
, key
, appid());
676 return static_cast<EntryType
>(rc
);
680 void Wallet::slotServiceOwnerChanged(const QString
& name
,const QString
& oldOwner
,const QString
& newOwner
) {
682 if (newOwner
.isEmpty() && name
== "org.kde.kwalletd") {
683 // if openWallet() waits for the DBUS reply, prevent it from waiting forever:
687 slotWalletClosed(d
->handle
);
692 void Wallet::slotFolderUpdated(const QString
& wallet
, const QString
& folder
) {
693 if (d
->name
== wallet
) {
694 emit
folderUpdated(folder
);
699 void Wallet::slotFolderListUpdated(const QString
& wallet
) {
700 if (d
->name
== wallet
) {
701 emit
folderListUpdated();
706 void Wallet::slotApplicationDisconnected(const QString
& wallet
, const QString
& application
) {
709 && application
== appid()) {
710 slotWalletClosed(d
->handle
);
714 void Wallet::walletAsyncOpened(int tId
, int handle
) {
715 // ignore responses to calls other than ours
716 if (d
->transactionId
!= tId
|| d
->handle
!= -1) {
720 // disconnect the async signal
721 disconnect(this, SLOT(walletAsyncOpened(int, int)));
724 emit
walletOpened(handle
> 0);
727 void Wallet::emitWalletAsyncOpenError() {
728 emit
walletOpened(false);
731 bool Wallet::folderDoesNotExist(const QString
& wallet
, const QString
& folder
)
733 QDBusReply
<bool> r
= walletLauncher
->getInterface().folderDoesNotExist(wallet
, folder
);
738 bool Wallet::keyDoesNotExist(const QString
& wallet
, const QString
& folder
, const QString
& key
)
740 QDBusReply
<bool> r
= walletLauncher
->getInterface().keyDoesNotExist(wallet
, folder
, key
);
744 void Wallet::virtual_hook(int, void*) {
745 //BASE::virtual_hook( id, data );
748 KWalletDLauncher::KWalletDLauncher()
749 : m_wallet("org.kde.kwalletd", "/modules/kwalletd", QDBusConnection::sessionBus()),
750 m_cgroup(KSharedConfig::openConfig("kwalletrc", KConfig::NoGlobals
)->group("Wallet"))
754 KWalletDLauncher::~KWalletDLauncher()
758 org::kde::KWallet
&KWalletDLauncher::getInterface()
760 // check if kwalletd is already running
761 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwalletd"))
763 // not running! check if it is enabled.
764 bool walletEnabled
= m_cgroup
.readEntry("Enabled", true);
766 // wallet is enabled! try launching it
768 int ret
= KToolInvocation::startServiceByDesktopPath("kwalletd.desktop", QStringList(), &error
);
771 kError(285) << "Couldn't start kwalletd: " << error
<< endl
;
774 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwalletd")) {
775 kDebug(285) << "The kwalletd service is still not registered";
777 kDebug(285) << "The kwalletd service has been registered";
780 kError(285) << "The kwalletd service has been disabled";
787 #include "kwallet.moc"