• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

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

KDE's Doxygen guidelines are available online.

KIOSlave

Skip menu "KIOSlave"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal