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