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