00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00115
do {
00116 rc = rand();
00117 }
while (_wallets.find(rc));
00118
00119
return rc;
00120 }
00121
00122
00123
void KWalletD::processTransactions() {
00124
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
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) {
00172
return -1;
00173 }
00174
00175
00176
return internalOpen(friendlyDCOPPeerName(), path,
true, wId);
00177 }
00178
00179
00180
int KWalletD::open(
const QString& wallet, uint wId) {
00181
if (!_enabled) {
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;
00202 }
00203
00204
int rc = doTransactionOpen(appid, wallet, wId);
00205
00206 _transactions.remove(xact);
00207
00208
if (rc < 0) {
00209
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
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
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
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;
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) {
00553
if (_handles.contains(appid)) {
00554
if (_handles[appid].contains(handle)) {
00555
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
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;
00583 }
00584
00585
return -1;
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
00606
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) {
00912
if (_handles.contains(appid)) {
00913
if (_handles[appid].contains(handle)) {
00914
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
00926
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
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
01052
if (_closeIdle) {
01053
if (_idleTime != timeSave) {
01054
QIntDictIterator<KWallet::Backend> it(_wallets);
01055
for (; it.current(); ++it) {
01056 _timeouts->resetTimer(it.currentKey(), _idleTime);
01057 }
01058 }
01059
01060
if (!idleSave) {
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
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
01079
if (!_enabled) {
01080
while (!_wallets.isEmpty()) {
01081
QIntDictIterator<KWallet::Backend> it(_wallets);
01082
if (!it.current()) {
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
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"