kio Library API Documentation

kwalletd.cpp

00001 /* 00002 This file is part of the KDE libraries 00003 00004 Copyright (c) 2002-2003 George Staikos <staikos@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 00021 */ 00022 00023 #include "kwalletwizard.h" 00024 #include "kwalletd.h" 00025 #include "ktimeout.h" 00026 00027 #include <dcopclient.h> 00028 #include <dcopref.h> 00029 #include <kapplication.h> 00030 #include <kconfig.h> 00031 #include <kdebug.h> 00032 #include <kdirwatch.h> 00033 #include <kglobal.h> 00034 #include <klocale.h> 00035 #include <kmessagebox.h> 00036 #include <kpassdlg.h> 00037 #include <kstddirs.h> 00038 #include <kwalletentry.h> 00039 #include <kwin.h> 00040 00041 #include <qdir.h> 00042 #include <qregexp.h> 00043 #include <qstylesheet.h> 00044 00045 #include <assert.h> 00046 00047 #include <X11/Xlib.h> 00048 00049 extern "C" { 00050 KDEDModule *create_kwalletd(const QCString &name) { 00051 return new KWalletD(name); 00052 } 00053 } 00054 00055 00056 class KWalletTransaction { 00057 public: 00058 KWalletTransaction() { 00059 tType = Unknown; 00060 transaction = 0L; 00061 client = 0L; 00062 } 00063 00064 ~KWalletTransaction() { 00065 // Don't delete these! 00066 transaction = 0L; 00067 client = 0L; 00068 } 00069 00070 enum Type { Unknown, Open, ChangePassword, OpenFail }; 00071 DCOPClient *client; 00072 DCOPClientTransaction *transaction; 00073 Type tType; 00074 QCString returnObject; 00075 QCString appid; 00076 uint wId; 00077 QString wallet; 00078 }; 00079 00080 00081 KWalletD::KWalletD(const QCString &name) 00082 : KDEDModule(name), _failed(0) { 00083 srand(time(0)); 00084 _transactions.setAutoDelete(true); 00085 _timeouts = new KTimeout(17); 00086 _closeIdle = false; 00087 _idleTime = 0; 00088 connect(_timeouts, SIGNAL(timedOut(int)), this, SLOT(timedOut(int))); 00089 reconfigure(); 00090 KGlobal::dirs()->addResourceType("kwallet", "share/apps/kwallet"); 00091 connect(KApplication::dcopClient(), 00092 SIGNAL(applicationRemoved(const QCString&)), 00093 this, 00094 SLOT(slotAppUnregistered(const QCString&))); 00095 _dw = new KDirWatch(this, "KWallet Directory Watcher"); 00096 _dw->addDir(KGlobal::dirs()->saveLocation("kwallet")); 00097 _dw->startScan(true); 00098 connect(_dw, SIGNAL(dirty(const QString&)), this, SLOT(emitWalletListDirty())); 00099 } 00100 00101 00102 KWalletD::~KWalletD() { 00103 delete _timeouts; 00104 _timeouts = 0; 00105 00106 closeAllWallets(); 00107 _transactions.clear(); 00108 } 00109 00110 00111 int KWalletD::generateHandle() { 00112 int rc; 00113 00114 // ASSUMPTION: RAND_MAX is fairly large. 00115 do { 00116 rc = rand(); 00117 } while (_wallets.find(rc)); 00118 00119 return rc; 00120 } 00121 00122 00123 void KWalletD::processTransactions() { 00124 // Process remaining transactions 00125 for (KWalletTransaction *xact = _transactions.first(); xact; ) { 00126 QCString replyType; 00127 int res; 00128 00129 assert(xact->tType != KWalletTransaction::Unknown); 00130 00131 switch (xact->tType) { 00132 case KWalletTransaction::Open: 00133 res = doTransactionOpen(xact->appid, xact->wallet, xact->wId); 00134 replyType = "int"; 00135 break; 00136 case KWalletTransaction::OpenFail: 00137 res = -1; 00138 replyType = "int"; 00139 break; 00140 case KWalletTransaction::ChangePassword: 00141 doTransactionChangePassword(xact->appid, xact->wallet, xact->wId); 00142 // fall through - no return 00143 default: 00144 KWalletTransaction *tmp = xact; 00145 xact = _transactions.next(); 00146 _transactions.removeRef(tmp); 00147 continue; 00148 } 00149 00150 QByteArray replyData; 00151 QDataStream stream(replyData, IO_WriteOnly); 00152 stream << res; 00153 xact->client->endTransaction(xact->transaction, replyType, replyData); 00154 KWalletTransaction *tmp = xact; 00155 xact = _transactions.next(); 00156 _transactions.removeRef(tmp); 00157 } 00158 } 00159 00160 void KWalletD::openAsynchronous(const QString& wallet, const QCString& returnObject, uint wId) { 00161 DCOPClient *dc = callingDcopClient(); 00162 if (!dc) return; 00163 QCString appid = dc->senderId(); 00164 00165 int rc = open(wallet, wId); 00166 DCOPRef(appid, returnObject).send("walletOpenResult", rc); 00167 } 00168 00169 00170 int KWalletD::openPath(const QString& path, uint wId) { 00171 if (!_enabled) { // guard 00172 return -1; 00173 } 00174 00175 // FIXME: setup transaction 00176 return internalOpen(friendlyDCOPPeerName(), path, true, wId); 00177 } 00178 00179 00180 int KWalletD::open(const QString& wallet, uint wId) { 00181 if (!_enabled) { // guard 00182 return -1; 00183 } 00184 00185 if (!QRegExp("^[A-Za-z0-9]+[A-Za-z0-9\\s\\-_]*$").exactMatch(wallet)) { 00186 return -1; 00187 } 00188 00189 QCString appid = friendlyDCOPPeerName(); 00190 00191 KWalletTransaction *xact = new KWalletTransaction; 00192 _transactions.append(xact); 00193 00194 if (_transactions.count() > 1) { 00195 xact->appid = appid; 00196 xact->client = callingDcopClient(); 00197 xact->transaction = xact->client->beginTransaction(); 00198 xact->wallet = wallet; 00199 xact->wId = wId; 00200 xact->tType = KWalletTransaction::Open; 00201 return 0; // process later 00202 } 00203 00204 int rc = doTransactionOpen(appid, wallet, wId); 00205 00206 _transactions.remove(xact); 00207 00208 if (rc < 0) { 00209 // multiple requests from the same client should not produce multiple password dialogs on a failure 00210 for (KWalletTransaction *x = _transactions.first(); x; x = _transactions.next()) { 00211 if (appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == wallet && x->wId == wId) 00212 x->tType = KWalletTransaction::OpenFail; 00213 } 00214 } 00215 00216 processTransactions(); 00217 00218 return rc; 00219 } 00220 00221 00222 int KWalletD::doTransactionOpen(const QCString& appid, const QString& wallet, uint wId) { 00223 if (_firstUse && !wallets().contains(KWallet::Wallet::LocalWallet())) { 00224 // First use wizard 00225 KWalletWizard *wiz = new KWalletWizard(0); 00226 XSetTransientForHint(qt_xdisplay(), wiz->winId(), wId); 00227 int rc = wiz->exec(); 00228 if (rc == QDialog::Accepted) { 00229 KConfig cfg("kwalletrc"); 00230 cfg.setGroup("Wallet"); 00231 cfg.writeEntry("First Use", false); 00232 cfg.writeEntry("Enabled", wiz->_useWallet->isChecked()); 00233 cfg.writeEntry("Close When Idle", wiz->_closeIdle->isChecked()); 00234 cfg.writeEntry("Use One Wallet", !wiz->_networkWallet->isChecked()); 00235 cfg.sync(); 00236 reconfigure(); 00237 00238 if (!wiz->_useWallet->isChecked()) { 00239 delete wiz; 00240 return -1; 00241 } 00242 00243 // Create the wallet 00244 KWallet::Backend *b = new KWallet::Backend(KWallet::Wallet::LocalWallet()); 00245 QByteArray p; 00246 p.duplicate(wiz->_pass1->text().utf8(), wiz->_pass1->text().length()); 00247 b->open(p); 00248 b->createFolder(KWallet::Wallet::PasswordFolder()); 00249 b->createFolder(KWallet::Wallet::FormDataFolder()); 00250 b->close(p); 00251 p.fill(0); 00252 delete b; 00253 delete wiz; 00254 } else { 00255 delete wiz; 00256 return -1; 00257 } 00258 } else if (_firstUse) { 00259 KConfig cfg("kwalletrc"); 00260 _firstUse = false; 00261 cfg.setGroup("Wallet"); 00262 cfg.writeEntry("First Use", false); 00263 cfg.sync(); 00264 } 00265 00266 return internalOpen(appid, wallet, false, wId); 00267 } 00268 00269 00270 int KWalletD::internalOpen(const QCString& appid, const QString& wallet, bool isPath, WId w) { 00271 int rc = -1; 00272 bool brandNew = false; 00273 00274 for (QIntDictIterator<KWallet::Backend> i(_wallets); i.current(); ++i) { 00275 if (i.current()->walletName() == wallet) { 00276 rc = i.currentKey(); 00277 break; 00278 } 00279 } 00280 00281 if (rc == -1) { 00282 if (_wallets.count() > 20) { 00283 kdDebug() << "Too many wallets open." << endl; 00284 return -1; 00285 } 00286 00287 KWallet::Backend *b = new KWallet::Backend(wallet, isPath); 00288 KPasswordDialog *kpd; 00289 if ((isPath || QFile::exists(wallet)) || KWallet::Backend::exists(wallet)) { 00290 kpd = new KPasswordDialog(KPasswordDialog::Password, false, 0); 00291 if (appid.isEmpty()) { 00292 kpd->setPrompt(i18n("<qt>KDE has requested to open the wallet '<b>%1</b>'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(wallet))); 00293 } else { 00294 kpd->setPrompt(i18n("<qt>The application '<b>%1</b>' has requested to open the wallet '<b>%2</b>'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet))); 00295 } 00296 brandNew = false; 00297 kpd->setButtonOKText(i18n("&Open")); 00298 } else if (wallet == KWallet::Wallet::LocalWallet() || 00299 wallet == KWallet::Wallet::NetworkWallet()) { 00300 // Auto create these wallets. 00301 kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); 00302 if (appid.isEmpty()) { 00303 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.")); 00304 } else { 00305 kpd->setPrompt(i18n("<qt>The application '<b>%1</b>' 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))); 00306 } 00307 brandNew = true; 00308 kpd->setButtonOKText(i18n("&Open")); 00309 } else { 00310 kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); 00311 if (appid.length() == 0) { 00312 kpd->setPrompt(i18n("<qt>KDE has requested to create a new wallet named '<b>%1</b>'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(wallet))); 00313 } else { 00314 kpd->setPrompt(i18n("<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet))); 00315 } 00316 brandNew = true; 00317 kpd->setButtonOKText(i18n("&Create")); 00318 } 00319 00320 kpd->setCaption(i18n("KDE Wallet Service")); 00321 const char *p = 0L; 00322 while (!b->isOpen()) { 00323 XSetTransientForHint(qt_xdisplay(), kpd->winId(), w); 00324 KWin::setState( kpd->winId(), NET::KeepAbove ); 00325 if (kpd->exec() == KDialog::Accepted) { 00326 p = kpd->password(); 00327 int rc = b->open(QByteArray().duplicate(p, strlen(p))); 00328 if (!b->isOpen()) { 00329 kpd->setPrompt(i18n("<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br>(Error code %2: %3)").arg(QStyleSheet::escape(wallet)).arg(rc).arg(KWallet::Backend::openRCToString(rc))); 00330 kpd->clearPassword(); 00331 } 00332 } else { 00333 break; 00334 } 00335 } 00336 00337 if (!p || !b->isOpen()) { 00338 delete b; 00339 delete kpd; 00340 return -1; 00341 } 00342 00343 _wallets.insert(rc = generateHandle(), b); 00344 _passwords[wallet] = p; 00345 _handles[appid].append(rc); 00346 00347 if (brandNew) { 00348 createFolder(rc, KWallet::Wallet::PasswordFolder()); 00349 createFolder(rc, KWallet::Wallet::FormDataFolder()); 00350 } 00351 00352 b->ref(); 00353 if (_closeIdle && _timeouts) { 00354 _timeouts->addTimer(rc, _idleTime); 00355 } 00356 delete kpd; 00357 QByteArray data; 00358 QDataStream ds(data, IO_WriteOnly); 00359 ds << wallet; 00360 if (brandNew) { 00361 emitDCOPSignal("walletCreated(QString)", data); 00362 } 00363 emitDCOPSignal("walletOpened(QString)", data); 00364 if (_wallets.count() == 1 && _launchManager) { 00365 KApplication::startServiceByDesktopName("kwalletmanager"); 00366 } 00367 } else { 00368 int response = KMessageBox::Yes; 00369 00370 if (_openPrompt && !_handles[appid].contains(rc) && !implicitAllow(wallet, appid)) { 00371 if (appid.isEmpty()) { 00372 response = KMessageBox::questionYesNoCancel(0L, i18n("<qt>KDE has requested access to the open wallet '<b>%1</b>'.").arg(QStyleSheet::escape(wallet)), 00373 i18n("KDE Wallet Service"), i18n("Allow &Once"), i18n("Allow &Always")); 00374 } else { 00375 response = KMessageBox::questionYesNoCancel(0L, i18n("<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.").arg(QStyleSheet::escape(QString(appid))).arg(QStyleSheet::escape(wallet)), i18n("KDE Wallet Service"), i18n("Allow &Once"), i18n("Allow &Always")); 00376 } 00377 } 00378 00379 if (response == KMessageBox::Yes || response == KMessageBox::No) { 00380 _handles[appid].append(rc); 00381 _wallets.find(rc)->ref(); 00382 if (response == KMessageBox::No) { 00383 KConfig cfg("kwalletrc"); 00384 cfg.setGroup("Auto Allow"); 00385 QStringList apps = cfg.readListEntry(wallet); 00386 if (!apps.contains(appid)) { 00387 apps += appid; 00388 _implicitAllowMap[wallet] += appid; 00389 cfg.writeEntry(wallet, apps); 00390 cfg.sync(); 00391 } 00392 } 00393 } else { 00394 return -1; 00395 } 00396 } 00397 00398 return rc; 00399 } 00400 00401 00402 int KWalletD::deleteWallet(const QString& wallet) { 00403 QString path = KGlobal::dirs()->saveLocation("kwallet") + QDir::separator() + wallet + ".kwl"; 00404 00405 if (QFile::exists(path)) { 00406 close(wallet, true); 00407 QFile::remove(path); 00408 QByteArray data; 00409 QDataStream ds(data, IO_WriteOnly); 00410 ds << wallet; 00411 emitDCOPSignal("walletDeleted(QString)", data); 00412 return 0; 00413 } 00414 00415 return -1; 00416 } 00417 00418 00419 void KWalletD::changePassword(const QString& wallet, uint wId) { 00420 QCString appid = friendlyDCOPPeerName(); 00421 00422 KWalletTransaction *xact = new KWalletTransaction; 00423 _transactions.append(xact); 00424 00425 if (_transactions.count() > 1) { 00426 xact->appid = appid; 00427 xact->client = callingDcopClient(); 00428 xact->transaction = xact->client->beginTransaction(); 00429 xact->wallet = wallet; 00430 xact->wId = wId; 00431 xact->tType = KWalletTransaction::ChangePassword; 00432 return; // process later 00433 } 00434 00435 doTransactionChangePassword(appid, wallet, wId); 00436 00437 _transactions.remove(xact); 00438 00439 processTransactions(); 00440 } 00441 00442 00443 void KWalletD::doTransactionChangePassword(const QCString& appid, const QString& wallet, uint wId) { 00444 QIntDictIterator<KWallet::Backend> it(_wallets); 00445 KWallet::Backend *w = 0L; 00446 int handle = -1; 00447 bool reclose = false; 00448 00449 for (; it.current(); ++it) { 00450 if (it.current()->walletName() == wallet) { 00451 break; 00452 } 00453 } 00454 00455 if (!it.current()) { 00456 handle = doTransactionOpen(appid, wallet, wId); 00457 if (-1 == handle) { 00458 KMessageBox::sorryWId(wId, i18n("Unable to open wallet. The wallet must be opened in order to change the password."), i18n("KDE Wallet Service")); 00459 return; 00460 } 00461 00462 w = _wallets.find(handle); 00463 reclose = true; 00464 } else { 00465 handle = it.currentKey(); 00466 w = it.current(); 00467 } 00468 00469 assert(w); 00470 00471 KPasswordDialog *kpd; 00472 kpd = new KPasswordDialog(KPasswordDialog::NewPassword, false, 0); 00473 kpd->setPrompt(i18n("<qt>Please choose a new password for the wallet '<b>%1</b>'.").arg(QStyleSheet::escape(wallet))); 00474 kpd->setCaption(i18n("KDE Wallet Service")); 00475 XSetTransientForHint(qt_xdisplay(), kpd->winId(), wId); 00476 if (kpd->exec() == KDialog::Accepted) { 00477 const char *p = kpd->password(); 00478 if (p) { 00479 _passwords[wallet] = p; 00480 QByteArray pa; 00481 pa.duplicate(p, strlen(p)); 00482 int rc = w->close(pa); 00483 if (rc < 0) { 00484 KMessageBox::sorryWId(wId, i18n("Error re-encrypting the wallet. Password was not changed."), i18n("KDE Wallet Service")); 00485 reclose = true; 00486 } else { 00487 rc = w->open(pa); 00488 if (rc < 0) { 00489 KMessageBox::sorryWId(wId, i18n("Error reopening the wallet. Data may be lost."), i18n("KDE Wallet Service")); 00490 reclose = true; 00491 } 00492 } 00493 } 00494 } 00495 00496 delete kpd; 00497 00498 if (reclose) { 00499 close(handle, true); 00500 } 00501 } 00502 00503 00504 int KWalletD::close(const QString& wallet, bool force) { 00505 int handle = -1; 00506 KWallet::Backend *w = 0L; 00507 00508 for (QIntDictIterator<KWallet::Backend> it(_wallets); 00509 it.current(); 00510 ++it) { 00511 if (it.current()->walletName() == wallet) { 00512 handle = it.currentKey(); 00513 w = it.current(); 00514 break; 00515 } 00516 } 00517 00518 return closeWallet(w, handle, force); 00519 } 00520 00521 00522 int KWalletD::closeWallet(KWallet::Backend *w, int handle, bool force) { 00523 if (w) { 00524 const QString& wallet = w->walletName(); 00525 if (w->refCount() == 0 || force) { 00526 invalidateHandle(handle); 00527 if (_closeIdle && _timeouts) { 00528 _timeouts->removeTimer(handle); 00529 } 00530 _wallets.remove(handle); 00531 if (_passwords.contains(wallet)) { 00532 w->close(QByteArray().duplicate(_passwords[wallet].data(), _passwords[wallet].length())); 00533 _passwords[wallet].fill(0); 00534 _passwords.remove(wallet); 00535 } 00536 doCloseSignals(handle, wallet); 00537 delete w; 00538 return 0; 00539 } 00540 return 1; 00541 } 00542 00543 return -1; 00544 } 00545 00546 00547 int KWalletD::close(int handle, bool force) { 00548 QCString appid = friendlyDCOPPeerName(); 00549 KWallet::Backend *w = _wallets.find(handle); 00550 bool contains = false; 00551 00552 if (w) { // the handle is valid 00553 if (_handles.contains(appid)) { // we know this app 00554 if (_handles[appid].contains(handle)) { 00555 // the app owns this handle 00556 _handles[appid].remove(_handles[appid].find(handle)); 00557 contains = true; 00558 if (_handles[appid].isEmpty()) { 00559 _handles.remove(appid); 00560 } 00561 } 00562 } 00563 00564 // watch the side effect of the deref() 00565 if ((contains && w->deref() == 0 && !_leaveOpen) || force) { 00566 if (_closeIdle && _timeouts) { 00567 _timeouts->removeTimer(handle); 00568 } 00569 _wallets.remove(handle); 00570 if (force) { 00571 invalidateHandle(handle); 00572 } 00573 if (_passwords.contains(w->walletName())) { 00574 w->close(QByteArray().duplicate(_passwords[w->walletName()].data(), _passwords[w->walletName()].length())); 00575 _passwords[w->walletName()].fill(0); 00576 _passwords.remove(w->walletName()); 00577 } 00578 doCloseSignals(handle, w->walletName()); 00579 delete w; 00580 return 0; 00581 } 00582 return 1; // not closed 00583 } 00584 00585 return -1; // not open to begin with, or other error 00586 } 00587 00588 00589 bool KWalletD::isOpen(const QString& wallet) const { 00590 for (QIntDictIterator<KWallet::Backend> it(_wallets); 00591 it.current(); 00592 ++it) { 00593 if (it.current()->walletName() == wallet) { 00594 return true; 00595 } 00596 } 00597 return false; 00598 } 00599 00600 00601 bool KWalletD::isOpen(int handle) { 00602 KWallet::Backend *rc = _wallets.find(handle); 00603 00604 if (rc == 0 && ++_failed > 5) { 00605 // FIXME: Make this part of a transaction or offload it from 00606 // the main execution path somehow. 00607 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")); 00608 _failed = 0; 00609 } else if (rc != 0) { 00610 _failed = 0; 00611 } 00612 00613 return rc != 0; 00614 } 00615 00616 00617 QStringList KWalletD::wallets() const { 00618 QString path = KGlobal::dirs()->saveLocation("kwallet"); 00619 QDir dir(path, "*.kwl"); 00620 QStringList rc; 00621 00622 dir.setFilter(QDir::Files | QDir::NoSymLinks); 00623 00624 const QFileInfoList *list = dir.entryInfoList(); 00625 QFileInfoListIterator it(*list); 00626 QFileInfo *fi; 00627 while ((fi = it.current()) != 0L) { 00628 QString fn = fi->fileName(); 00629 if (fn.endsWith(".kwl")) { 00630 fn.truncate(fn.length()-4); 00631 } 00632 rc += fn; 00633 ++it; 00634 } 00635 return rc; 00636 } 00637 00638 00639 void KWalletD::sync(int handle) { 00640 KWallet::Backend *b; 00641 00642 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00643 QByteArray p; 00644 QString wallet = b->walletName(); 00645 p.duplicate(_passwords[wallet].data(), _passwords[wallet].length()); 00646 b->sync(p); 00647 p.fill(0); 00648 } 00649 } 00650 00651 00652 QStringList KWalletD::folderList(int handle) { 00653 KWallet::Backend *b; 00654 00655 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00656 return b->folderList(); 00657 } 00658 00659 return QStringList(); 00660 } 00661 00662 00663 bool KWalletD::hasFolder(int handle, const QString& f) { 00664 KWallet::Backend *b; 00665 00666 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00667 return b->hasFolder(f); 00668 } 00669 00670 return false; 00671 } 00672 00673 00674 bool KWalletD::removeFolder(int handle, const QString& f) { 00675 KWallet::Backend *b; 00676 00677 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00678 bool rc = b->removeFolder(f); 00679 QByteArray data; 00680 QDataStream ds(data, IO_WriteOnly); 00681 ds << b->walletName(); 00682 emitDCOPSignal("folderListUpdated(QString)", data); 00683 return rc; 00684 } 00685 00686 return false; 00687 } 00688 00689 00690 bool KWalletD::createFolder(int handle, const QString& f) { 00691 KWallet::Backend *b; 00692 00693 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00694 bool rc = b->createFolder(f); 00695 QByteArray data; 00696 QDataStream ds(data, IO_WriteOnly); 00697 ds << b->walletName(); 00698 emitDCOPSignal("folderListUpdated(QString)", data); 00699 return rc; 00700 } 00701 00702 return false; 00703 } 00704 00705 00706 QByteArray KWalletD::readMap(int handle, const QString& folder, const QString& key) { 00707 KWallet::Backend *b; 00708 00709 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00710 b->setFolder(folder); 00711 KWallet::Entry *e = b->readEntry(key); 00712 if (e && e->type() == KWallet::Wallet::Map) { 00713 return e->map(); 00714 } 00715 } 00716 00717 return QByteArray(); 00718 } 00719 00720 00721 QByteArray KWalletD::readEntry(int handle, const QString& folder, const QString& key) { 00722 KWallet::Backend *b; 00723 00724 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00725 b->setFolder(folder); 00726 KWallet::Entry *e = b->readEntry(key); 00727 if (e) { 00728 return e->value(); 00729 } 00730 } 00731 00732 return QByteArray(); 00733 } 00734 00735 00736 QStringList KWalletD::entryList(int handle, const QString& folder) { 00737 KWallet::Backend *b; 00738 00739 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00740 b->setFolder(folder); 00741 return b->entryList(); 00742 } 00743 00744 return QStringList(); 00745 } 00746 00747 00748 QString KWalletD::readPassword(int handle, const QString& folder, const QString& key) { 00749 KWallet::Backend *b; 00750 00751 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00752 b->setFolder(folder); 00753 KWallet::Entry *e = b->readEntry(key); 00754 if (e && e->type() == KWallet::Wallet::Password) { 00755 return e->password(); 00756 } 00757 } 00758 00759 return QString::null; 00760 } 00761 00762 00763 int KWalletD::writeMap(int handle, const QString& folder, const QString& key, const QByteArray& value) { 00764 KWallet::Backend *b; 00765 00766 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00767 b->setFolder(folder); 00768 KWallet::Entry e; 00769 e.setKey(key); 00770 e.setValue(value); 00771 e.setType(KWallet::Wallet::Map); 00772 b->writeEntry(&e); 00773 emitFolderUpdated(b->walletName(), folder); 00774 return 0; 00775 } 00776 00777 return -1; 00778 } 00779 00780 00781 int KWalletD::writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value, int entryType) { 00782 KWallet::Backend *b; 00783 00784 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00785 b->setFolder(folder); 00786 KWallet::Entry e; 00787 e.setKey(key); 00788 e.setValue(value); 00789 e.setType(KWallet::Wallet::EntryType(entryType)); 00790 b->writeEntry(&e); 00791 emitFolderUpdated(b->walletName(), folder); 00792 return 0; 00793 } 00794 00795 return -1; 00796 } 00797 00798 00799 int KWalletD::writeEntry(int handle, const QString& folder, const QString& key, const QByteArray& value) { 00800 KWallet::Backend *b; 00801 00802 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00803 b->setFolder(folder); 00804 KWallet::Entry e; 00805 e.setKey(key); 00806 e.setValue(value); 00807 e.setType(KWallet::Wallet::Stream); 00808 b->writeEntry(&e); 00809 emitFolderUpdated(b->walletName(), folder); 00810 return 0; 00811 } 00812 00813 return -1; 00814 } 00815 00816 00817 int KWalletD::writePassword(int handle, const QString& folder, const QString& key, const QString& value) { 00818 KWallet::Backend *b; 00819 00820 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00821 b->setFolder(folder); 00822 KWallet::Entry e; 00823 e.setKey(key); 00824 e.setValue(value); 00825 e.setType(KWallet::Wallet::Password); 00826 b->writeEntry(&e); 00827 emitFolderUpdated(b->walletName(), folder); 00828 return 0; 00829 } 00830 00831 return -1; 00832 } 00833 00834 00835 int KWalletD::entryType(int handle, const QString& folder, const QString& key) { 00836 KWallet::Backend *b; 00837 00838 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00839 if (!b->hasFolder(folder)) { 00840 return KWallet::Wallet::Unknown; 00841 } 00842 b->setFolder(folder); 00843 if (b->hasEntry(key)) { 00844 return b->readEntry(key)->type(); 00845 } 00846 } 00847 00848 return KWallet::Wallet::Unknown; 00849 } 00850 00851 00852 bool KWalletD::hasEntry(int handle, const QString& folder, const QString& key) { 00853 KWallet::Backend *b; 00854 00855 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00856 if (!b->hasFolder(folder)) { 00857 return false; 00858 } 00859 b->setFolder(folder); 00860 return b->hasEntry(key); 00861 } 00862 00863 return false; 00864 } 00865 00866 00867 int KWalletD::removeEntry(int handle, const QString& folder, const QString& key) { 00868 KWallet::Backend *b; 00869 00870 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00871 if (!b->hasFolder(folder)) { 00872 return 0; 00873 } 00874 b->setFolder(folder); 00875 bool rc = b->removeEntry(key); 00876 emitFolderUpdated(b->walletName(), folder); 00877 return rc ? 0 : -3; 00878 } 00879 00880 return -1; 00881 } 00882 00883 00884 void KWalletD::slotAppUnregistered(const QCString& app) { 00885 if (_handles.contains(app)) { 00886 QValueList<int> l = _handles[app]; 00887 for (QValueList<int>::Iterator i = l.begin(); i != l.end(); i++) { 00888 _handles[app].remove(*i); 00889 KWallet::Backend *w = _wallets.find(*i); 00890 if (w && !_leaveOpen && 0 == w->deref()) { 00891 close(w->walletName(), true); 00892 } 00893 } 00894 _handles.remove(app); 00895 } 00896 } 00897 00898 00899 void KWalletD::invalidateHandle(int handle) { 00900 for (QMap<QCString,QValueList<int> >::Iterator i = _handles.begin(); 00901 i != _handles.end(); 00902 ++i) { 00903 i.data().remove(handle); 00904 } 00905 } 00906 00907 00908 KWallet::Backend *KWalletD::getWallet(const QCString& appid, int handle) { 00909 KWallet::Backend *w = _wallets.find(handle); 00910 00911 if (w) { // the handle is valid 00912 if (_handles.contains(appid)) { // we know this app 00913 if (_handles[appid].contains(handle)) { 00914 // the app owns this handle 00915 _failed = 0; 00916 if (_closeIdle && _timeouts) { 00917 _timeouts->resetTimer(handle, _idleTime); 00918 } 00919 return w; 00920 } 00921 } 00922 } 00923 00924 if (++_failed > 5) { 00925 // FIXME: Make this part of a transaction or offload it from 00926 // the main execution path somehow. 00927 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")); 00928 _failed = 0; 00929 } 00930 00931 return 0L; 00932 } 00933 00934 00935 void KWalletD::doCloseSignals(int handle, const QString& wallet) { 00936 QByteArray data; 00937 QDataStream ds(data, IO_WriteOnly); 00938 ds << handle; 00939 emitDCOPSignal("walletClosed(int)", data); 00940 00941 QByteArray data2; 00942 QDataStream ds2(data2, IO_WriteOnly); 00943 ds2 << wallet; 00944 emitDCOPSignal("walletClosed(QString)", data2); 00945 00946 if (_wallets.isEmpty()) { 00947 emitDCOPSignal("allWalletsClosed()", QByteArray()); 00948 } 00949 } 00950 00951 00952 int KWalletD::renameEntry(int handle, const QString& folder, const QString& oldName, const QString& newName) { 00953 KWallet::Backend *b; 00954 00955 if ((b = getWallet(friendlyDCOPPeerName(), handle))) { 00956 b->setFolder(folder); 00957 int rc = b->renameEntry(oldName, newName); 00958 emitFolderUpdated(b->walletName(), folder); 00959 return rc; 00960 } 00961 00962 return -1; 00963 } 00964 00965 00966 QStringList KWalletD::users(const QString& wallet) const { 00967 QStringList rc; 00968 00969 for (QIntDictIterator<KWallet::Backend> it(_wallets); 00970 it.current(); 00971 ++it) { 00972 if (it.current()->walletName() == wallet) { 00973 for (QMap<QCString,QValueList<int> >::ConstIterator hit = _handles.begin(); hit != _handles.end(); ++hit) { 00974 if (hit.data().contains(it.currentKey())) { 00975 rc += hit.key(); 00976 } 00977 } 00978 break; 00979 } 00980 } 00981 00982 return rc; 00983 } 00984 00985 00986 bool KWalletD::disconnectApplication(const QString& wallet, const QCString& application) { 00987 for (QIntDictIterator<KWallet::Backend> it(_wallets); 00988 it.current(); 00989 ++it) { 00990 if (it.current()->walletName() == wallet) { 00991 if (_handles[application].contains(it.currentKey())) { 00992 _handles[application].remove(it.currentKey()); 00993 00994 if (_handles[application].isEmpty()) { 00995 _handles.remove(application); 00996 } 00997 00998 if (it.current()->deref() == 0) { 00999 close(it.current()->walletName(), true); 01000 } 01001 01002 QByteArray data; 01003 QDataStream ds(data, IO_WriteOnly); 01004 ds << wallet; 01005 ds << application; 01006 emitDCOPSignal("applicationDisconnected(QString,QCString)", data); 01007 01008 return true; 01009 } 01010 } 01011 } 01012 01013 return false; 01014 } 01015 01016 01017 void KWalletD::emitFolderUpdated(const QString& wallet, const QString& folder) { 01018 QByteArray data; 01019 QDataStream ds(data, IO_WriteOnly); 01020 ds << wallet; 01021 ds << folder; 01022 emitDCOPSignal("folderUpdated(QString,QString)", data); 01023 } 01024 01025 01026 void KWalletD::emitWalletListDirty() { 01027 emitDCOPSignal("walletListDirty()", QByteArray()); 01028 } 01029 01030 01031 void KWalletD::reconfigure() { 01032 KConfig cfg("kwalletrc"); 01033 cfg.setGroup("Wallet"); 01034 _firstUse = cfg.readBoolEntry("First Use", true); 01035 _enabled = cfg.readBoolEntry("Enabled", true); 01036 _launchManager = cfg.readBoolEntry("Launch Manager", true); 01037 _leaveOpen = cfg.readBoolEntry("Leave Open", false); 01038 bool idleSave = _closeIdle; 01039 _closeIdle = cfg.readBoolEntry("Close When Idle", false); 01040 _openPrompt = cfg.readBoolEntry("Prompt on Open", true); 01041 int timeSave = _idleTime; 01042 // in minutes! 01043 _idleTime = cfg.readNumEntry("Idle Timeout", 10) * 60 * 1000; 01044 01045 if (cfg.readBoolEntry("Close on Screensaver", false)) { 01046 connectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_start_screensaver()", "closeAllWallets()", false); 01047 } else { 01048 disconnectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_start_screensaver()", "closeAllWallets()"); 01049 } 01050 01051 // Handle idle changes 01052 if (_closeIdle) { 01053 if (_idleTime != timeSave) { // Timer length changed 01054 QIntDictIterator<KWallet::Backend> it(_wallets); 01055 for (; it.current(); ++it) { 01056 _timeouts->resetTimer(it.currentKey(), _idleTime); 01057 } 01058 } 01059 01060 if (!idleSave) { // add timers for all the wallets 01061 QIntDictIterator<KWallet::Backend> it(_wallets); 01062 for (; it.current(); ++it) { 01063 _timeouts->addTimer(it.currentKey(), _idleTime); 01064 } 01065 } 01066 } else { 01067 _timeouts->clear(); 01068 } 01069 01070 // Update the implicit allow stuff 01071 _implicitAllowMap.clear(); 01072 cfg.setGroup("Auto Allow"); 01073 QStringList entries = cfg.entryMap("Auto Allow").keys(); 01074 for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) { 01075 _implicitAllowMap[*i] = cfg.readListEntry(*i); 01076 } 01077 01078 // Update if wallet was enabled/disabled 01079 if (!_enabled) { // close all wallets 01080 while (!_wallets.isEmpty()) { 01081 QIntDictIterator<KWallet::Backend> it(_wallets); 01082 if (!it.current()) { // necessary? 01083 break; 01084 } 01085 closeWallet(it.current(), it.currentKey(), true); 01086 } 01087 } 01088 } 01089 01090 01091 bool KWalletD::isEnabled() const { 01092 return _enabled; 01093 } 01094 01095 01096 bool KWalletD::folderDoesNotExist(const QString& wallet, const QString& folder) { 01097 if (!wallets().contains(wallet)) { 01098 return true; 01099 } 01100 01101 for (QIntDictIterator<KWallet::Backend> it(_wallets); it.current(); ++it) { 01102 if (it.current()->walletName() == wallet) { 01103 return it.current()->folderDoesNotExist(folder); 01104 } 01105 } 01106 01107 KWallet::Backend *b = new KWallet::Backend(wallet); 01108 b->open(QByteArray()); 01109 bool rc = b->folderDoesNotExist(folder); 01110 delete b; 01111 return rc; 01112 } 01113 01114 01115 bool KWalletD::keyDoesNotExist(const QString& wallet, const QString& folder, const QString& key) { 01116 if (!wallets().contains(wallet)) { 01117 return true; 01118 } 01119 01120 for (QIntDictIterator<KWallet::Backend> it(_wallets); it.current(); ++it) { 01121 if (it.current()->walletName() == wallet) { 01122 return it.current()->entryDoesNotExist(folder, key); 01123 } 01124 } 01125 01126 KWallet::Backend *b = new KWallet::Backend(wallet); 01127 b->open(QByteArray()); 01128 bool rc = b->entryDoesNotExist(folder, key); 01129 delete b; 01130 return rc; 01131 } 01132 01133 01134 bool KWalletD::implicitAllow(const QString& wallet, const QCString& app) { 01135 return _implicitAllowMap[wallet].contains(QString::fromLocal8Bit(app)); 01136 } 01137 01138 01139 QCString KWalletD::friendlyDCOPPeerName() { 01140 DCOPClient *dc = callingDcopClient(); 01141 if (!dc) { 01142 return ""; 01143 } 01144 return dc->senderId().replace(QRegExp("-[0-9]+$"), ""); 01145 } 01146 01147 01148 void KWalletD::timedOut(int id) { 01149 KWallet::Backend *w = _wallets.find(id); 01150 if (w) { 01151 closeWallet(w, id, true); 01152 } 01153 } 01154 01155 01156 void KWalletD::closeAllWallets() { 01157 QIntDict<KWallet::Backend> tw = _wallets; 01158 01159 for (QIntDictIterator<KWallet::Backend> it(tw); it.current(); ++it) { 01160 closeWallet(it.current(), it.currentKey(), true); 01161 } 01162 01163 tw.clear(); 01164 01165 // All of this should be basically noop. Let's just be safe. 01166 _wallets.clear(); 01167 01168 for (QMap<QString,QCString>::Iterator it = _passwords.begin(); 01169 it != _passwords.end(); 01170 ++it) { 01171 it.data().fill(0); 01172 } 01173 _passwords.clear(); 01174 } 01175 01176 01177 QString KWalletD::networkWallet() { 01178 return KWallet::Wallet::NetworkWallet(); 01179 } 01180 01181 01182 QString KWalletD::localWallet() { 01183 return KWallet::Wallet::LocalWallet(); 01184 } 01185 01186 01187 #include "kwalletd.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:41:08 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003