KIOSlave
kcookieserver.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of KDE 00003 00004 Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org) 00005 00006 Permission is hereby granted, free of charge, to any person obtaining a copy 00007 of this software and associated documentation files (the "Software"), to deal 00008 in the Software without restriction, including without limitation the rights 00009 to use, copy, modify, merge, publish, distribute, and/or sell 00010 copies of the Software, and to permit persons to whom the Software is 00011 furnished to do so, subject to the following conditions: 00012 00013 The above copyright notice and this permission notice shall be included in 00014 all copies or substantial portions of the Software. 00015 00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00022 */ 00023 //---------------------------------------------------------------------------- 00024 // 00025 // KDE Cookie Server 00026 00027 #include "kcookieserver.h" 00028 00029 #define SAVE_DELAY 3 // Save after 3 minutes 00030 00031 #include <QtCore/QTimer> 00032 #include <QtCore/QFile> 00033 #include <QtDBus/QtDBus> 00034 00035 #include <kconfig.h> 00036 #include <kdebug.h> 00037 #include <kcmdlineargs.h> 00038 #include <kstandarddirs.h> 00039 #include <kpluginfactory.h> 00040 #include <kpluginloader.h> 00041 #include <kwindowsystem.h> 00042 00043 #include "kcookiejar.h" 00044 #include "kcookiewin.h" 00045 #include "kcookieserveradaptor.h" 00046 00047 #define QL1S(x) QLatin1String(x) 00048 #define QL1C(x) QLatin1Char(x) 00049 00050 K_PLUGIN_FACTORY(KdedCookieServerFactory, 00051 registerPlugin<KCookieServer>(); 00052 ) 00053 K_EXPORT_PLUGIN(KdedCookieServerFactory("kcookiejar")) 00054 00055 // Cookie field indexes 00056 enum CookieDetails { CF_DOMAIN=0, CF_PATH, CF_NAME, CF_HOST, 00057 CF_VALUE, CF_EXPIRE, CF_PROVER, CF_SECURE }; 00058 00059 00060 class CookieRequest { 00061 public: 00062 QDBusMessage reply; 00063 QString url; 00064 bool DOM; 00065 qlonglong windowId; 00066 }; 00067 00068 template class QList<CookieRequest*>; 00069 00070 class RequestList : public QList<CookieRequest*> 00071 { 00072 public: 00073 RequestList() : QList<CookieRequest*>() { } 00074 }; 00075 00076 KCookieServer::KCookieServer(QObject* parent, const QList<QVariant>&) 00077 : KDEDModule(parent) 00078 { 00079 (void)new KCookieServerAdaptor(this); 00080 mCookieJar = new KCookieJar; 00081 mPendingCookies = new KHttpCookieList; 00082 mRequestList = new RequestList; 00083 mAdvicePending = false; 00084 mTimer = new QTimer(); 00085 mTimer->setSingleShot(true); 00086 connect(mTimer, SIGNAL(timeout()), SLOT(slotSave())); 00087 mConfig = new KConfig("kcookiejarrc"); 00088 mCookieJar->loadConfig( mConfig ); 00089 00090 const QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies"); 00091 00092 // Stay backwards compatible! 00093 const QString filenameOld = KStandardDirs::locate("data", "kfm/cookies"); 00094 if (!filenameOld.isEmpty()) 00095 { 00096 mCookieJar->loadCookies( filenameOld ); 00097 if (mCookieJar->saveCookies( filename)) 00098 { 00099 QFile::remove(filenameOld); // Remove old kfm cookie file 00100 } 00101 } 00102 else 00103 { 00104 mCookieJar->loadCookies( filename); 00105 } 00106 connect(this, SIGNAL(windowUnregistered(qlonglong)), 00107 this, SLOT(slotDeleteSessionCookies(qlonglong))); 00108 } 00109 00110 KCookieServer::~KCookieServer() 00111 { 00112 slotSave(); 00113 delete mCookieJar; 00114 delete mTimer; 00115 delete mPendingCookies; 00116 delete mConfig; 00117 } 00118 00119 bool KCookieServer::cookiesPending( const QString &url, KHttpCookieList *cookieList ) 00120 { 00121 QString fqdn; 00122 QString path; 00123 // Check whether 'url' has cookies on the pending list 00124 if (mPendingCookies->isEmpty()) 00125 return false; 00126 if (!KCookieJar::parseUrl(url, fqdn, path)) 00127 return false; 00128 00129 QStringList domains; 00130 mCookieJar->extractDomains(fqdn, domains); 00131 Q_FOREACH(const KHttpCookie& cookie, *mPendingCookies) { 00132 if (cookie.match( fqdn, domains, path)) { 00133 if (!cookieList) 00134 return true; 00135 cookieList->append(cookie); 00136 } 00137 } 00138 if (!cookieList) 00139 return false; 00140 return cookieList->isEmpty(); 00141 } 00142 00143 void KCookieServer::addCookies( const QString &url, const QByteArray &cookieHeader, 00144 qlonglong windowId, bool useDOMFormat ) 00145 { 00146 KHttpCookieList cookieList; 00147 if (useDOMFormat) 00148 cookieList = mCookieJar->makeDOMCookies(url, cookieHeader, windowId); 00149 else 00150 cookieList = mCookieJar->makeCookies(url, cookieHeader, windowId); 00151 00152 checkCookies(&cookieList, windowId); 00153 00154 *mPendingCookies += cookieList; 00155 00156 if (!mAdvicePending) 00157 { 00158 mAdvicePending = true; 00159 while (!mPendingCookies->isEmpty()) 00160 { 00161 checkCookies(0, windowId); 00162 } 00163 mAdvicePending = false; 00164 } 00165 } 00166 00167 void KCookieServer::checkCookies(KHttpCookieList *cookieList) 00168 { 00169 checkCookies(cookieList, 0); 00170 } 00171 00172 void KCookieServer::checkCookies(KHttpCookieList *cookieList, qlonglong windowId) 00173 { 00174 KHttpCookieList *list; 00175 00176 if (cookieList) 00177 list = cookieList; 00178 else 00179 list = mPendingCookies; 00180 00181 QMutableListIterator<KHttpCookie> cookieIterator(*list); 00182 while (cookieIterator.hasNext()) { 00183 KHttpCookie& cookie = cookieIterator.next(); 00184 const KCookieAdvice advice = mCookieJar->cookieAdvice(cookie); 00185 switch(advice) { 00186 case KCookieAccept: 00187 mCookieJar->addCookie(cookie); 00188 cookieIterator.remove(); 00189 break; 00190 case KCookieReject: 00191 cookieIterator.remove(); 00192 break; 00193 default: 00194 break; 00195 } 00196 } 00197 00198 if (cookieList || list->isEmpty()) 00199 return; 00200 00201 // Collect all pending cookies with the same host as the first pending cookie 00202 const KHttpCookie& currentCookie = mPendingCookies->first(); 00203 KHttpCookieList currentList; 00204 currentList.append(currentCookie); 00205 const QString currentHost = currentCookie.host(); 00206 QList<int> shownCookies; shownCookies << 0; 00207 for (int i = 1 /*first already done*/; i < mPendingCookies->count(); ++i) { 00208 const KHttpCookie& cookie = (*mPendingCookies)[i]; 00209 if (cookie.host() == currentHost) { 00210 currentList.append(cookie); 00211 shownCookies << i; 00212 } 00213 } 00214 //kDebug() << shownCookies; 00215 00216 KCookieWin *kw = new KCookieWin( 0L, currentList, 00217 mCookieJar->preferredDefaultPolicy(), 00218 mCookieJar->showCookieDetails() ); 00219 if (windowId > 0) { 00220 #ifndef Q_WS_WIN 00221 KWindowSystem::setMainWindow(kw, static_cast<WId>(windowId)); 00222 #else 00223 KWindowSystem::setMainWindow(kw, (HWND)(long)windowId); 00224 #endif 00225 } 00226 00227 KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie); 00228 delete kw; 00229 // Save the cookie config if it has changed 00230 mCookieJar->saveConfig( mConfig ); 00231 00232 // Apply the user's choice to all cookies that are currently 00233 // queued for this host (or just the first one, if the user asks for that). 00234 QMutableListIterator<KHttpCookie> cookieIterator2(*mPendingCookies); 00235 int pendingCookieIndex = -1; 00236 while (cookieIterator2.hasNext()) { 00237 ++pendingCookieIndex; 00238 KHttpCookie& cookie = cookieIterator2.next(); 00239 if (cookie.host() != currentHost) 00240 continue; 00241 if (mCookieJar->preferredDefaultPolicy() == KCookieJar::ApplyToShownCookiesOnly 00242 && !shownCookies.contains(pendingCookieIndex)) { 00243 // User chose "only those cookies", and this one was added while the dialog was up -> skip 00244 break; 00245 } 00246 switch(userAdvice) { 00247 case KCookieAccept: 00248 mCookieJar->addCookie(cookie); 00249 cookieIterator2.remove(); 00250 break; 00251 00252 case KCookieReject: 00253 cookieIterator2.remove(); 00254 break; 00255 00256 default: 00257 kWarning() << "userAdvice not accept or reject, this should never happen!"; 00258 break; 00259 } 00260 } 00261 00262 // Check if we can handle any request 00263 QMutableListIterator<CookieRequest *> requestIterator(*mRequestList); 00264 while (requestIterator.hasNext()) { 00265 CookieRequest *request = requestIterator.next(); 00266 if (!cookiesPending(request->url)) { 00267 const QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId); 00268 00269 QDBusConnection::sessionBus().send(request->reply.createReply(res)); 00270 delete request; 00271 requestIterator.remove(); 00272 } 00273 } 00274 00275 saveCookieJar(); 00276 } 00277 00278 void KCookieServer::slotSave() 00279 { 00280 if (mCookieJar->changed()) 00281 { 00282 QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies"); 00283 mCookieJar->saveCookies(filename); 00284 } 00285 } 00286 00287 void KCookieServer::saveCookieJar() 00288 { 00289 if( mTimer->isActive() ) 00290 return; 00291 00292 mTimer->start( 1000*60*SAVE_DELAY ); 00293 } 00294 00295 void KCookieServer::putCookie( QStringList& out, const KHttpCookie& cookie, 00296 const QList<int>& fields ) 00297 { 00298 foreach ( int i, fields ) { 00299 switch(i) 00300 { 00301 case CF_DOMAIN : 00302 out << cookie.domain(); 00303 break; 00304 case CF_NAME : 00305 out << cookie.name(); 00306 break; 00307 case CF_PATH : 00308 out << cookie.path(); 00309 break; 00310 case CF_HOST : 00311 out << cookie.host(); 00312 break; 00313 case CF_VALUE : 00314 out << cookie.value(); 00315 break; 00316 case CF_EXPIRE : 00317 out << QString::number(cookie.expireDate()); 00318 break; 00319 case CF_PROVER : 00320 out << QString::number(cookie.protocolVersion()); 00321 break; 00322 case CF_SECURE : 00323 out << QString::number(cookie.isSecure() ? 1 : 0); 00324 break; 00325 default : 00326 out << QString(); 00327 } 00328 } 00329 } 00330 00331 bool KCookieServer::cookieMatches(const KHttpCookie& c, 00332 const QString &domain, const QString &fqdn, 00333 const QString &path, const QString &name) 00334 { 00335 const bool hasDomain = !domain.isEmpty(); 00336 return (((hasDomain && c.domain() == domain) || fqdn == c.host()) && 00337 (c.path() == path) && (c.name() == name) && 00338 (!c.isExpired())); 00339 } 00340 00341 00342 // DBUS function 00343 QString KCookieServer::listCookies(const QString &url) 00344 { 00345 return findCookies(url, 0); 00346 } 00347 00348 // DBUS function 00349 QString KCookieServer::findCookies(const QString &url, qlonglong windowId) 00350 { 00351 if (cookiesPending(url)) 00352 { 00353 CookieRequest *request = new CookieRequest; 00354 message().setDelayedReply(true); 00355 request->reply = message(); 00356 request->url = url; 00357 request->DOM = false; 00358 request->windowId = windowId; 00359 mRequestList->append( request ); 00360 return QString(); // Talk to you later :-) 00361 } 00362 00363 QString cookies = mCookieJar->findCookies(url, false, windowId); 00364 saveCookieJar(); 00365 return cookies; 00366 } 00367 00368 // DBUS function 00369 QStringList 00370 KCookieServer::findDomains() 00371 { 00372 QStringList result; 00373 Q_FOREACH(const QString& domain, mCookieJar->getDomainList()) 00374 { 00375 // Ignore domains that have policy set for but contain 00376 // no cookies whatsoever... 00377 const KHttpCookieList* list = mCookieJar->getCookieList(domain, ""); 00378 if ( list && !list->isEmpty() ) 00379 result << domain; 00380 } 00381 return result; 00382 } 00383 00384 // DBUS function 00385 QStringList 00386 KCookieServer::findCookies(const QList<int> &fields, 00387 const QString &_domain, 00388 const QString &fqdn, 00389 const QString &path, 00390 const QString &name) 00391 { 00392 QStringList result; 00393 const bool allCookies = name.isEmpty(); 00394 const QStringList domainList = _domain.split(QLatin1Char(' ')); 00395 00396 if (allCookies) 00397 { 00398 Q_FOREACH(const QString& domain, domainList) 00399 { 00400 const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn); 00401 if (!list) 00402 continue; 00403 Q_FOREACH(const KHttpCookie& cookie, *list) 00404 { 00405 if (cookie.isExpired()) 00406 continue; 00407 putCookie(result, cookie, fields); 00408 } 00409 } 00410 } 00411 else 00412 { 00413 Q_FOREACH(const QString& domain, domainList) 00414 { 00415 const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn); 00416 if (!list) 00417 continue; 00418 Q_FOREACH(const KHttpCookie& cookie, *list) 00419 { 00420 if (cookie.isExpired()) 00421 continue; 00422 if (cookieMatches(cookie, domain, fqdn, path, name)) 00423 { 00424 putCookie(result, cookie, fields); 00425 break; 00426 } 00427 } 00428 } 00429 } 00430 00431 return result; 00432 } 00433 00434 // DBUS function 00435 QString 00436 KCookieServer::findDOMCookies(const QString &url) 00437 { 00438 return findDOMCookies(url, 0); 00439 } 00440 00441 // DBUS function 00442 QString 00443 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId) 00444 { 00445 // We don't wait for pending cookies because it locks up konqueror 00446 // which can cause a deadlock if it happens to have a popup-menu up. 00447 // Instead we just return pending cookies as if they had been accepted already. 00448 KHttpCookieList pendingCookies; 00449 cookiesPending(url, &pendingCookies); 00450 00451 return mCookieJar->findCookies(url, true, windowId, &pendingCookies); 00452 } 00453 00454 // DBUS function 00455 void 00456 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3) 00457 { 00458 addCookies(arg1, arg2, arg3, false); 00459 } 00460 00461 // DBUS function 00462 void 00463 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn, 00464 const QString &path, const QString &name) 00465 { 00466 KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn ); 00467 if (cookieList && !cookieList->isEmpty()) { 00468 KHttpCookieList::Iterator itEnd = cookieList->end(); 00469 for (KHttpCookieList::Iterator it = cookieList->begin(); it != itEnd; ++it) 00470 { 00471 if (cookieMatches(*it, domain, fqdn, path, name)) { 00472 mCookieJar->eatCookie(it); 00473 saveCookieJar(); 00474 break; 00475 } 00476 } 00477 } 00478 } 00479 00480 // DBUS function 00481 void 00482 KCookieServer::deleteCookiesFromDomain(const QString &domain) 00483 { 00484 mCookieJar->eatCookiesForDomain(domain); 00485 saveCookieJar(); 00486 } 00487 00488 00489 // Qt function 00490 void 00491 KCookieServer::slotDeleteSessionCookies( qlonglong windowId ) 00492 { 00493 deleteSessionCookies(windowId); 00494 } 00495 00496 // DBUS function 00497 void 00498 KCookieServer::deleteSessionCookies( qlonglong windowId ) 00499 { 00500 mCookieJar->eatSessionCookies( windowId ); 00501 saveCookieJar(); 00502 } 00503 00504 void 00505 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId) 00506 { 00507 mCookieJar->eatSessionCookies( fqdn, windowId ); 00508 saveCookieJar(); 00509 } 00510 00511 // DBUS function 00512 void 00513 KCookieServer::deleteAllCookies() 00514 { 00515 mCookieJar->eatAllCookies(); 00516 saveCookieJar(); 00517 } 00518 00519 // DBUS function 00520 void 00521 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId) 00522 { 00523 addCookies(url, cookieHeader, windowId, true); 00524 } 00525 00526 // DBUS function 00527 bool 00528 KCookieServer::setDomainAdvice(const QString &url, const QString &advice) 00529 { 00530 QString fqdn; 00531 QString dummy; 00532 if (KCookieJar::parseUrl(url, fqdn, dummy)) 00533 { 00534 QStringList domains; 00535 mCookieJar->extractDomains(fqdn, domains); 00536 00537 mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0], 00538 KCookieJar::strToAdvice(advice)); 00539 // Save the cookie config if it has changed 00540 mCookieJar->saveConfig( mConfig ); 00541 return true; 00542 } 00543 return false; 00544 } 00545 00546 // DBUS function 00547 QString 00548 KCookieServer::getDomainAdvice(const QString &url) 00549 { 00550 KCookieAdvice advice = KCookieDunno; 00551 QString fqdn; 00552 QString dummy; 00553 if (KCookieJar::parseUrl(url, fqdn, dummy)) 00554 { 00555 QStringList domains; 00556 mCookieJar->extractDomains(fqdn, domains); 00557 00558 QStringListIterator it (domains); 00559 while ( (advice == KCookieDunno) && it.hasNext() ) 00560 { 00561 // Always check advice in both ".domain" and "domain". Note 00562 // that we only want to check "domain" if it matches the 00563 // fqdn of the requested URL. 00564 const QString& domain = it.next(); 00565 if ( domain.at(0) == '.' || domain == fqdn ) 00566 advice = mCookieJar->getDomainAdvice(domain); 00567 } 00568 if (advice == KCookieDunno) 00569 advice = mCookieJar->getGlobalAdvice(); 00570 } 00571 return KCookieJar::adviceToStr(advice); 00572 } 00573 00574 // DBUS function 00575 void 00576 KCookieServer::reloadPolicy() 00577 { 00578 mCookieJar->loadConfig( mConfig, true ); 00579 } 00580 00581 // DBUS function 00582 void 00583 KCookieServer::shutdown() 00584 { 00585 deleteLater(); 00586 } 00587 00588 #include "kcookieserver.moc" 00589
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:57:54 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:57:54 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.