00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define SAVE_DELAY 3 // Save after 3 minutes
00029
00030 #include <unistd.h>
00031
00032 #include <qtimer.h>
00033 #include <qptrlist.h>
00034 #include <qfile.h>
00035
00036 #include <dcopclient.h>
00037
00038 #include <kconfig.h>
00039 #include <kdebug.h>
00040 #include <kapplication.h>
00041 #include <kcmdlineargs.h>
00042 #include <kstandarddirs.h>
00043
00044 #include "kcookiejar.h"
00045 #include "kcookiewin.h"
00046 #include "kcookieserver.h"
00047
00048 extern "C" {
00049 KDE_EXPORT KDEDModule *create_kcookiejar(const QCString &name)
00050 {
00051 return new KCookieServer(name);
00052 }
00053 }
00054
00055
00056
00057 enum CookieDetails { CF_DOMAIN=0, CF_PATH, CF_NAME, CF_HOST,
00058 CF_VALUE, CF_EXPIRE, CF_PROVER, CF_SECURE };
00059
00060
00061 class CookieRequest {
00062 public:
00063 DCOPClient *client;
00064 DCOPClientTransaction *transaction;
00065 QString url;
00066 bool DOM;
00067 long windowId;
00068 };
00069
00070 template class QPtrList<CookieRequest>;
00071
00072 class RequestList : public QPtrList<CookieRequest>
00073 {
00074 public:
00075 RequestList() : QPtrList<CookieRequest>() { }
00076 };
00077
00078 KCookieServer::KCookieServer(const QCString &name)
00079 :KDEDModule(name)
00080 {
00081 mOldCookieServer = new DCOPClient();
00082 mOldCookieServer->registerAs("kcookiejar", false);
00083 mOldCookieServer->setDaemonMode( true );
00084 mCookieJar = new KCookieJar;
00085 mPendingCookies = new KHttpCookieList;
00086 mPendingCookies->setAutoDelete(true);
00087 mRequestList = new RequestList;
00088 mAdvicePending = false;
00089 mTimer = new QTimer();
00090 connect( mTimer, SIGNAL( timeout()), SLOT( slotSave()));
00091 mConfig = new KConfig("kcookiejarrc");
00092 mCookieJar->loadConfig( mConfig );
00093
00094 QString filename = locateLocal("data", "kcookiejar/cookies");
00095
00096
00097 QString filenameOld = locate("data", "kfm/cookies");
00098 if (!filenameOld.isEmpty())
00099 {
00100 mCookieJar->loadCookies( filenameOld );
00101 if (mCookieJar->saveCookies( filename))
00102 {
00103 unlink(QFile::encodeName(filenameOld));
00104 }
00105 }
00106 else
00107 {
00108 mCookieJar->loadCookies( filename);
00109 }
00110 connect(this, SIGNAL(windowUnregistered(long)),
00111 this, SLOT(slotDeleteSessionCookies(long)));
00112 }
00113
00114 KCookieServer::~KCookieServer()
00115 {
00116 if (mCookieJar->changed())
00117 slotSave();
00118 delete mOldCookieServer;
00119 delete mCookieJar;
00120 delete mTimer;
00121 delete mPendingCookies;
00122 delete mConfig;
00123 }
00124
00125 bool KCookieServer::cookiesPending( const QString &url, KHttpCookieList *cookieList )
00126 {
00127 QString fqdn;
00128 QStringList domains;
00129 QString path;
00130
00131 if (mPendingCookies->isEmpty())
00132 return false;
00133 if (!KCookieJar::parseURL(url, fqdn, path))
00134 return false;
00135
00136 mCookieJar->extractDomains( fqdn, domains );
00137 for( KHttpCookie *cookie = mPendingCookies->first();
00138 cookie != 0L;
00139 cookie = mPendingCookies->next())
00140 {
00141 if (cookie->match( fqdn, domains, path))
00142 {
00143 if (!cookieList)
00144 return true;
00145 cookieList->append(cookie);
00146 }
00147 }
00148 if (!cookieList)
00149 return false;
00150 return cookieList->isEmpty();
00151 }
00152
00153 void KCookieServer::addCookies( const QString &url, const QCString &cookieHeader,
00154 long windowId, bool useDOMFormat )
00155 {
00156 KHttpCookieList cookieList;
00157 if (useDOMFormat)
00158 cookieList = mCookieJar->makeDOMCookies(url, cookieHeader, windowId);
00159 else
00160 cookieList = mCookieJar->makeCookies(url, cookieHeader, windowId);
00161
00162 checkCookies(&cookieList);
00163
00164 for(KHttpCookiePtr cookie = cookieList.first(); cookie; cookie = cookieList.first())
00165 mPendingCookies->append(cookieList.take());
00166
00167 if (!mAdvicePending)
00168 {
00169 mAdvicePending = true;
00170 while (!mPendingCookies->isEmpty())
00171 {
00172 checkCookies(0);
00173 }
00174 mAdvicePending = false;
00175 }
00176 }
00177
00178 void KCookieServer::checkCookies( KHttpCookieList *cookieList)
00179 {
00180 KHttpCookieList *list;
00181
00182 if (cookieList)
00183 list = cookieList;
00184 else
00185 list = mPendingCookies;
00186
00187 KHttpCookiePtr cookie = list->first();
00188 while (cookie)
00189 {
00190 kdDebug(7104) << "checkCookies: Asking cookie advice for " << cookie->host() << endl;
00191 KCookieAdvice advice = mCookieJar->cookieAdvice(cookie);
00192 switch(advice)
00193 {
00194 case KCookieAccept:
00195 list->take();
00196 mCookieJar->addCookie(cookie);
00197 cookie = list->current();
00198 break;
00199
00200 case KCookieReject:
00201 list->take();
00202 delete cookie;
00203 cookie = list->current();
00204 break;
00205
00206 default:
00207 cookie = list->next();
00208 break;
00209 }
00210 }
00211
00212 if (cookieList || list->isEmpty())
00213 return;
00214
00215 KHttpCookiePtr currentCookie = mPendingCookies->first();
00216
00217 KHttpCookieList currentList;
00218 currentList.append(currentCookie);
00219 QString currentHost = currentCookie->host();
00220
00221 cookie = mPendingCookies->next();
00222 while (cookie)
00223 {
00224 if (cookie->host() == currentHost)
00225 {
00226 currentList.append(cookie);
00227 }
00228 cookie = mPendingCookies->next();
00229 }
00230
00231 KCookieWin *kw = new KCookieWin( 0L, currentList,
00232 mCookieJar->preferredDefaultPolicy(),
00233 mCookieJar->showCookieDetails() );
00234 KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
00235 delete kw;
00236
00237 mCookieJar->saveConfig( mConfig );
00238
00239
00240
00241 cookie = mPendingCookies->first();
00242 while (cookie)
00243 {
00244 if (cookie->host() == currentHost)
00245 {
00246 switch(userAdvice)
00247 {
00248 case KCookieAccept:
00249 mPendingCookies->take();
00250 mCookieJar->addCookie(cookie);
00251 cookie = mPendingCookies->current();
00252 break;
00253
00254 case KCookieReject:
00255 mPendingCookies->take();
00256 delete cookie;
00257 cookie = mPendingCookies->current();
00258 break;
00259
00260 default:
00261 qWarning(__FILE__":%d Problem!", __LINE__);
00262 cookie = mPendingCookies->next();
00263 break;
00264 }
00265 }
00266 else
00267 {
00268 cookie = mPendingCookies->next();
00269 }
00270 }
00271
00272
00273
00274 for ( CookieRequest *request = mRequestList->first(); request;)
00275 {
00276 if (!cookiesPending( request->url ))
00277 {
00278 QCString replyType;
00279 QByteArray replyData;
00280 QString res = mCookieJar->findCookies( request->url, request->DOM, request->windowId );
00281
00282 QDataStream stream2(replyData, IO_WriteOnly);
00283 stream2 << res;
00284 replyType = "QString";
00285 request->client->endTransaction( request->transaction,
00286 replyType, replyData);
00287 CookieRequest *tmp = request;
00288 request = mRequestList->next();
00289 mRequestList->removeRef( tmp );
00290 delete tmp;
00291 }
00292 else
00293 {
00294 request = mRequestList->next();
00295 }
00296 }
00297 if (mCookieJar->changed())
00298 saveCookieJar();
00299 }
00300
00301 void KCookieServer::slotSave()
00302 {
00303 QString filename = locateLocal("data", "kcookiejar/cookies");
00304 mCookieJar->saveCookies(filename);
00305 }
00306
00307 void KCookieServer::saveCookieJar()
00308 {
00309 if( mTimer->isActive() )
00310 return;
00311
00312 mTimer->start( 1000*60*SAVE_DELAY, true );
00313 }
00314
00315 void KCookieServer::putCookie( QStringList& out, KHttpCookie *cookie,
00316 const QValueList<int>& fields )
00317 {
00318 QValueList<int>::ConstIterator i = fields.begin();
00319 for ( ; i != fields.end(); ++i )
00320 {
00321 switch(*i)
00322 {
00323 case CF_DOMAIN :
00324 out << cookie->domain();
00325 break;
00326 case CF_NAME :
00327 out << cookie->name();
00328 break;
00329 case CF_PATH :
00330 out << cookie->path();
00331 break;
00332 case CF_HOST :
00333 out << cookie->host();
00334 break;
00335 case CF_VALUE :
00336 out << cookie->value();
00337 break;
00338 case CF_EXPIRE :
00339 out << QString::number(cookie->expireDate());
00340 break;
00341 case CF_PROVER :
00342 out << QString::number(cookie->protocolVersion());
00343 break;
00344 case CF_SECURE :
00345 out << QString::number( cookie->isSecure() ? 1 : 0 );
00346 break;
00347 default :
00348 out << QString::null;
00349 }
00350 }
00351 }
00352
00353 bool KCookieServer::cookieMatches( KHttpCookiePtr c,
00354 QString domain, QString fqdn,
00355 QString path, QString name )
00356 {
00357 if( c )
00358 {
00359 bool hasDomain = !domain.isEmpty();
00360 return
00361 ((hasDomain && c->domain() == domain) ||
00362 fqdn == c->host()) &&
00363 (c->path() == path) &&
00364 (c->name() == name) &&
00365 (!c->isExpired(time(0)));
00366 }
00367 return false;
00368 }
00369
00370
00371 QString
00372 KCookieServer::findCookies(QString url)
00373 {
00374 return findCookies(url, 0);
00375 }
00376
00377
00378 QString
00379 KCookieServer::findCookies(QString url, long windowId)
00380 {
00381 if (cookiesPending(url))
00382 {
00383 CookieRequest *request = new CookieRequest;
00384 request->client = callingDcopClient();
00385 request->transaction = request->client->beginTransaction();
00386 request->url = url;
00387 request->DOM = false;
00388 request->windowId = windowId;
00389 mRequestList->append( request );
00390 return QString::null;
00391 }
00392
00393 QString cookies = mCookieJar->findCookies(url, false, windowId);
00394
00395 if (mCookieJar->changed())
00396 saveCookieJar();
00397
00398 return cookies;
00399 }
00400
00401
00402 QStringList
00403 KCookieServer::findDomains()
00404 {
00405 QStringList result;
00406 const QStringList domains = mCookieJar->getDomainList();
00407 for ( QStringList::ConstIterator domIt = domains.begin();
00408 domIt != domains.end(); ++domIt )
00409 {
00410
00411
00412 const KHttpCookieList* list = mCookieJar->getCookieList(*domIt, "");
00413 if ( list && !list->isEmpty() )
00414 result << *domIt;
00415 }
00416 return result;
00417 }
00418
00419
00420 QStringList
00421 KCookieServer::findCookies(QValueList<int> fields,
00422 QString domain,
00423 QString fqdn,
00424 QString path,
00425 QString name)
00426 {
00427 QStringList result;
00428 bool allDomCookies = name.isEmpty();
00429
00430 const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
00431 if ( list && !list->isEmpty() )
00432 {
00433 QPtrListIterator<KHttpCookie>it( *list );
00434 for ( ; it.current(); ++it )
00435 {
00436 if ( !allDomCookies )
00437 {
00438 if ( cookieMatches(it.current(), domain, fqdn, path, name) )
00439 {
00440 putCookie(result, it.current(), fields);
00441 break;
00442 }
00443 }
00444 else
00445 putCookie(result, it.current(), fields);
00446 }
00447 }
00448 return result;
00449 }
00450
00451
00452 QString
00453 KCookieServer::findDOMCookies(QString url)
00454 {
00455 return findDOMCookies(url, 0);
00456 }
00457
00458
00459 QString
00460 KCookieServer::findDOMCookies(QString url, long windowId)
00461 {
00462
00463
00464
00465 KHttpCookieList pendingCookies;
00466 cookiesPending(url, &pendingCookies);
00467
00468 return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
00469 }
00470
00471
00472 void
00473 KCookieServer::addCookies(QString arg1, QCString arg2, long arg3)
00474 {
00475 addCookies(arg1, arg2, arg3, false);
00476 }
00477
00478
00479 void
00480 KCookieServer::deleteCookie(QString domain, QString fqdn,
00481 QString path, QString name)
00482 {
00483 const KHttpCookieList* list = mCookieJar->getCookieList( domain, fqdn );
00484 if ( list && !list->isEmpty() )
00485 {
00486 QPtrListIterator<KHttpCookie>it (*list);
00487 for ( ; it.current(); ++it )
00488 {
00489 if( cookieMatches(it.current(), domain, fqdn, path, name) )
00490 {
00491 mCookieJar->eatCookie( it.current() );
00492 saveCookieJar();
00493 break;
00494 }
00495 }
00496 }
00497 }
00498
00499
00500 void
00501 KCookieServer::deleteCookiesFromDomain(QString domain)
00502 {
00503 mCookieJar->eatCookiesForDomain(domain);
00504 saveCookieJar();
00505 }
00506
00507
00508
00509 void
00510 KCookieServer::slotDeleteSessionCookies( long windowId )
00511 {
00512 deleteSessionCookies(windowId);
00513 }
00514
00515
00516 void
00517 KCookieServer::deleteSessionCookies( long windowId )
00518 {
00519 mCookieJar->eatSessionCookies( windowId );
00520 saveCookieJar();
00521 }
00522
00523 void
00524 KCookieServer::deleteSessionCookiesFor(QString fqdn, long windowId)
00525 {
00526 mCookieJar->eatSessionCookies( fqdn, windowId );
00527 saveCookieJar();
00528 }
00529
00530
00531 void
00532 KCookieServer::deleteAllCookies()
00533 {
00534 mCookieJar->eatAllCookies();
00535 saveCookieJar();
00536 }
00537
00538
00539 void
00540 KCookieServer::addDOMCookies(QString arg1, QCString arg2, long arg3)
00541 {
00542 addCookies(arg1, arg2, arg3, true);
00543 }
00544
00545
00546 void
00547 KCookieServer::setDomainAdvice(QString url, QString advice)
00548 {
00549 QString fqdn;
00550 QString dummy;
00551 if (KCookieJar::parseURL(url, fqdn, dummy))
00552 {
00553 QStringList domains;
00554 mCookieJar->extractDomains(fqdn, domains);
00555
00556 mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
00557 KCookieJar::strToAdvice(advice));
00558
00559 mCookieJar->saveConfig( mConfig );
00560 }
00561 }
00562
00563
00564 QString
00565 KCookieServer::getDomainAdvice(QString url)
00566 {
00567 KCookieAdvice advice = KCookieDunno;
00568 QString fqdn;
00569 QString dummy;
00570 if (KCookieJar::parseURL(url, fqdn, dummy))
00571 {
00572 QStringList domains;
00573 mCookieJar->extractDomains(fqdn, domains);
00574
00575 QStringList::ConstIterator it = domains.begin();
00576 while ( (advice == KCookieDunno) && (it != domains.end()) )
00577 {
00578
00579
00580
00581 if ( (*it)[0] == '.' || (*it) == fqdn )
00582 advice = mCookieJar->getDomainAdvice(*it);
00583 ++it;
00584 }
00585 if (advice == KCookieDunno)
00586 advice = mCookieJar->getGlobalAdvice();
00587 }
00588 return KCookieJar::adviceToStr(advice);
00589 }
00590
00591
00592 void
00593 KCookieServer::reloadPolicy()
00594 {
00595 mCookieJar->loadConfig( mConfig, true );
00596 }
00597
00598
00599 void
00600 KCookieServer::shutdown()
00601 {
00602 deleteLater();
00603 }
00604
00605 #include "kcookieserver.moc"
00606