From ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kio/misc/kwalletd/Makefile.am | 35 + kio/misc/kwalletd/kbetterthankdialogbase.ui | 154 +++ kio/misc/kwalletd/kbetterthankdialogbase.ui.h | 50 + kio/misc/kwalletd/ktimeout.cpp | 84 ++ kio/misc/kwalletd/ktimeout.h | 52 + kio/misc/kwalletd/kwalletd.cpp | 1428 +++++++++++++++++++++++++ kio/misc/kwalletd/kwalletd.desktop | 151 +++ kio/misc/kwalletd/kwalletd.h | 195 ++++ kio/misc/kwalletd/kwalletwizard.ui | 545 ++++++++++ kio/misc/kwalletd/kwalletwizard.ui.h | 74 ++ 10 files changed, 2768 insertions(+) create mode 100644 kio/misc/kwalletd/Makefile.am create mode 100644 kio/misc/kwalletd/kbetterthankdialogbase.ui create mode 100644 kio/misc/kwalletd/kbetterthankdialogbase.ui.h create mode 100644 kio/misc/kwalletd/ktimeout.cpp create mode 100644 kio/misc/kwalletd/ktimeout.h create mode 100644 kio/misc/kwalletd/kwalletd.cpp create mode 100644 kio/misc/kwalletd/kwalletd.desktop create mode 100644 kio/misc/kwalletd/kwalletd.h create mode 100644 kio/misc/kwalletd/kwalletwizard.ui create mode 100644 kio/misc/kwalletd/kwalletwizard.ui.h (limited to 'kio/misc/kwalletd') diff --git a/kio/misc/kwalletd/Makefile.am b/kio/misc/kwalletd/Makefile.am new file mode 100644 index 000000000..f57f2c692 --- /dev/null +++ b/kio/misc/kwalletd/Makefile.am @@ -0,0 +1,35 @@ +# This file is part of the KDE libraries +# Copyright (C) 2002 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES= -I$(srcdir)/.. -I$(top_srcdir) -I$(top_srcdir)/kwallet/backend -I$(top_builddir)/kwallet/backend -I$(top_srcdir)/kwallet/client -I$(top_builddir)/kwallet/client $(all_includes) + +kde_module_LTLIBRARIES = kded_kwalletd.la + +kded_kwalletd_la_LDFLAGS = $(all_libraries) -module -avoid-version +kded_kwalletd_la_LIBADD = $(LIB_KIO) ../../../kwallet/backend/libkwalletbackend.la ../../../kwallet/client/libkwalletclient.la $(LIB_KDED) +kded_kwalletd_la_SOURCES = kwalletd.cpp kwalletd.skel ktimeout.cpp kwalletwizard.ui kbetterthankdialogbase.ui + +METASOURCES = AUTO + +noinst_HEADERS = kwalletd.h ktimeout.h kwalletwizard.ui.h + +services_DATA = kwalletd.desktop +servicesdir = $(kde_servicesdir)/kded + +kwalletwizard.lo: kwalletwizard.ui kwalletwizard.ui.h +kbetterthankdialogbase.lo: kbetterthankdialogbase.ui kbetterthankdialogbase.ui.h diff --git a/kio/misc/kwalletd/kbetterthankdialogbase.ui b/kio/misc/kwalletd/kbetterthankdialogbase.ui new file mode 100644 index 000000000..ecf2d236f --- /dev/null +++ b/kio/misc/kwalletd/kbetterthankdialogbase.ui @@ -0,0 +1,154 @@ + +KBetterThanKDialogBase + + + KBetterThanKDialogBase + + + + 0 + 0 + 479 + 109 + + + + + + + + unnamed + + + Fixed + + + + _label + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 41 + 21 + + + + + + layout1 + + + + unnamed + + + + _allowOnce + + + Allow &Once + + + true + + + + + _allowAlways + + + Allow &Always + + + + + _deny + + + &Deny + + + + + _denyForever + + + Deny &Forever + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 61 + 21 + + + + + + + + + + _allowOnce + clicked() + KBetterThanKDialogBase + clicked() + + + _allowAlways + clicked() + KBetterThanKDialogBase + clicked() + + + _deny + clicked() + KBetterThanKDialogBase + clicked() + + + _denyForever + clicked() + KBetterThanKDialogBase + clicked() + + + + kactivelabel.h + kbetterthankdialogbase.ui.h + + + clicked() + setLabel( const QString & label ) + init() + accept() + reject() + + + + kactivelabel.h + + diff --git a/kio/misc/kwalletd/kbetterthankdialogbase.ui.h b/kio/misc/kwalletd/kbetterthankdialogbase.ui.h new file mode 100644 index 000000000..565e0880e --- /dev/null +++ b/kio/misc/kwalletd/kbetterthankdialogbase.ui.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + + +void KBetterThanKDialogBase::clicked() +{ + if (sender() == _allowOnce) { + done(0); + } else if (sender() == _allowAlways) { + done(1); + } else if (sender() == _deny) { + done(2); + } else if (sender() == _denyForever) { + done(3); + } +} + + +void KBetterThanKDialogBase::setLabel( const QString & label ) +{ + _label->setText(label); +} + + +void KBetterThanKDialogBase::init() +{ + _allowOnce->setFocus(); +} + + +void KBetterThanKDialogBase::accept() +{ + setResult(0); +} + + +void KBetterThanKDialogBase::reject() +{ + QDialog::reject(); + setResult(2); +} diff --git a/kio/misc/kwalletd/ktimeout.cpp b/kio/misc/kwalletd/ktimeout.cpp new file mode 100644 index 000000000..1827b8bba --- /dev/null +++ b/kio/misc/kwalletd/ktimeout.cpp @@ -0,0 +1,84 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "ktimeout.h" + +KTimeout::KTimeout(int size) +: QObject(), _timers(size) { + _timers.setAutoDelete(true); +} + + +KTimeout::~KTimeout() { + clear(); +} + + +void KTimeout::clear() { + _timers.clear(); +} + + +void KTimeout::removeTimer(int id) { + QTimer *t = _timers.find(id); + if (t != 0L) { + _timers.remove(id); // autodeletes + } +} + + +void KTimeout::addTimer(int id, int timeout) { + if (_timers.find(id) != 0L) { + return; + } + + QTimer *t = new QTimer; + connect(t, SIGNAL(timeout()), this, SLOT(timeout())); + t->start(timeout); + _timers.insert(id, t); +} + + +void KTimeout::resetTimer(int id, int timeout) { + QTimer *t = _timers.find(id); + if (t) { + t->changeInterval(timeout); + } +} + + +void KTimeout::timeout() { + const QTimer *t = static_cast(sender()); + if (t) { + QIntDictIterator it(_timers); + for (; it.current(); ++it) { + if (it.current() == t) { + emit timedOut(it.currentKey()); + return; + } + } + } +} + + +#include "ktimeout.moc" + diff --git a/kio/misc/kwalletd/ktimeout.h b/kio/misc/kwalletd/ktimeout.h new file mode 100644 index 000000000..287de44cb --- /dev/null +++ b/kio/misc/kwalletd/ktimeout.h @@ -0,0 +1,52 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _KTIMEOUT_H_ +#define _KTIMEOUT_H_ + +#include +#include +#include + +// @internal +class KTimeout : public QObject { + Q_OBJECT + public: + KTimeout(int size = 29); + virtual ~KTimeout(); + + signals: + void timedOut(int id); + + public slots: + void resetTimer(int id, int timeout); + void addTimer(int id, int timeout); + void removeTimer(int id); + void clear(); + + private slots: + void timeout(); + + private: + QIntDict _timers; +}; + +#endif diff --git a/kio/misc/kwalletd/kwalletd.cpp b/kio/misc/kwalletd/kwalletd.cpp new file mode 100644 index 000000000..686a99d6f --- /dev/null +++ b/kio/misc/kwalletd/kwalletd.cpp @@ -0,0 +1,1428 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2002-2004 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "kbetterthankdialogbase.h" +#include "kwalletwizard.h" +#include "kwalletd.h" +#include "ktimeout.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { + KDE_EXPORT KDEDModule *create_kwalletd(const QCString &name) { + return new KWalletD(name); + } +} + + +class KWalletTransaction { + public: + KWalletTransaction() { + tType = Unknown; + transaction = 0L; + client = 0L; + modal = false; + } + + ~KWalletTransaction() { + // Don't delete these! + transaction = 0L; + client = 0L; + } + + enum Type { Unknown, Open, ChangePassword, OpenFail }; + DCOPClient *client; + DCOPClientTransaction *transaction; + Type tType; + QCString rawappid, returnObject; + QCString appid; + uint wId; + QString wallet; + bool modal; +}; + + +KWalletD::KWalletD(const QCString &name) +: KDEDModule(name), _failed(0) { + srand(time(0)); + _showingFailureNotify = false; + _transactions.setAutoDelete(true); + _timeouts = new KTimeout(17); + _closeIdle = false; + _idleTime = 0; + connect(_timeouts, SIGNAL(timedOut(int)), this, SLOT(timedOut(int))); + reconfigure(); + KGlobal::dirs()->addResourceType("kwallet", "share/apps/kwallet"); + connect(KApplication::dcopClient(), + SIGNAL(applicationRemoved(const QCString&)), + this, + SLOT(slotAppUnregistered(const QCString&))); + _dw = new KDirWatch(this, "KWallet Directory Watcher"); + _dw->addDir(KGlobal::dirs()->saveLocation("kwallet")); + _dw->startScan(true); + connect(_dw, SIGNAL(dirty(const QString&)), this, SLOT(emitWalletListDirty())); +} + + +KWalletD::~KWalletD() { + delete _timeouts; + _timeouts = 0; + + closeAllWallets(); + _transactions.clear(); +} + + +int KWalletD::generateHandle() { + int rc; + + // ASSUMPTION: RAND_MAX is fairly large. + do { + rc = rand(); + } while (_wallets.find(rc) || rc == 0); + + return rc; +} + + +void KWalletD::processTransactions() { + static bool processing = false; + + if (processing) { + return; + } + + processing = true; + + // Process remaining transactions + KWalletTransaction *xact; + while (!_transactions.isEmpty()) { + xact = _transactions.first(); + QCString replyType; + int res; + + assert(xact->tType != KWalletTransaction::Unknown); + + switch (xact->tType) { + case KWalletTransaction::Open: + res = doTransactionOpen(xact->appid, xact->wallet, xact->wId, xact->modal); + replyType = "int"; + if (!xact->returnObject.isEmpty()) { + DCOPRef(xact->rawappid, xact->returnObject).send("walletOpenResult", res); + } + + // multiple requests from the same client + // should not produce multiple password + // dialogs on a failure + if (res < 0) { + QPtrListIterator it(_transactions); + KWalletTransaction *x; + while ((x = it.current()) && x != xact) { + ++it; + } + if (x) { + ++it; + } + while ((x = it.current())) { + if (xact->appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == xact->wallet && x->wId == xact->wId) { + x->tType = KWalletTransaction::OpenFail; + } + ++it; + } + } + break; + case KWalletTransaction::OpenFail: + res = -1; + replyType = "int"; + if (!xact->returnObject.isEmpty()) { + DCOPRef(xact->rawappid, xact->returnObject).send("walletOpenResult", res); + } + break; + case KWalletTransaction::ChangePassword: + doTransactionChangePassword(xact->appid, xact->wallet, xact->wId); + // fall through - no return + default: + _transactions.removeRef(xact); + continue; + } + + if (xact->returnObject.isEmpty() && xact->tType != KWalletTransaction::ChangePassword) { + QByteArray replyData; + QDataStream stream(replyData, IO_WriteOnly); + stream << res; + xact->client->endTransaction(xact->transaction, replyType, replyData); + } + _transactions.removeRef(xact); + } + + processing = false; +} + + +void KWalletD::openAsynchronous(const QString& wallet, const QCString& returnObject, uint wId) { + DCOPClient *dc = callingDcopClient(); + if (!dc) { + return; + } + + QCString appid = dc->senderId(); + if (!_enabled || + !QRegExp("^[A-Za-z0-9]+[A-Za-z0-9\\s\\-_]*$").exactMatch(wallet)) { + DCOPRef(appid, returnObject).send("walletOpenResult", -1); + return; + } + + QCString peerName = friendlyDCOPPeerName(); + + KWalletTransaction *xact = new KWalletTransaction; + + xact->appid = peerName; + xact->rawappid = appid; + xact->client = callingDcopClient(); + xact->wallet = wallet; + xact->wId = wId; + xact->tType = KWalletTransaction::Open; + xact->returnObject = returnObject; + _transactions.append(xact); + + DCOPRef(appid, returnObject).send("walletOpenResult", 0); + + QTimer::singleShot(0, this, SLOT(processTransactions())); + checkActiveDialog(); +} + + +int KWalletD::openPath(const QString& path, uint wId) { + if (!_enabled) { // guard + return -1; + } + + // FIXME: setup transaction + int rc = internalOpen(friendlyDCOPPeerName(), path, true, wId); + return rc; +} + + +int KWalletD::open(const QString& wallet, uint wId) { + if (!_enabled) { // guard + return -1; + } + + if (!QRegExp("^[A-Za-z0-9]+[A-Za-z0-9\\s\\-_]*$").exactMatch(wallet)) { + return -1; + } + + QCString appid = friendlyDCOPPeerName(); + + KWalletTransaction *xact = new KWalletTransaction; + _transactions.append(xact); + + xact->appid = appid; + xact->client = callingDcopClient(); + xact->transaction = xact->client->beginTransaction(); + xact->wallet = wallet; + xact->wId = wId; + xact->tType = KWalletTransaction::Open; + xact->modal = true; // mark dialogs as modal, the app has blocking wait + QTimer::singleShot(0, this, SLOT(processTransactions())); + checkActiveDialog(); + return 0; // process later +} + + +// Sets up a dialog that will be shown by kwallet. +void KWalletD::setupDialog( QWidget* dialog, WId wId, const QCString& appid, bool modal ) { + if( wId != 0 ) + KWin::setMainWindow( dialog, wId ); // correct, set dialog parent + else { + if( appid.isEmpty()) + kdWarning() << "Using kwallet without parent window!" << endl; + else + kdWarning() << "Application '" << appid << "' using kwallet without parent window!" << endl; + // allow dialog activation even if it interrupts, better than trying hacks + // with keeping the dialog on top or on all desktops + kapp->updateUserTimestamp(); + } + if( modal ) + KWin::setState( dialog->winId(), NET::Modal ); + else + KWin::clearState( dialog->winId(), NET::Modal ); + activeDialog = dialog; +} + +// If there's a dialog already open and another application tries some operation that'd lead to +// opening a dialog, that application will be blocked by this dialog. A proper solution would +// be to set the second application's window also as a parent for the active dialog, so that +// KWin properly handles focus changes and so on, but there's currently no support for multiple +// dialog parents. Hopefully to be done in KDE4, for now just use all kinds of bad hacks to make +// sure the user doesn't overlook the active dialog. +void KWalletD::checkActiveDialog() { + if( !activeDialog || !activeDialog->isShown()) + return; + kapp->updateUserTimestamp(); + KWin::setState( activeDialog->winId(), NET::KeepAbove ); + KWin::setOnAllDesktops( activeDialog->winId(), true ); + KWin::forceActiveWindow( activeDialog->winId()); +} + +int KWalletD::doTransactionOpen(const QCString& appid, const QString& wallet, uint wId, bool modal) { + if (_firstUse && !wallets().contains(KWallet::Wallet::LocalWallet())) { + // First use wizard + KWalletWizard *wiz = new KWalletWizard(0); + setupDialog( wiz, wId, appid, modal ); + int rc = wiz->exec(); + if (rc == QDialog::Accepted) { + KConfig cfg("kwalletrc"); + cfg.setGroup("Wallet"); + cfg.writeEntry("First Use", false); + cfg.writeEntry("Enabled", wiz->_useWallet->isChecked()); + cfg.writeEntry("Close When Idle", wiz->_closeIdle->isChecked()); + cfg.writeEntry("Use One Wallet", !wiz->_networkWallet->isChecked()); + cfg.sync(); + reconfigure(); + + if (!wiz->_useWallet->isChecked()) { + delete wiz; + return -1; + } + + // Create the wallet + KWallet::Backend *b = new KWallet::Backend(KWallet::Wallet::LocalWallet()); + QByteArray p; + p.duplicate(wiz->_pass1->text().utf8(), wiz->_pass1->text().length()); + b->open(p); + b->createFolder(KWallet::Wallet::PasswordFolder()); + b->createFolder(KWallet::Wallet::FormDataFolder()); + b->close(p); + p.fill(0); + delete b; + delete wiz; + } else { + delete wiz; + return -1; + } + } else if (_firstUse) { + KConfig cfg("kwalletrc"); + _firstUse = false; + cfg.setGroup("Wallet"); + cfg.writeEntry("First Use", false); + cfg.sync(); + } + + int rc = internalOpen(appid, wallet, false, wId, modal); + return rc; +} + + +int KWalletD::internalOpen(const QCString& appid, const QString& wallet, bool isPath, WId w, bool modal) { + int rc = -1; + bool brandNew = false; + + QCString thisApp; + if (appid.isEmpty()) { + thisApp = "KDE System"; + } else { + thisApp = appid; + } + + if (implicitDeny(wallet, thisApp)) { + return -1; + } + + for (QIntDictIterator i(_wallets); i.current(); ++i) { + if (i.current()->walletName() == wallet) { + rc = i.currentKey(); + break; + } + } + + if (rc == -1) { + if (_wallets.count() > 20) { + kdDebug() << "Too many wallets open." << endl; + return -1; + } + + KWallet::Backend *b = new KWallet::Backend(wallet, isPath); + KPasswordDialog *kpd = 0L; + bool emptyPass = false; + if ((isPath && QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) { + int pwless = b->open(QByteArray()); + if (0 != pwless || !b->isOpen()) { + if (pwless == 0) { + // release, start anew + delete b; + b = new KWallet::Backend(wallet, isPath); + } + kpd = new KPasswordDialog(KPasswordDialog::Password, false, 0); + if (appid.isEmpty()) { + kpd->setPrompt(i18n("KDE has requested to open the wallet '%1'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(wallet))); + } else { + kpd->setPrompt(i18n("The application '%1' has requested to open the wallet '%2'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet))); + } + brandNew = false; + kpd->setButtonOK(KGuiItem(i18n("&Open"),"fileopen")); + } else { + emptyPass = true; + } + } else if (wallet == KWallet::Wallet::LocalWallet() || + wallet == KWallet::Wallet::NetworkWallet()) { + // Auto create these wallets. + kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); + if (appid.isEmpty()) { + kpd->setPrompt(i18n("KDE has requested to open the wallet. This is used to store sensitive data in a secure fashion. Please enter a password to use with this wallet or click cancel to deny the application's request.")); + } else { + kpd->setPrompt(i18n("The application '%1' has requested to open the KDE wallet. This is used to store sensitive data in a secure fashion. Please enter a password to use with this wallet or click cancel to deny the application's request.").arg(QStyleSheet::escape(appid))); + } + brandNew = true; + kpd->setButtonOK(KGuiItem(i18n("&Open"),"fileopen")); + } else { + kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); + if (appid.length() == 0) { + kpd->setPrompt(i18n("KDE has requested to create a new wallet named '%1'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(wallet))); + } else { + kpd->setPrompt(i18n("The application '%1' has requested to create a new wallet named '%2'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet))); + } + brandNew = true; + kpd->setButtonOK(KGuiItem(i18n("C&reate"),"filenew")); + } + + if (kpd) { + kpd->setCaption(i18n("KDE Wallet Service")); + kpd->setAllowEmptyPasswords(true); + } + + const char *p = 0L; + while (!b->isOpen()) { + assert(kpd); // kpd can't be null if isOpen() is false + setupDialog( kpd, w, appid, modal ); + if (kpd->exec() == KDialog::Accepted) { + p = kpd->password(); + int rc = b->open(QByteArray().duplicate(p, strlen(p))); + if (!b->isOpen()) { + kpd->setPrompt(i18n("Error opening the wallet '%1'. Please try again.
(Error code %2: %3)").arg(QStyleSheet::escape(wallet)).arg(rc).arg(KWallet::Backend::openRCToString(rc))); + kpd->clearPassword(); + } + } else { + break; + } + } + + if (!emptyPass && (!p || !b->isOpen())) { + delete b; + delete kpd; + return -1; + } + + if (emptyPass && _openPrompt && !isAuthorizedApp(appid, wallet, w)) { + delete b; + delete kpd; + return -1; + } + + _wallets.insert(rc = generateHandle(), b); + if (emptyPass) { + _passwords[wallet] = ""; + } else { + _passwords[wallet] = p; + } + _handles[appid].append(rc); + + delete kpd; // don't refactor this!! Argh I hate KPassDlg + + if (brandNew) { + createFolder(rc, KWallet::Wallet::PasswordFolder()); + createFolder(rc, KWallet::Wallet::FormDataFolder()); + } + + b->ref(); + if (_closeIdle && _timeouts) { + _timeouts->addTimer(rc, _idleTime); + } + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << wallet; + if (brandNew) { + emitDCOPSignal("walletCreated(QString)", data); + } + emitDCOPSignal("walletOpened(QString)", data); + if (_wallets.count() == 1 && _launchManager) { + KApplication::startServiceByDesktopName("kwalletmanager-kwalletd"); + } + } else { + if (!_handles[appid].contains(rc) && _openPrompt && !isAuthorizedApp(appid, wallet, w)) { + return -1; + } + _handles[appid].append(rc); + _wallets.find(rc)->ref(); + } + + return rc; +} + + +bool KWalletD::isAuthorizedApp(const QCString& appid, const QString& wallet, WId w) { + int response = 0; + + QCString thisApp; + if (appid.isEmpty()) { + thisApp = "KDE System"; + } else { + thisApp = appid; + } + + if (!implicitAllow(wallet, thisApp)) { + KBetterThanKDialogBase *dialog = new KBetterThanKDialogBase; + if (appid.isEmpty()) { + dialog->setLabel(i18n("KDE has requested access to the open wallet '%1'.").arg(QStyleSheet::escape(wallet))); + } else { + dialog->setLabel(i18n("The application '%1' has requested access to the open wallet '%2'.").arg(QStyleSheet::escape(QString(appid))).arg(QStyleSheet::escape(wallet))); + } + setupDialog( dialog, w, appid, false ); + response = dialog->exec(); + delete dialog; + } + + if (response == 0 || response == 1) { + if (response == 1) { + KConfig cfg("kwalletrc"); + cfg.setGroup("Auto Allow"); + QStringList apps = cfg.readListEntry(wallet); + if (!apps.contains(thisApp)) { + apps += thisApp; + _implicitAllowMap[wallet] += thisApp; + cfg.writeEntry(wallet, apps); + cfg.sync(); + } + } + } else if (response == 3) { + KConfig cfg("kwalletrc"); + cfg.setGroup("Auto Deny"); + QStringList apps = cfg.readListEntry(wallet); + if (!apps.contains(thisApp)) { + apps += thisApp; + _implicitDenyMap[wallet] += thisApp; + cfg.writeEntry(wallet, apps); + cfg.sync(); + } + return false; + } else { + return false; + } + return true; +} + + +int KWalletD::deleteWallet(const QString& wallet) { + QString path = KGlobal::dirs()->saveLocation("kwallet") + QDir::separator() + wallet + ".kwl"; + + if (QFile::exists(path)) { + close(wallet, true); + QFile::remove(path); + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << wallet; + emitDCOPSignal("walletDeleted(QString)", data); + return 0; + } + + return -1; +} + + +void KWalletD::changePassword(const QString& wallet, uint wId) { + QCString appid = friendlyDCOPPeerName(); + + KWalletTransaction *xact = new KWalletTransaction; + + xact->appid = appid; + xact->client = callingDcopClient(); + xact->wallet = wallet; + xact->wId = wId; + xact->tType = KWalletTransaction::ChangePassword; + + _transactions.append(xact); + + QTimer::singleShot(0, this, SLOT(processTransactions())); + checkActiveDialog(); +} + + +void KWalletD::doTransactionChangePassword(const QCString& appid, const QString& wallet, uint wId) { + QIntDictIterator it(_wallets); + KWallet::Backend *w = 0L; + int handle = -1; + bool reclose = false; + + for (; it.current(); ++it) { + if (it.current()->walletName() == wallet) { + break; + } + } + + if (!it.current()) { + handle = doTransactionOpen(appid, wallet, wId,false); + if (-1 == handle) { + KMessageBox::sorryWId(wId, i18n("Unable to open wallet. The wallet must be opened in order to change the password."), i18n("KDE Wallet Service")); + return; + } + + w = _wallets.find(handle); + reclose = true; + } else { + handle = it.currentKey(); + w = it.current(); + } + + assert(w); + + KPasswordDialog *kpd; + kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); + kpd->setPrompt(i18n("Please choose a new password for the wallet '%1'.").arg(QStyleSheet::escape(wallet))); + kpd->setCaption(i18n("KDE Wallet Service")); + kpd->setAllowEmptyPasswords(true); + setupDialog( kpd, wId, appid, false ); + if (kpd->exec() == KDialog::Accepted) { + const char *p = kpd->password(); + if (p) { + _passwords[wallet] = p; + QByteArray pa; + pa.duplicate(p, strlen(p)); + int rc = w->close(pa); + if (rc < 0) { + KMessageBox::sorryWId(wId, i18n("Error re-encrypting the wallet. Password was not changed."), i18n("KDE Wallet Service")); + reclose = true; + } else { + rc = w->open(pa); + if (rc < 0) { + KMessageBox::sorryWId(wId, i18n("Error reopening the wallet. Data may be lost."), i18n("KDE Wallet Service")); + reclose = true; + } + } + } + } + + delete kpd; + + if (reclose) { + close(handle, true); + } +} + + +int KWalletD::close(const QString& wallet, bool force) { + int handle = -1; + KWallet::Backend *w = 0L; + + for (QIntDictIterator it(_wallets); + it.current(); + ++it) { + if (it.current()->walletName() == wallet) { + handle = it.currentKey(); + w = it.current(); + break; + } + } + + return closeWallet(w, handle, force); +} + + +int KWalletD::closeWallet(KWallet::Backend *w, int handle, bool force) { + if (w) { + const QString& wallet = w->walletName(); + assert(_passwords.contains(wallet)); + if (w->refCount() == 0 || force) { + invalidateHandle(handle); + if (_closeIdle && _timeouts) { + _timeouts->removeTimer(handle); + } + _wallets.remove(handle); + if (_passwords.contains(wallet)) { + w->close(QByteArray().duplicate(_passwords[wallet].data(), _passwords[wallet].length())); + _passwords[wallet].fill(0); + _passwords.remove(wallet); + } + doCloseSignals(handle, wallet); + delete w; + return 0; + } + return 1; + } + + return -1; +} + + +int KWalletD::close(int handle, bool force) { + QCString appid = friendlyDCOPPeerName(); + KWallet::Backend *w = _wallets.find(handle); + bool contains = false; + + if (w) { // the handle is valid + if (_handles.contains(appid)) { // we know this app + if (_handles[appid].contains(handle)) { + // the app owns this handle + _handles[appid].remove(_handles[appid].find(handle)); + contains = true; + if (_handles[appid].isEmpty()) { + _handles.remove(appid); + } + } + } + + // watch the side effect of the deref() + if ((contains && w->deref() == 0 && !_leaveOpen) || force) { + if (_closeIdle && _timeouts) { + _timeouts->removeTimer(handle); + } + _wallets.remove(handle); + if (force) { + invalidateHandle(handle); + } + if (_passwords.contains(w->walletName())) { + w->close(QByteArray().duplicate(_passwords[w->walletName()].data(), _passwords[w->walletName()].length())); + _passwords[w->walletName()].fill(0); + _passwords.remove(w->walletName()); + } + doCloseSignals(handle, w->walletName()); + delete w; + return 0; + } + return 1; // not closed + } + + return -1; // not open to begin with, or other error +} + + +bool KWalletD::isOpen(const QString& wallet) const { + for (QIntDictIterator it(_wallets); + it.current(); + ++it) { + if (it.current()->walletName() == wallet) { + return true; + } + } + return false; +} + + +bool KWalletD::isOpen(int handle) { + if (handle == 0) { + return false; + } + + KWallet::Backend *rc = _wallets.find(handle); + + if (rc == 0 && ++_failed > 5) { + _failed = 0; + QTimer::singleShot(0, this, SLOT(notifyFailures())); + } else if (rc != 0) { + _failed = 0; + } + + return rc != 0; +} + + +QStringList KWalletD::wallets() const { + QString path = KGlobal::dirs()->saveLocation("kwallet"); + QDir dir(path, "*.kwl"); + QStringList rc; + + dir.setFilter(QDir::Files | QDir::NoSymLinks); + + const QFileInfoList *list = dir.entryInfoList(); + QFileInfoListIterator it(*list); + QFileInfo *fi; + while ((fi = it.current()) != 0L) { + QString fn = fi->fileName(); + if (fn.endsWith(".kwl")) { + fn.truncate(fn.length()-4); + } + rc += fn; + ++it; + } + return rc; +} + + +void KWalletD::sync(int handle) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + QByteArray p; + QString wallet = b->walletName(); + p.duplicate(_passwords[wallet].data(), _passwords[wallet].length()); + b->sync(p); + p.fill(0); + } +} + + +QStringList KWalletD::folderList(int handle) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + return b->folderList(); + } + + return QStringList(); +} + + +bool KWalletD::hasFolder(int handle, const QString& f) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + return b->hasFolder(f); + } + + return false; +} + + +bool KWalletD::removeFolder(int handle, const QString& f) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + bool rc = b->removeFolder(f); + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << b->walletName(); + emitDCOPSignal("folderListUpdated(QString)", data); + return rc; + } + + return false; +} + + +bool KWalletD::createFolder(int handle, const QString& f) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + bool rc = b->createFolder(f); + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << b->walletName(); + emitDCOPSignal("folderListUpdated(QString)", data); + return rc; + } + + return false; +} + + +QByteArray KWalletD::readMap(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry *e = b->readEntry(key); + if (e && e->type() == KWallet::Wallet::Map) { + return e->map(); + } + } + + return QByteArray(); +} + + +QMap KWalletD::readMapList(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + QPtrList e = b->readEntryList(key); + QMap rc; + QPtrListIterator it(e); + KWallet::Entry *entry; + while ((entry = it.current())) { + if (entry->type() == KWallet::Wallet::Map) { + rc.insert(entry->key(), entry->map()); + } + ++it; + } + return rc; + } + + return QMap(); +} + + +QByteArray KWalletD::readEntry(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry *e = b->readEntry(key); + if (e) { + return e->value(); + } + } + + return QByteArray(); +} + + +QMap KWalletD::readEntryList(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + QPtrList e = b->readEntryList(key); + QMap rc; + QPtrListIterator it(e); + KWallet::Entry *entry; + while ((entry = it.current())) { + rc.insert(entry->key(), entry->value()); + ++it; + } + return rc; + } + + return QMap(); +} + + +QStringList KWalletD::entryList(int handle, const QString& folder) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + return b->entryList(); + } + + return QStringList(); +} + + +QString KWalletD::readPassword(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry *e = b->readEntry(key); + if (e && e->type() == KWallet::Wallet::Password) { + return e->password(); + } + } + + return QString::null; +} + + +QMap KWalletD::readPasswordList(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + QPtrList e = b->readEntryList(key); + QMap rc; + QPtrListIterator it(e); + KWallet::Entry *entry; + while ((entry = it.current())) { + if (entry->type() == KWallet::Wallet::Password) { + rc.insert(entry->key(), entry->password()); + } + ++it; + } + return rc; + } + + return QMap(); +} + + +int KWalletD::writeMap(int handle, const QString& folder, const QString& key, const QByteArray& value) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry e; + e.setKey(key); + e.setValue(value); + e.setType(KWallet::Wallet::Map); + b->writeEntry(&e); + emitFolderUpdated(b->walletName(), folder); + return 0; + } + + return -1; +} + + +int KWalletD::writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value, int entryType) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry e; + e.setKey(key); + e.setValue(value); + e.setType(KWallet::Wallet::EntryType(entryType)); + b->writeEntry(&e); + emitFolderUpdated(b->walletName(), folder); + return 0; + } + + return -1; +} + + +int KWalletD::writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry e; + e.setKey(key); + e.setValue(value); + e.setType(KWallet::Wallet::Stream); + b->writeEntry(&e); + emitFolderUpdated(b->walletName(), folder); + return 0; + } + + return -1; +} + + +int KWalletD::writePassword(int handle, const QString& folder, const QString& key, const QString& value) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + KWallet::Entry e; + e.setKey(key); + e.setValue(value); + e.setType(KWallet::Wallet::Password); + b->writeEntry(&e); + emitFolderUpdated(b->walletName(), folder); + return 0; + } + + return -1; +} + + +int KWalletD::entryType(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + if (!b->hasFolder(folder)) { + return KWallet::Wallet::Unknown; + } + b->setFolder(folder); + if (b->hasEntry(key)) { + return b->readEntry(key)->type(); + } + } + + return KWallet::Wallet::Unknown; +} + + +bool KWalletD::hasEntry(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + if (!b->hasFolder(folder)) { + return false; + } + b->setFolder(folder); + return b->hasEntry(key); + } + + return false; +} + + +int KWalletD::removeEntry(int handle, const QString& folder, const QString& key) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + if (!b->hasFolder(folder)) { + return 0; + } + b->setFolder(folder); + bool rc = b->removeEntry(key); + emitFolderUpdated(b->walletName(), folder); + return rc ? 0 : -3; + } + + return -1; +} + + +void KWalletD::slotAppUnregistered(const QCString& app) { + if (_handles.contains(app)) { + QValueList l = _handles[app]; + for (QValueList::Iterator i = l.begin(); i != l.end(); ++i) { + _handles[app].remove(*i); + KWallet::Backend *w = _wallets.find(*i); + if (w && !_leaveOpen && 0 == w->deref()) { + close(w->walletName(), true); + } + } + _handles.remove(app); + } +} + + +void KWalletD::invalidateHandle(int handle) { + for (QMap >::Iterator i = _handles.begin(); + i != _handles.end(); + ++i) { + i.data().remove(handle); + } +} + + +KWallet::Backend *KWalletD::getWallet(const QCString& appid, int handle) { + if (handle == 0) { + return 0L; + } + + KWallet::Backend *w = _wallets.find(handle); + + if (w) { // the handle is valid + if (_handles.contains(appid)) { // we know this app + if (_handles[appid].contains(handle)) { + // the app owns this handle + _failed = 0; + if (_closeIdle && _timeouts) { + _timeouts->resetTimer(handle, _idleTime); + } + return w; + } + } + } + + if (++_failed > 5) { + _failed = 0; + QTimer::singleShot(0, this, SLOT(notifyFailures())); + } + + return 0L; +} + + +void KWalletD::notifyFailures() { + if (!_showingFailureNotify) { + _showingFailureNotify = true; + KMessageBox::information(0, i18n("There have been repeated failed attempts to gain access to a wallet. An application may be misbehaving."), i18n("KDE Wallet Service")); + _showingFailureNotify = false; + } +} + + +void KWalletD::doCloseSignals(int handle, const QString& wallet) { + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << handle; + emitDCOPSignal("walletClosed(int)", data); + + QByteArray data2; + QDataStream ds2(data2, IO_WriteOnly); + ds2 << wallet; + emitDCOPSignal("walletClosed(QString)", data2); + + if (_wallets.isEmpty()) { + emitDCOPSignal("allWalletsClosed()", QByteArray()); + } +} + + +int KWalletD::renameEntry(int handle, const QString& folder, const QString& oldName, const QString& newName) { + KWallet::Backend *b; + + if ((b = getWallet(friendlyDCOPPeerName(), handle))) { + b->setFolder(folder); + int rc = b->renameEntry(oldName, newName); + emitFolderUpdated(b->walletName(), folder); + return rc; + } + + return -1; +} + + +QStringList KWalletD::users(const QString& wallet) const { + QStringList rc; + + for (QIntDictIterator it(_wallets); + it.current(); + ++it) { + if (it.current()->walletName() == wallet) { + for (QMap >::ConstIterator hit = _handles.begin(); hit != _handles.end(); ++hit) { + if (hit.data().contains(it.currentKey())) { + rc += hit.key(); + } + } + break; + } + } + + return rc; +} + + +bool KWalletD::disconnectApplication(const QString& wallet, const QCString& application) { + for (QIntDictIterator it(_wallets); + it.current(); + ++it) { + if (it.current()->walletName() == wallet) { + if (_handles[application].contains(it.currentKey())) { + _handles[application].remove(it.currentKey()); + + if (_handles[application].isEmpty()) { + _handles.remove(application); + } + + if (it.current()->deref() == 0) { + close(it.current()->walletName(), true); + } + + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << wallet; + ds << application; + emitDCOPSignal("applicationDisconnected(QString,QCString)", data); + + return true; + } + } + } + + return false; +} + + +void KWalletD::emitFolderUpdated(const QString& wallet, const QString& folder) { + QByteArray data; + QDataStream ds(data, IO_WriteOnly); + ds << wallet; + ds << folder; + emitDCOPSignal("folderUpdated(QString,QString)", data); +} + + +void KWalletD::emitWalletListDirty() { + emitDCOPSignal("walletListDirty()", QByteArray()); +} + + +void KWalletD::reconfigure() { + KConfig cfg("kwalletrc"); + cfg.setGroup("Wallet"); + _firstUse = cfg.readBoolEntry("First Use", true); + _enabled = cfg.readBoolEntry("Enabled", true); + _launchManager = cfg.readBoolEntry("Launch Manager", true); + _leaveOpen = cfg.readBoolEntry("Leave Open", false); + bool idleSave = _closeIdle; + _closeIdle = cfg.readBoolEntry("Close When Idle", false); + _openPrompt = cfg.readBoolEntry("Prompt on Open", true); + int timeSave = _idleTime; + // in minutes! + _idleTime = cfg.readNumEntry("Idle Timeout", 10) * 60 * 1000; + + if (cfg.readBoolEntry("Close on Screensaver", false)) { + connectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_start_screensaver()", "closeAllWallets()", false); + } else { + disconnectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_start_screensaver()", "closeAllWallets()"); + } + + // Handle idle changes + if (_closeIdle) { + if (_idleTime != timeSave) { // Timer length changed + QIntDictIterator it(_wallets); + for (; it.current(); ++it) { + _timeouts->resetTimer(it.currentKey(), _idleTime); + } + } + + if (!idleSave) { // add timers for all the wallets + QIntDictIterator it(_wallets); + for (; it.current(); ++it) { + _timeouts->addTimer(it.currentKey(), _idleTime); + } + } + } else { + _timeouts->clear(); + } + + // Update the implicit allow stuff + _implicitAllowMap.clear(); + cfg.setGroup("Auto Allow"); + QStringList entries = cfg.entryMap("Auto Allow").keys(); + for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) { + _implicitAllowMap[*i] = cfg.readListEntry(*i); + } + + // Update the implicit allow stuff + _implicitDenyMap.clear(); + cfg.setGroup("Auto Deny"); + entries = cfg.entryMap("Auto Deny").keys(); + for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) { + _implicitDenyMap[*i] = cfg.readListEntry(*i); + } + + // Update if wallet was enabled/disabled + if (!_enabled) { // close all wallets + while (!_wallets.isEmpty()) { + QIntDictIterator it(_wallets); + if (!it.current()) { // necessary? + break; + } + closeWallet(it.current(), it.currentKey(), true); + } + } +} + + +bool KWalletD::isEnabled() const { + return _enabled; +} + + +bool KWalletD::folderDoesNotExist(const QString& wallet, const QString& folder) { + if (!wallets().contains(wallet)) { + return true; + } + + for (QIntDictIterator it(_wallets); it.current(); ++it) { + if (it.current()->walletName() == wallet) { + return it.current()->folderDoesNotExist(folder); + } + } + + KWallet::Backend *b = new KWallet::Backend(wallet); + b->open(QByteArray()); + bool rc = b->folderDoesNotExist(folder); + delete b; + return rc; +} + + +bool KWalletD::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key) { + if (!wallets().contains(wallet)) { + return true; + } + + for (QIntDictIterator it(_wallets); it.current(); ++it) { + if (it.current()->walletName() == wallet) { + return it.current()->entryDoesNotExist(folder, key); + } + } + + KWallet::Backend *b = new KWallet::Backend(wallet); + b->open(QByteArray()); + bool rc = b->entryDoesNotExist(folder, key); + delete b; + return rc; +} + + +bool KWalletD::implicitAllow(const QString& wallet, const QCString& app) { + return _implicitAllowMap[wallet].contains(QString::fromLocal8Bit(app)); +} + + +bool KWalletD::implicitDeny(const QString& wallet, const QCString& app) { + return _implicitDenyMap[wallet].contains(QString::fromLocal8Bit(app)); +} + + +QCString KWalletD::friendlyDCOPPeerName() { + DCOPClient *dc = callingDcopClient(); + if (!dc) { + return ""; + } + return dc->senderId().replace(QRegExp("-[0-9]+$"), ""); +} + + +void KWalletD::timedOut(int id) { + KWallet::Backend *w = _wallets.find(id); + if (w) { + closeWallet(w, id, true); + } +} + + +void KWalletD::closeAllWallets() { + QIntDict tw = _wallets; + + for (QIntDictIterator it(tw); it.current(); ++it) { + closeWallet(it.current(), it.currentKey(), true); + } + + tw.clear(); + + // All of this should be basically noop. Let's just be safe. + _wallets.clear(); + + for (QMap::Iterator it = _passwords.begin(); + it != _passwords.end(); + ++it) { + it.data().fill(0); + } + _passwords.clear(); +} + + +QString KWalletD::networkWallet() { + return KWallet::Wallet::NetworkWallet(); +} + + +QString KWalletD::localWallet() { + return KWallet::Wallet::LocalWallet(); +} + + +#include "kwalletd.moc" diff --git a/kio/misc/kwalletd/kwalletd.desktop b/kio/misc/kwalletd/kwalletd.desktop new file mode 100644 index 000000000..b33851ceb --- /dev/null +++ b/kio/misc/kwalletd/kwalletd.desktop @@ -0,0 +1,151 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=kwalletd +X-KDE-FactoryName=kwalletd +X-KDE-Kded-autoload=false +X-KDE-Kded-load-on-demand=true +Name=KWallet Daemon Module +Name[af]=KBeursie Bediener Module +Name[ar]=مراقب وحدة KWallet +Name[az]=KWallet Demon Modulu +Name[be]=Модуль сервіса KWallet +Name[bg]=Демон Портфейл +Name[bn]=কে-ওয়ালেট ডিমন মডিউল +Name[br]=Mollad an diaoul KWallet +Name[ca]=Mòdul del dimoni KWallet +Name[cs]=Modul démona KWallet +Name[csb]=Pòrtfel +Name[cy]=Modiwl Daemon KWaled +Name[da]=KWallet Dæmonmodul +Name[de]=Digitale Brieftasche +Name[el]=Άρθρωμα δαίμονα KWallet +Name[eo]=Sekreteja demono-modulo +Name[es]=Módulo de demonio KWallet +Name[et]=KWalleti deemoni moodul +Name[eu]=KWallet daemon modulua +Name[fa]=پیمانه شبح KWallet +Name[fi]=KWallet-palvelinmoduuli +Name[fr]=Module démon KWallet +Name[ga]=Modúl Deamhain KWallet +Name[gl]=Módulo do Demo KWallet +Name[he]=מודול תהליך הרקע של KWallet +Name[hi]=केवैलट डेमन मॉड्यूल +Name[hr]=Modul KWallet demona +Name[hu]=KWallet szolgáltatás +Name[id]=Modul Daemon KWallet +Name[is]=KWallet þjónseining +Name[it]=Modulo demone KWallet +Name[ja]=KWallet デーモンモジュール +Name[ka]=KWallet გუშაგის მოდული +Name[kk]=KWallet әмиян қызметтің модулі +Name[km]=ម៉ូឌុល Daemon KWallet +Name[ko]=K지갑 데몬 모듈 +Name[lb]=KWallet-Dämonmodul +Name[lt]=KDE slaptažodinių tarnybos modulis +Name[lv]=KWallet Dēmona Modulis +Name[mn]=KWallet Daemon Модул +Name[ms]=Modul Daemon KWallet +Name[nb]=KWallet nisseprogramtillegg +Name[nds]=KWallet-Dämoon +Name[ne]=KWallet डेइमन मोड्युल +Name[nl]=KWallet daemon-module +Name[nn]=KWallet-nissemodul +Name[pa]=KWallet ਪੇਸ਼ਕਾਰੀ ਮੈਡੀਊਲ +Name[pl]=Portfel +Name[pt]=Módulo do Servidor do KWallet +Name[pt_BR]=Módulo do Serviço do KWallet +Name[ro]=Modul demon KWallet +Name[ru]=Служба бумажника +Name[rw]=Igice Dayimoni KUruhago +Name[se]=KWallet-bálvámoduvla +Name[sk]=Modul démona KWallet +Name[sl]=Modul demona KListnica +Name[sq]=Demoni për Modulin KWallet +Name[sr]=KWallet демон модул +Name[sr@Latn]=KWallet demon modul +Name[sv]=Kwallet-demonmodul +Name[ta]=KWallet டெமான் பகுதி +Name[te]=కెవాలెట్ సూత్రధారి మాడ్యూల్ +Name[tg]=Модули Демон KWallet +Name[th]=โมดูลเดมอน KWallet +Name[tr]=KWallet Program Modülü +Name[tt]=KWallet Xezmäteneñ Modulı +Name[uk]=Модуль демону KWallet +Name[uz]=KWallet xizmatining moduli +Name[uz@cyrillic]=KWallet хизматининг модули +Name[vi]=Mô-đun trình nền KWallet +Name[zh_CN]=KWallet 守护进程模块 +Name[zh_HK]=KWAllet 伺服程式模組 +Name[zh_TW]=KWAllet 服務程式模組 +Comment=KWallet daemon module for KDED +Comment[af]=KBeursie bediener module vir KDED +Comment[be]=Модуль сервіса KWallet для KDED +Comment[bg]=Модул демон за системата Портфейл за KDED +Comment[bn]=KDED-র জন্য কে-ওয়ালেট ডিমন মডিউল +Comment[br]=Mollad an diaoul KWallet evit KDED +Comment[bs]=KWallet daemon modul za KDED +Comment[ca]=Mòdul del dimoni KWallet per a KDED +Comment[cs]=Modul démona KWallet pro KDED +Comment[csb]=Mòduł KWallet w KDED +Comment[da]=KWallet Dæmonmodul for KDED +Comment[de]=Unterstützung für die digitale Brieftasche "KWallet" +Comment[el]=Άρθρωμα δαίμονα KWallet για το KDED +Comment[eo]=Sekreteja demono-modulo por KDED +Comment[es]=Módulo de demonio KWallet para KDED +Comment[et]=KDED KWalleti deemoni moodul +Comment[eu]=KWallet daemon modulua KDEDrako +Comment[fa]=پیمانۀ شبح KWallet برای KDED +Comment[fi]=KWallet palvelinmoduuli KDED:lle +Comment[fr]=Module démon KWallet pour KDED +Comment[fy]=KWallet daemon module foar KDED +Comment[ga]=Modúl deamhain KWallet le haghaidh KDED +Comment[gl]=Demo de KWallet para KDED +Comment[he]=מודול תהליך רקע של KWallet עבור KDED +Comment[hi]=केडीईडी के लिए के-वॉलेट डेमन मॉड्यूल +Comment[hr]=KWallet demon modul za KDED +Comment[hu]=KWallet szolgáltatásmodul a KDED-hez +Comment[id]=Modul daemon KWallet untuk KDED +Comment[is]=KWallet þjónseining fyrir KDED +Comment[it]=Modulo demone KWallet per KDED +Comment[ja]=KDED 用の KWallet デーモンモジュール +Comment[ka]=KSSL მოდული KDE-სთვის +Comment[kk]=KDE KWallet әмиянін басқару қызметтің модулі +Comment[km]=ម៉ូឌុល daemon KWallet សម្រាប់ KDED +Comment[lb]=KWallet-Dämonmodul fir KDED +Comment[lt]=KDE slaptažodinių tarnybos modulis skirtas KDED +Comment[lv]=KWallet Dēmona Modulis priekš KDED +Comment[mk]=KWallet даемон модул за KDED +Comment[ms]=Modul Daemon KWallet untuk KDED +Comment[nb]=KWallet nissemodul for KDED +Comment[nds]=KWallet-Dämoonmoduul för KDED +Comment[ne]=KDED का लागि डेइमन मोड्युल KWallet +Comment[nl]=KWallet daemon-module voor KDED +Comment[nn]=KWallet-nissemodul for KDED +Comment[pa]=KDED ਲਈ KWallet ਪੇਸ਼ਕਾਰੀ ਮੈਡੀਊਲ +Comment[pl]=Moduł KWallet w KDED +Comment[pt]=Módulo servidor do KWallet para o KDED +Comment[pt_BR]=Módulo do serviço de carteira para o KDE +Comment[ro]=Modul demon KWallet pentru KDED +Comment[ru]=Управление бумажником KDE +Comment[rw]=Igice cya dayimoni KUruhago cya KDED +Comment[se]=KDED:a KWallet-bálvámoduvla +Comment[sk]=Modul démona KWallet pre KDED +Comment[sl]=Modul demona KListnica za KDED +Comment[sr]=KWallet демон модул за KDED +Comment[sr@Latn]=KWallet demon modul za KDED +Comment[sv]=Kwallet-demonmodul för KDED +Comment[ta]=KDEDக்கான KWallet Daemon தொகுதி +Comment[te]=కెడిఈడి కొరకు కెవాలెట్ సూత్రధారి మాడ్యూల్ +Comment[tg]=Модули Демон KWallet барои KDED +Comment[th]=โมดูลเดมอน KWallet สำหรับ KDED +Comment[tr]=KDED için KWallet program modülü +Comment[tt]=KDED öçen KWallet xezmäteneñ modulı +Comment[uk]=Модуль демону торбинок KWallet для KDED +Comment[uz]=KDED uchun KWallet xizmatining moduli +Comment[uz@cyrillic]=KDED учун KWallet хизматининг модули +Comment[vi]=Mô-đun trình nền KWallet cho KDED. +Comment[zh_CN]=KDED 的 KWallet 守护进程模块 +Comment[zh_HK]=KDED 的 KWallet 伺服程式模組 +Comment[zh_TW]=KDED 的 KWallet 服務程式模組 diff --git a/kio/misc/kwalletd/kwalletd.h b/kio/misc/kwalletd/kwalletd.h new file mode 100644 index 000000000..afa999f24 --- /dev/null +++ b/kio/misc/kwalletd/kwalletd.h @@ -0,0 +1,195 @@ +/* + This file is part of the KDE libraries + + Copyright (c) 2002-2004 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _KWALLETD_H_ +#define _KWALLETD_H_ + +#include +#include +#include +#include +#include +#include "kwalletbackend.h" + +#include +#include + +class KDirWatch; +class KTimeout; + +// @Private +class KWalletTransaction; + +class KWalletD : public KDEDModule { + Q_OBJECT + K_DCOP + public: + KWalletD(const QCString &name); + virtual ~KWalletD(); + + k_dcop: + // Is the wallet enabled? If not, all open() calls fail. + virtual bool isEnabled() const; + + // Open and unlock the wallet + virtual int open(const QString& wallet, uint wId); + + // Open and unlock the wallet with this path + virtual int openPath(const QString& path, uint wId); + + // Asynchronous open - must give the object to return the handle + // to. + virtual void openAsynchronous(const QString& wallet, const QCString& returnObject, uint wId); + + // Close and lock the wallet + // If force = true, will close it for all users. Behave. This + // can break applications, and is generally intended for use by + // the wallet manager app only. + virtual int close(const QString& wallet, bool force); + virtual int close(int handle, bool force); + + // Save to disk but leave open + virtual ASYNC sync(int handle); + + // Physically deletes the wallet from disk. + virtual int deleteWallet(const QString& wallet); + + // Returns true if the wallet is open + virtual bool isOpen(const QString& wallet) const; + virtual bool isOpen(int handle); + + // List the users of this wallet + virtual QStringList users(const QString& wallet) const; + + // Change the password of this wallet + virtual void changePassword(const QString& wallet, uint wId); + + // A list of all wallets + virtual QStringList wallets() const; + + // A list of all folders in this wallet + virtual QStringList folderList(int handle); + + // Does this wallet have this folder? + virtual bool hasFolder(int handle, const QString& folder); + + // Create this folder + virtual bool createFolder(int handle, const QString& folder); + + // Remove this folder + virtual bool removeFolder(int handle, const QString& folder); + + // List of entries in this folder + virtual QStringList entryList(int handle, const QString& folder); + + // Read an entry. If the entry does not exist, it just + // returns an empty result. It is your responsibility to check + // hasEntry() first. + virtual QByteArray readEntry(int handle, const QString& folder, const QString& key); + virtual QByteArray readMap(int handle, const QString& folder, const QString& key); + virtual QString readPassword(int handle, const QString& folder, const QString& key); + virtual QMap readEntryList(int handle, const QString& folder, const QString& key); + virtual QMap readMapList(int handle, const QString& folder, const QString& key); + virtual QMap readPasswordList(int handle, const QString& folder, const QString& key); + + // Rename an entry. rc=0 on success. + virtual int renameEntry(int handle, const QString& folder, const QString& oldName, const QString& newName); + + // Write an entry. rc=0 on success. + virtual int writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value, int entryType); + virtual int writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value); + virtual int writeMap(int handle, const QString& folder, const QString& key, const QByteArray& value); + virtual int writePassword(int handle, const QString& folder, const QString& key, const QString& value); + + // Does the entry exist? + virtual bool hasEntry(int handle, const QString& folder, const QString& key); + + // What type is the entry? + virtual int entryType(int handle, const QString& folder, const QString& key); + + // Remove an entry. rc=0 on success. + virtual int removeEntry(int handle, const QString& folder, const QString& key); + + // Disconnect an app from a wallet + virtual bool disconnectApplication(const QString& wallet, const QCString& application); + + virtual void reconfigure(); + + // Determine + virtual bool folderDoesNotExist(const QString& wallet, const QString& folder); + virtual bool keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key); + + virtual void closeAllWallets(); + + virtual QString networkWallet(); + + virtual QString localWallet(); + + private slots: + void slotAppUnregistered(const QCString& app); + void emitWalletListDirty(); + void timedOut(int); + void notifyFailures(); + void processTransactions(); + + private: + int internalOpen(const QCString& appid, const QString& wallet, bool isPath = false, WId w = 0, bool modal = false); + bool isAuthorizedApp(const QCString& appid, const QString& wallet, WId w); + // This also validates the handle. May return NULL. + KWallet::Backend* getWallet(const QCString& appid, int handle); + // Generate a new unique handle. + int generateHandle(); + // Invalidate a handle (remove it from the QMap) + void invalidateHandle(int handle); + // Emit signals about closing wallets + void doCloseSignals(int,const QString&); + void emitFolderUpdated(const QString&, const QString&); + // Internal - close this wallet. + int closeWallet(KWallet::Backend *w, int handle, bool force); + // Implicitly allow access for this application + bool implicitAllow(const QString& wallet, const QCString& app); + bool implicitDeny(const QString& wallet, const QCString& app); + QCString friendlyDCOPPeerName(); + + void doTransactionChangePassword(const QCString& appid, const QString& wallet, uint wId); + int doTransactionOpen(const QCString& appid, const QString& wallet, uint wId, bool modal); + + void setupDialog( QWidget* dialog, WId wId, const QCString& appid, bool modal ); + void checkActiveDialog(); + + QIntDict _wallets; + QMap > _handles; + QMap _passwords; + KDirWatch *_dw; + int _failed; + + bool _leaveOpen, _closeIdle, _launchManager, _enabled; + bool _openPrompt, _firstUse, _showingFailureNotify; + int _idleTime; + QMap _implicitAllowMap, _implicitDenyMap; + KTimeout *_timeouts; + + QPtrList _transactions; + QGuardedPtr< QWidget > activeDialog; +}; + + +#endif diff --git a/kio/misc/kwalletd/kwalletwizard.ui b/kio/misc/kwalletd/kwalletwizard.ui new file mode 100644 index 000000000..609508e11 --- /dev/null +++ b/kio/misc/kwalletd/kwalletwizard.ui @@ -0,0 +1,545 @@ + +KWalletWizard + + + KWalletWizard + + + + 0 + 0 + 556 + 385 + + + + KDE Wallet Wizard + + + + page1 + + + Introduction + + + + unnamed + + + + spacer3 + + + Vertical + + + Expanding + + + + 21 + 21 + + + + + + textLabel1 + + + + 20 + + + + <u>KWallet</u> - The KDE Wallet System + + + RichText + + + WordBreak|AlignCenter + + + + + textLabel2 + + + + 5 + 5 + 0 + 2 + + + + 26 + + + Welcome to KWallet, the KDE Wallet System. KWallet allows you to store your passwords and other personal information on disk in an encrypted file, preventing others from viewing the information. This wizard will tell you about KWallet and help you configure it for the first time. + + + RichText + + + WordBreak|AlignVCenter + + + + + buttonGroup1 + + + NoFrame + + + + + + + unnamed + + + 0 + + + + _basic + + + &Basic setup (recommended) + + + true + + + + + _advanced + + + &Advanced setup + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 140 + 21 + + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 140 + 31 + + + + + + + + page4 + + + Information + + + + unnamed + + + + textLabel2_3 + + + The KDE Wallet system stores your data in a <i>wallet</i> file on your local hard disk. The data is only written in encrypted form, presently using the blowfish algorithm with your password as the key. When a wallet is opened, the wallet manager application will launch and display an icon in the system tray. You can use this application to manage your wallets. It even permits you to drag wallets and wallet contents, allowing you to easily copy a wallet to a remote system. + + + RichText + + + + + + + page2 + + + Password Selection + + + + unnamed + + + + textLabel3 + + + Various applications may attempt to use the KDE wallet to store passwords or other information such as web form data and cookies. If you would like these applications to use the wallet, you must enable it now and choose a password. The password you choose <i>cannot</i> be recovered if it is lost, and will allow anyone who knows it to obtain all the information contained in the wallet. + + + RichText + + + + + layout7 + + + + unnamed + + + + layout5 + + + + unnamed + + + + textLabel1_2 + + + false + + + Enter a new password: + + + AlignVCenter|AlignRight + + + _pass1 + + + + + textLabel2_2 + + + false + + + Verify password: + + + AlignVCenter|AlignRight + + + _pass2 + + + + + + + layout4 + + + + unnamed + + + + _pass1 + + + false + + + Password + + + + + _pass2 + + + false + + + Password + + + + + + + + + _useWallet + + + Yes, I wish to use the KDE wallet to store my personal information. + + + + + spacer5 + + + Vertical + + + Expanding + + + + 21 + 51 + + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 101 + 21 + + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 111 + 31 + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 21 + 70 + + + + + + _matchLabel + + + + + + WordBreak|AlignVCenter|AlignRight + + + + + + + page3 + + + Security Level + + + + unnamed + + + + textLabel1_3 + + + The KDE Wallet system allows you to control the level of security of your personal data. Some of these settings do impact usability. While the default settings are generally acceptable for most users, you may wish to change some of them. You may further tune these settings from the KWallet control module. + + + RichText + + + WordBreak|AlignVCenter + + + + + spacer8 + + + Vertical + + + Expanding + + + + 21 + 121 + + + + + + _networkWallet + + + Store network passwords and local passwords in separate wallet files + + + + + _closeIdle + + + Automatically close idle wallets + + + + + spacer9 + + + Vertical + + + Expanding + + + + 21 + 51 + + + + + + + + + _useWallet + toggled(bool) + textLabel1_2 + setEnabled(bool) + + + _useWallet + toggled(bool) + textLabel2_2 + setEnabled(bool) + + + _useWallet + toggled(bool) + _pass1 + setEnabled(bool) + + + _useWallet + toggled(bool) + _pass2 + setEnabled(bool) + + + _useWallet + clicked() + _pass1 + setFocus() + + + _useWallet + clicked() + KWalletWizard + passwordPageUpdate() + + + _pass1 + textChanged(const QString&) + KWalletWizard + passwordPageUpdate() + + + _pass2 + textChanged(const QString&) + KWalletWizard + passwordPageUpdate() + + + _advanced + clicked() + KWalletWizard + setAdvanced() + + + _basic + clicked() + KWalletWizard + setBasic() + + + + _basic + _advanced + _useWallet + _pass1 + _pass2 + + + qcheckbox.h + klocale.h + kwalletwizard.ui.h + + + passwordPageUpdate() + init() + setAdvanced() + setBasic() + destroy() + + + diff --git a/kio/misc/kwalletd/kwalletwizard.ui.h b/kio/misc/kwalletd/kwalletwizard.ui.h new file mode 100644 index 000000000..95346355a --- /dev/null +++ b/kio/misc/kwalletd/kwalletwizard.ui.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + +void KWalletWizard::passwordPageUpdate() +{ + bool fe = !_useWallet->isChecked() || _pass1->text() == _pass2->text(); + if (_basic->isChecked()) { + setFinishEnabled(page2, fe); + } else { + setNextEnabled(page2, fe); + setFinishEnabled(page3, fe); + } + + if (_useWallet->isChecked()) { + if (_pass1->text() == _pass2->text()) { + if (_pass1->text().isEmpty()) { + _matchLabel->setText(i18n("Password is empty. (WARNING: Insecure)")); + } else { + _matchLabel->setText(i18n("Passwords match.")); + } + } else { + _matchLabel->setText(i18n("Passwords do not match.")); + } + } else { + _matchLabel->setText(QString::null); + } + +} + + +void KWalletWizard::init() +{ + setHelpEnabled(page1, false); + setHelpEnabled(page2, false); + setHelpEnabled(page3, false); + setHelpEnabled(page4, false); + setAppropriate(page3, false); + setAppropriate(page4, false); + setFinishEnabled(page2, true); +} + + +void KWalletWizard::setAdvanced() +{ + setAppropriate(page3, true); + setAppropriate(page4, true); + bool fe = !_useWallet->isChecked() || _pass1->text() == _pass2->text(); + setFinishEnabled(page2, false); + setNextEnabled(page2, fe); + setFinishEnabled(page3, fe); +} + + +void KWalletWizard::setBasic() +{ + setAppropriate(page3, false); + setAppropriate(page4, false); + bool fe = !_useWallet->isChecked() || _pass1->text() == _pass2->text(); + setFinishEnabled(page3, false); + setFinishEnabled(page2, fe); +} + + +void KWalletWizard::destroy() +{ + _pass1->clear(); + _pass2->clear(); +} -- cgit v1.2.1