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
00198 const KHttpCookie& currentCookie = mPendingCookies->first();
00199 KHttpCookieList currentList;
00200 currentList.append(currentCookie);
00201 const QString currentHost = currentCookie.host();
00202 QList<int> shownCookies; shownCookies << 0;
00203 for (int i = 1 ; i < mPendingCookies->count(); ++i) {
00204 const KHttpCookie& cookie = (*mPendingCookies)[i];
00205 if (cookie.host() == currentHost) {
00206 currentList.append(cookie);
00207 shownCookies << i;
00208 }
00209 }
00210 kDebug() << shownCookies;
00211
00212 KCookieWin *kw = new KCookieWin( 0L, currentList,
00213 mCookieJar->preferredDefaultPolicy(),
00214 mCookieJar->showCookieDetails() );
00215 KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
00216 delete kw;
00217
00218 mCookieJar->saveConfig( mConfig );
00219
00220
00221
00222 QMutableListIterator<KHttpCookie> cookieIterator2(*mPendingCookies);
00223 int pendingCookieIndex = -1;
00224 while (cookieIterator2.hasNext()) {
00225 ++pendingCookieIndex;
00226 KHttpCookie& cookie = cookieIterator2.next();
00227 if (cookie.host() != currentHost)
00228 continue;
00229 if (mCookieJar->preferredDefaultPolicy() == KCookieJar::ApplyToShownCookiesOnly
00230 && !shownCookies.contains(pendingCookieIndex)) {
00231
00232 break;
00233 }
00234 switch(userAdvice) {
00235 case KCookieAccept:
00236 mCookieJar->addCookie(cookie);
00237 cookieIterator2.remove();
00238 break;
00239
00240 case KCookieReject:
00241 cookieIterator2.remove();
00242 break;
00243
00244 default:
00245 kWarning() << "userAdvice not accept or reject, this should never happen!";
00246 break;
00247 }
00248 }
00249
00250
00251 QMutableListIterator<CookieRequest *> requestIterator(*mRequestList);
00252 while (requestIterator.hasNext()) {
00253 CookieRequest *request = requestIterator.next();
00254 if (!cookiesPending(request->url)) {
00255 const QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId);
00256
00257 QDBusConnection::sessionBus().send(request->reply.createReply(res));
00258 delete request;
00259 requestIterator.remove();
00260 }
00261 }
00262
00263 saveCookieJar();
00264 }
00265
00266 void KCookieServer::slotSave()
00267 {
00268 if (mCookieJar->changed())
00269 {
00270 QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies");
00271 mCookieJar->saveCookies(filename);
00272 }
00273 }
00274
00275 void KCookieServer::saveCookieJar()
00276 {
00277 if( mTimer->isActive() )
00278 return;
00279
00280 mTimer->start( 1000*60*SAVE_DELAY );
00281 }
00282
00283 void KCookieServer::putCookie( QStringList& out, const KHttpCookie& cookie,
00284 const QList<int>& fields )
00285 {
00286 foreach ( int i, fields ) {
00287 switch(i)
00288 {
00289 case CF_DOMAIN :
00290 out << cookie.domain();
00291 break;
00292 case CF_NAME :
00293 out << cookie.name();
00294 break;
00295 case CF_PATH :
00296 out << cookie.path();
00297 break;
00298 case CF_HOST :
00299 out << cookie.host();
00300 break;
00301 case CF_VALUE :
00302 out << cookie.value();
00303 break;
00304 case CF_EXPIRE :
00305 out << QString::number(cookie.expireDate());
00306 break;
00307 case CF_PROVER :
00308 out << QString::number(cookie.protocolVersion());
00309 break;
00310 case CF_SECURE :
00311 out << QString::number(cookie.isSecure() ? 1 : 0);
00312 break;
00313 default :
00314 out << QString();
00315 }
00316 }
00317 }
00318
00319 bool KCookieServer::cookieMatches(const KHttpCookie& c,
00320 const QString &domain, const QString &fqdn,
00321 const QString &path, const QString &name)
00322 {
00323 const bool hasDomain = !domain.isEmpty();
00324 return
00325 ((hasDomain && c.domain() == domain) ||
00326 fqdn == c.host()) &&
00327 (c.path() == path) &&
00328 (c.name() == name) &&
00329 (!c.isExpired(time(0)));
00330 }
00331
00332
00333
00334 QString KCookieServer::listCookies(const QString &url)
00335 {
00336 return findCookies(url, 0);
00337 }
00338
00339
00340 QString KCookieServer::findCookies(const QString &url, qlonglong windowId)
00341 {
00342 if (cookiesPending(url))
00343 {
00344 CookieRequest *request = new CookieRequest;
00345 message().setDelayedReply(true);
00346 request->reply = message();
00347 request->url = url;
00348 request->DOM = false;
00349 request->windowId = windowId;
00350 mRequestList->append( request );
00351 return QString();
00352 }
00353
00354 QString cookies = mCookieJar->findCookies(url, false, windowId);
00355 saveCookieJar();
00356 return cookies;
00357 }
00358
00359
00360 QStringList
00361 KCookieServer::findDomains()
00362 {
00363 QStringList result;
00364 const QStringList domains = mCookieJar->getDomainList();
00365 for ( QStringList::ConstIterator domIt = domains.begin();
00366 domIt != domains.end(); ++domIt )
00367 {
00368
00369
00370 const KHttpCookieList* list = mCookieJar->getCookieList(*domIt, "");
00371 if ( list && !list->isEmpty() )
00372 result << *domIt;
00373 }
00374 return result;
00375 }
00376
00377
00378 QStringList
00379 KCookieServer::findCookies(const QList<int> &fields,
00380 const QString &domain,
00381 const QString &fqdn,
00382 const QString &path,
00383 const QString &name)
00384 {
00385 QStringList result;
00386 const bool allDomCookies = name.isEmpty();
00387
00388 const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
00389 if (list && !list->isEmpty()) {
00390 Q_FOREACH(const KHttpCookie& cookie, *list) {
00391 if (!allDomCookies) {
00392 if (cookieMatches(cookie, domain, fqdn, path, name)) {
00393 putCookie(result, cookie, fields);
00394 break;
00395 }
00396 } else {
00397 putCookie(result, cookie, fields);
00398 }
00399 }
00400 }
00401 return result;
00402 }
00403
00404
00405 QString
00406 KCookieServer::findDOMCookies(const QString &url)
00407 {
00408 return findDOMCookies(url, 0);
00409 }
00410
00411
00412 QString
00413 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
00414 {
00415
00416
00417
00418 KHttpCookieList pendingCookies;
00419 cookiesPending(url, &pendingCookies);
00420
00421 return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
00422 }
00423
00424
00425 void
00426 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
00427 {
00428 addCookies(arg1, arg2, arg3, false);
00429 }
00430
00431
00432 void
00433 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn,
00434 const QString &path, const QString &name)
00435 {
00436 KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn );
00437 if (cookieList && !cookieList->isEmpty()) {
00438 for (KHttpCookieList::iterator cookieIterator = cookieList->begin();
00439 cookieIterator != cookieList->end();
00440 ++cookieIterator ) {
00441 KHttpCookie& cookie = *cookieIterator;
00442 if (cookieMatches(cookie, domain, fqdn, path, name)) {
00443 mCookieJar->eatCookie(cookieIterator);
00444 saveCookieJar();
00445 break;
00446 }
00447 }
00448 }
00449 }
00450
00451
00452 void
00453 KCookieServer::deleteCookiesFromDomain(const QString &domain)
00454 {
00455 mCookieJar->eatCookiesForDomain(domain);
00456 saveCookieJar();
00457 }
00458
00459
00460
00461 void
00462 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
00463 {
00464 deleteSessionCookies(windowId);
00465 }
00466
00467
00468 void
00469 KCookieServer::deleteSessionCookies( qlonglong windowId )
00470 {
00471 mCookieJar->eatSessionCookies( windowId );
00472 saveCookieJar();
00473 }
00474
00475 void
00476 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId)
00477 {
00478 mCookieJar->eatSessionCookies( fqdn, windowId );
00479 saveCookieJar();
00480 }
00481
00482
00483 void
00484 KCookieServer::deleteAllCookies()
00485 {
00486 mCookieJar->eatAllCookies();
00487 saveCookieJar();
00488 }
00489
00490
00491 void
00492 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
00493 {
00494 addCookies(url, cookieHeader, windowId, true);
00495 }
00496
00497
00498 bool
00499 KCookieServer::setDomainAdvice(const QString &url, const QString &advice)
00500 {
00501 QString fqdn;
00502 QString dummy;
00503 if (KCookieJar::parseUrl(url, fqdn, dummy))
00504 {
00505 QStringList domains;
00506 mCookieJar->extractDomains(fqdn, domains);
00507
00508 mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
00509 KCookieJar::strToAdvice(advice));
00510
00511 mCookieJar->saveConfig( mConfig );
00512 return true;
00513 }
00514 return false;
00515 }
00516
00517
00518 QString
00519 KCookieServer::getDomainAdvice(const QString &url)
00520 {
00521 KCookieAdvice advice = KCookieDunno;
00522 QString fqdn;
00523 QString dummy;
00524 if (KCookieJar::parseUrl(url, fqdn, dummy))
00525 {
00526 QStringList domains;
00527 mCookieJar->extractDomains(fqdn, domains);
00528
00529 QStringList::ConstIterator it = domains.constBegin();
00530 while ( (advice == KCookieDunno) && (it != domains.constEnd()) )
00531 {
00532
00533
00534
00535 if ( (*it)[0] == '.' || (*it) == fqdn )
00536 advice = mCookieJar->getDomainAdvice(*it);
00537 ++it;
00538 }
00539 if (advice == KCookieDunno)
00540 advice = mCookieJar->getGlobalAdvice();
00541 }
00542 return KCookieJar::adviceToStr(advice);
00543 }
00544
00545
00546 void
00547 KCookieServer::reloadPolicy()
00548 {
00549 mCookieJar->loadConfig( mConfig, true );
00550 }
00551
00552
00553 void
00554 KCookieServer::shutdown()
00555 {
00556 deleteLater();
00557 }
00558
00559 #include "kcookieserver.moc"
00560