26 #include "kpasswdserver.h"
32 #include <tdeapplication.h>
33 #include <tdelocale.h>
34 #include <tdemessagebox.h>
36 #include <tdeio/passdlg.h>
37 #include <tdewallet.h>
46 TDE_EXPORT KDEDModule *create_kpasswdserver(
const TQCString &name)
48 return new KPasswdServer(name);
53 KPasswdServer::AuthInfoList::compareItems(TQPtrCollection::Item n1, TQPtrCollection::Item n2)
58 AuthInfo *i1 = (AuthInfo *) n1;
59 AuthInfo *i2 = (AuthInfo *) n2;
61 int l1 = i1->directory.length();
62 int l2 = i2->directory.length();
72 KPasswdServer::KPasswdServer(
const TQCString &name)
75 m_authDict.setAutoDelete(
true);
76 m_authPending.setAutoDelete(
true);
79 connect(
this, TQ_SIGNAL(windowUnregistered(
long)),
80 this, TQ_SLOT(removeAuthForWindowId(
long)));
83 KPasswdServer::~KPasswdServer()
89 static TQString makeWalletKey(
const TQString& key,
const TQString& realm )
91 return realm.isEmpty() ? key : key +
'-' + realm;
95 static TQString makeMapKey(
const char* key,
int entryNumber )
97 TQString str = TQString::fromLatin1( key );
98 if ( entryNumber > 1 )
99 str +=
"-" + TQString::number( entryNumber );
103 static bool storeInWallet( TDEWallet::Wallet* wallet,
const TQString& key,
const TDEIO::AuthInfo &info )
105 if ( !wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) )
106 if ( !wallet->createFolder( TDEWallet::Wallet::PasswordFolder() ) )
108 wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
111 typedef TQMap<TQString,TQString> Map;
114 TQString walletKey = makeWalletKey( key, info.realmValue );
115 kdDebug(130) <<
"storeInWallet: walletKey=" << walletKey <<
" reading existing map" << endl;
116 if ( wallet->readMap( walletKey, map ) == 0 ) {
117 Map::ConstIterator end = map.end();
118 Map::ConstIterator it = map.find(
"login" );
119 while ( it != end ) {
120 if ( it.data() == info.username ) {
123 it = map.find( TQString(
"login-" ) + TQString::number( ++entryNumber ) );
127 const TQString loginKey = makeMapKey(
"login", entryNumber );
128 const TQString passwordKey = makeMapKey(
"password", entryNumber );
129 kdDebug(130) <<
"storeInWallet: writing to " << loginKey <<
"," << passwordKey << endl;
131 map.insert( loginKey, info.username );
132 map.insert( passwordKey, info.password );
133 wallet->writeMap( walletKey, map );
138 static bool readFromWallet( TDEWallet::Wallet* wallet,
const TQString& key,
const TQString& realm, TQString& username, TQString& password,
bool userReadOnly, TQMap<TQString,TQString>& knownLogins )
141 if ( wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) )
143 wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
145 TQMap<TQString,TQString> map;
146 if ( wallet->readMap( makeWalletKey( key, realm ), map ) == 0 )
148 typedef TQMap<TQString,TQString> Map;
150 Map::ConstIterator end = map.end();
151 Map::ConstIterator it = map.find(
"login" );
152 while ( it != end ) {
154 Map::ConstIterator pwdIter = map.find( makeMapKey(
"password", entryNumber ) );
155 if ( pwdIter != end ) {
156 if ( it.data() == username )
157 password = pwdIter.data();
158 knownLogins.insert( it.data(), pwdIter.data() );
161 it = map.find( TQString(
"login-" ) + TQString::number( ++entryNumber ) );
165 if ( !userReadOnly && !knownLogins.isEmpty() && username.isEmpty() ) {
167 username = knownLogins.begin().key();
168 password = knownLogins.begin().data();
179 KPasswdServer::checkAuthInfo(TDEIO::AuthInfo info,
long windowId)
181 return checkAuthInfo(info, windowId, 0);
185 KPasswdServer::checkAuthInfo(TDEIO::AuthInfo info,
long windowId,
unsigned long usertime)
187 kdDebug(130) <<
"KPasswdServer::checkAuthInfo: User= " << info.username
188 <<
", WindowId = " << windowId << endl;
190 kapp->updateUserTimestamp( usertime );
192 TQString key = createCacheKey(info);
194 Request *request = m_authPending.first();
195 TQString path2 = info.url.directory(
false,
false);
196 for(; request; request = m_authPending.next())
198 if (request->key != key)
203 TQString path1 = request->info.url.directory(
false,
false);
204 if (!path2.startsWith(path1))
208 request =
new Request;
209 request->client = callingDcopClient();
210 request->transaction = request->client->beginTransaction();
212 request->info = info;
213 m_authWait.append(request);
217 const AuthInfo *result = findAuthInfoItem(key, info);
218 if (!result || result->isCanceled)
221 (info.username.isEmpty() || info.password.isEmpty()) &&
222 !TDEWallet::Wallet::keyDoesNotExist(TDEWallet::Wallet::NetworkWallet(),
223 TDEWallet::Wallet::PasswordFolder(), makeWalletKey(key, info.realmValue)))
225 TQMap<TQString, TQString> knownLogins;
226 if (openWallet(windowId)) {
227 if (readFromWallet(m_wallet, key, info.realmValue, info.username, info.password,
228 info.readOnly, knownLogins))
230 info.setModified(
true);
236 info.setModified(
false);
240 updateAuthExpire(key, result, windowId,
false);
242 return copyAuthInfo(result);
246 KPasswdServer::queryAuthInfo(TDEIO::AuthInfo info, TQString errorMsg,
long windowId,
long seqNr)
248 return queryAuthInfo(info, errorMsg, windowId, seqNr, 0 );
252 KPasswdServer::queryAuthInfo(TDEIO::AuthInfo info, TQString errorMsg,
long windowId,
long seqNr,
unsigned long usertime)
254 kdDebug(130) <<
"KPasswdServer::queryAuthInfo: User= " << info.username
255 <<
", Message= " << info.prompt <<
", WindowId = " << windowId << endl;
256 if ( !info.password.isEmpty() )
257 kdDebug(130) <<
"password was set by caller" << endl;
259 kapp->updateUserTimestamp( usertime );
261 TQString key = createCacheKey(info);
262 Request *request =
new Request;
263 request->client = callingDcopClient();
264 request->transaction = request->client->beginTransaction();
266 request->info = info;
267 request->windowId = windowId;
268 request->seqNr = seqNr;
269 if (errorMsg ==
"<NoAuthPrompt>")
271 request->errorMsg = TQString::null;
272 request->prompt =
false;
276 request->errorMsg = errorMsg;
277 request->prompt =
true;
279 m_authPending.append(request);
281 if (m_authPending.count() == 1)
282 TQTimer::singleShot(0,
this, TQ_SLOT(processRequest()));
288 KPasswdServer::addAuthInfo(TDEIO::AuthInfo info,
long windowId)
290 kdDebug(130) <<
"KPasswdServer::addAuthInfo: User= " << info.username
291 <<
", RealmValue= " << info.realmValue <<
", WindowId = " << windowId << endl;
292 TQString key = createCacheKey(info);
296 addAuthInfoItem(key, info, windowId, m_seqNr,
false);
300 KPasswdServer::openWallet( WId windowId )
302 if ( m_wallet && !m_wallet->isOpen() ) {
307 m_wallet = TDEWallet::Wallet::openWallet(
308 TDEWallet::Wallet::NetworkWallet(), windowId );
309 return m_wallet != 0;
313 KPasswdServer::processRequest()
315 Request *request = m_authPending.first();
319 TDEIO::AuthInfo &info = request->info;
321 kdDebug(130) <<
"KPasswdServer::processRequest: User= " << info.username
322 <<
", Message= " << info.prompt << endl;
323 const AuthInfo *result = findAuthInfoItem(request->key, request->info);
325 if (result && (request->seqNr < result->seqNr))
327 kdDebug(130) <<
"KPasswdServer::processRequest: auto retry!" << endl;
328 if (result->isCanceled)
330 info.setModified(
false);
334 updateAuthExpire(request->key, result, request->windowId,
false);
335 info = copyAuthInfo(result);
341 bool askPw = request->prompt;
342 if (result && !info.username.isEmpty() &&
343 !request->errorMsg.isEmpty())
345 TQString prompt = request->errorMsg;
346 prompt += i18n(
" Do you want to retry?");
347 int dlgResult = KMessageBox::warningContinueCancelWId(request->windowId, prompt,
348 i18n(
"Authentication"), i18n(
"Retry"));
349 if (dlgResult != KMessageBox::Continue)
353 int dlgResult = TQDialog::Rejected;
356 TQString username = info.username;
357 TQString password = info.password;
358 bool hasWalletData =
false;
359 TQMap<TQString, TQString> knownLogins;
361 if ( ( username.isEmpty() || password.isEmpty() )
362 && !TDEWallet::Wallet::keyDoesNotExist(TDEWallet::Wallet::NetworkWallet(), TDEWallet::Wallet::PasswordFolder(), makeWalletKey( request->key, info.realmValue )) )
365 if ( openWallet( request->windowId ) )
366 hasWalletData = readFromWallet( m_wallet, request->key, info.realmValue, username, password, info.readOnly, knownLogins );
369 TDEIO::PasswordDialog dlg( info.prompt, username, info.keepPassword );
370 if (info.caption.isEmpty())
371 dlg.setPlainCaption( i18n(
"Authorization Dialog") );
373 dlg.setPlainCaption( info.caption );
375 if ( !info.comment.isEmpty() )
376 dlg.addCommentLine( info.commentLabel, info.comment );
378 if ( !password.isEmpty() )
379 dlg.setPassword( password );
382 dlg.setUserReadOnly(
true );
384 dlg.setKnownLogins( knownLogins );
387 dlg.setKeepPassword(
true );
390 XSetTransientForHint( tqt_xdisplay(), dlg.winId(), request->windowId);
393 dlgResult = dlg.exec();
395 if (dlgResult == TQDialog::Accepted)
397 info.username = dlg.username();
398 info.password = dlg.password();
399 info.keepPassword = dlg.keepPassword();
405 if ( info.keepPassword ) {
406 if ( openWallet( request->windowId ) ) {
407 if ( storeInWallet( m_wallet, request->key, info ) )
409 info.keepPassword =
false;
414 if ( dlgResult != TQDialog::Accepted )
416 addAuthInfoItem(request->key, info, 0, m_seqNr,
true);
417 info.setModified(
false );
421 addAuthInfoItem(request->key, info, request->windowId, m_seqNr,
false);
422 info.setModified(
true );
427 TQByteArray replyData;
429 TQDataStream stream2(replyData, IO_WriteOnly);
430 stream2 << info << m_seqNr;
431 replyType =
"TDEIO::AuthInfo";
432 request->client->endTransaction( request->transaction,
433 replyType, replyData);
435 m_authPending.remove((
unsigned int) 0);
438 for(Request *waitRequest = m_authWait.first();
441 bool keepQueued =
false;
442 TQString key = waitRequest->key;
444 request = m_authPending.first();
445 TQString path2 = waitRequest->info.url.directory(
false,
false);
446 for(; request; request = m_authPending.next())
448 if (request->key != key)
453 TQString path1 = request->info.url.directory(
false,
false);
454 if (!path2.startsWith(path1))
463 waitRequest = m_authWait.next();
467 const AuthInfo *result = findAuthInfoItem(waitRequest->key, waitRequest->info);
470 TQByteArray replyData;
472 TQDataStream stream2(replyData, IO_WriteOnly);
474 if (!result || result->isCanceled)
476 waitRequest->info.setModified(
false);
477 stream2 << waitRequest->info;
481 updateAuthExpire(waitRequest->key, result, waitRequest->windowId,
false);
482 TDEIO::AuthInfo info = copyAuthInfo(result);
486 replyType =
"TDEIO::AuthInfo";
487 waitRequest->client->endTransaction( waitRequest->transaction,
488 replyType, replyData);
491 waitRequest = m_authWait.current();
495 if (m_authPending.count())
496 TQTimer::singleShot(0,
this, TQ_SLOT(processRequest()));
500 TQString KPasswdServer::createCacheKey(
const TDEIO::AuthInfo &info )
502 if( !info.url.isValid() ) {
504 kdWarning(130) <<
"createCacheKey: invalid URL " << info.url << endl;
505 return TQString::null;
509 TQString key = info.url.protocol();
511 if (!info.url.user().isEmpty())
513 key += info.url.user();
516 key += info.url.host();
517 int port = info.url.port();
521 key += TQString::number(port);
528 KPasswdServer::copyAuthInfo(
const AuthInfo *i)
530 TDEIO::AuthInfo result;
532 result.username = i->username;
533 result.password = i->password;
534 result.realmValue = i->realmValue;
535 result.digestInfo = i->digestInfo;
536 result.setModified(
true);
541 const KPasswdServer::AuthInfo *
542 KPasswdServer::findAuthInfoItem(
const TQString &key,
const TDEIO::AuthInfo &info)
544 AuthInfoList *authList = m_authDict.find(key);
548 TQString path2 = info.url.directory(
false,
false);
549 for(AuthInfo *current = authList->first();
552 if ((current->expire == AuthInfo::expTime) &&
553 (difftime(time(0), current->expireTime) > 0))
556 current = authList->current();
562 TQString path1 = current->directory;
563 if (path2.startsWith(path1) &&
564 (info.username.isEmpty() || info.username == current->username))
569 if (current->realmValue == info.realmValue &&
570 (info.username.isEmpty() || info.username == current->username))
574 current = authList->next();
580 KPasswdServer::removeAuthInfoItem(
const TQString &key,
const TDEIO::AuthInfo &info)
582 AuthInfoList *authList = m_authDict.find(key);
586 for(AuthInfo *current = authList->first();
589 if (current->realmValue == info.realmValue)
592 current = authList->current();
596 current = authList->next();
599 if (authList->isEmpty())
601 m_authDict.remove(key);
607 KPasswdServer::addAuthInfoItem(
const TQString &key,
const TDEIO::AuthInfo &info,
long windowId,
long seqNr,
bool canceled)
609 AuthInfoList *authList = m_authDict.find(key);
612 authList =
new AuthInfoList;
613 m_authDict.insert(key, authList);
615 AuthInfo *current = authList->first();
616 for(; current; current = authList->next())
618 if (current->realmValue == info.realmValue)
627 current =
new AuthInfo;
628 current->expire = AuthInfo::expTime;
629 kdDebug(130) <<
"Creating AuthInfo" << endl;
633 kdDebug(130) <<
"Updating AuthInfo" << endl;
636 current->url = info.url;
637 current->directory = info.url.directory(
false,
false);
638 current->username = info.username;
639 current->password = info.password;
640 current->realmValue = info.realmValue;
641 current->digestInfo = info.digestInfo;
642 current->seqNr = seqNr;
643 current->isCanceled = canceled;
645 updateAuthExpire(key, current, windowId, info.keepPassword && !canceled);
648 authList->inSort(current);
652 KPasswdServer::updateAuthExpire(
const TQString &key,
const AuthInfo *auth,
long windowId,
bool keep)
654 AuthInfo *current =
const_cast<AuthInfo *
>(auth);
657 current->expire = AuthInfo::expNever;
659 else if (windowId && (current->expire != AuthInfo::expNever))
661 current->expire = AuthInfo::expWindowClose;
662 if (!current->windowList.contains(windowId))
663 current->windowList.append(windowId);
665 else if (current->expire == AuthInfo::expTime)
667 current->expireTime = time(0)+10;
673 TQStringList *keysChanged = mWindowIdList.find(windowId);
676 keysChanged =
new TQStringList;
677 mWindowIdList.insert(windowId, keysChanged);
679 if (!keysChanged->contains(key))
680 keysChanged->append(key);
685 KPasswdServer::removeAuthForWindowId(
long windowId)
687 TQStringList *keysChanged = mWindowIdList.find(windowId);
688 if (!keysChanged)
return;
690 for(TQStringList::ConstIterator it = keysChanged->begin();
691 it != keysChanged->end(); ++it)
694 AuthInfoList *authList = m_authDict.find(key);
698 AuthInfo *current = authList->first();
701 if (current->expire == AuthInfo::expWindowClose)
703 if (current->windowList.remove(windowId) && current->windowList.isEmpty())
706 current = authList->current();
710 current = authList->next();
715 #include "kpasswdserver.moc"