• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • 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 
00040 #include "kcookiejar.h"
00041 #include "kcookiewin.h"
00042 #include "kcookieserveradaptor.h"
00043 #include <kpluginfactory.h>
00044 #include <kpluginloader.h>
00045 
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);
00153 
00154     *mPendingCookies += cookieList;
00155 
00156     if (!mAdvicePending)
00157     {
00158        mAdvicePending = true;
00159        while (!mPendingCookies->isEmpty())
00160        {
00161           checkCookies(0);
00162        }
00163        mAdvicePending = false;
00164     }
00165 }
00166 
00167 void KCookieServer::checkCookies(KHttpCookieList *cookieList)
00168 {
00169     KHttpCookieList *list;
00170 
00171     if (cookieList)
00172        list = cookieList;
00173     else
00174        list = mPendingCookies;
00175 
00176     QMutableListIterator<KHttpCookie> cookieIterator(*list);
00177     while (cookieIterator.hasNext()) {
00178         KHttpCookie& cookie = cookieIterator.next();
00179         const KCookieAdvice advice = mCookieJar->cookieAdvice(cookie);
00180         switch(advice) {
00181         case KCookieAccept:
00182             mCookieJar->addCookie(cookie);
00183             cookieIterator.remove();
00184             break;
00185         case KCookieReject:
00186             cookieIterator.remove();
00187             break;
00188         default:
00189             break;
00190         }
00191     }
00192 
00193     if (cookieList || list->isEmpty())
00194        return;
00195 
00196     // Collect all pending cookies with the same host as the first pending cookie
00197     const KHttpCookie& currentCookie = mPendingCookies->first();
00198     KHttpCookieList currentList;
00199     currentList.append(currentCookie);
00200     const QString currentHost = currentCookie.host();
00201     QList<int> shownCookies; shownCookies << 0;
00202     for (int i = 1 /*first already done*/; i < mPendingCookies->count(); ++i) {
00203         const KHttpCookie& cookie = (*mPendingCookies)[i];
00204         if (cookie.host() == currentHost) {
00205             currentList.append(cookie);
00206             shownCookies << i;
00207         }
00208     }
00209     //kDebug() << shownCookies;
00210 
00211     KCookieWin *kw = new KCookieWin( 0L, currentList,
00212                                      mCookieJar->preferredDefaultPolicy(),
00213                                      mCookieJar->showCookieDetails() );
00214     KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
00215     delete kw;
00216     // Save the cookie config if it has changed
00217     mCookieJar->saveConfig( mConfig );
00218 
00219     // Apply the user's choice to all cookies that are currently
00220     // queued for this host (or just the first one, if the user asks for that).
00221     QMutableListIterator<KHttpCookie> cookieIterator2(*mPendingCookies);
00222     int pendingCookieIndex = -1;
00223     while (cookieIterator2.hasNext()) {
00224         ++pendingCookieIndex;
00225         KHttpCookie& cookie = cookieIterator2.next();
00226         if (cookie.host() != currentHost)
00227             continue;
00228         if (mCookieJar->preferredDefaultPolicy() == KCookieJar::ApplyToShownCookiesOnly
00229             && !shownCookies.contains(pendingCookieIndex)) {
00230             // User chose "only those cookies", and this one was added while the dialog was up -> skip
00231             break;
00232         }
00233         switch(userAdvice) {
00234            case KCookieAccept:
00235                mCookieJar->addCookie(cookie);
00236                cookieIterator2.remove();
00237                break;
00238 
00239            case KCookieReject:
00240                cookieIterator2.remove();
00241                break;
00242 
00243            default:
00244                kWarning() << "userAdvice not accept or reject, this should never happen!";
00245                break;
00246         }
00247     }
00248 
00249     // Check if we can handle any request
00250     QMutableListIterator<CookieRequest *> requestIterator(*mRequestList);
00251     while (requestIterator.hasNext()) {
00252         CookieRequest *request = requestIterator.next();
00253         if (!cookiesPending(request->url)) {
00254            const QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId);
00255 
00256            QDBusConnection::sessionBus().send(request->reply.createReply(res));
00257            delete request;
00258            requestIterator.remove();
00259         }
00260     }
00261 
00262     saveCookieJar();
00263 }
00264 
00265 void KCookieServer::slotSave()
00266 {
00267    if (mCookieJar->changed())
00268    {
00269       QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies");
00270       mCookieJar->saveCookies(filename);
00271    }
00272 }
00273 
00274 void KCookieServer::saveCookieJar()
00275 {
00276     if( mTimer->isActive() )
00277         return;
00278 
00279     mTimer->start( 1000*60*SAVE_DELAY );
00280 }
00281 
00282 void KCookieServer::putCookie( QStringList& out, const KHttpCookie& cookie,
00283                                const QList<int>& fields )
00284 {
00285     foreach ( int i, fields ) {
00286        switch(i)
00287         {
00288          case CF_DOMAIN :
00289             out << cookie.domain();
00290             break;
00291          case CF_NAME :
00292             out << cookie.name();
00293             break;
00294          case CF_PATH :
00295             out << cookie.path();
00296             break;
00297          case CF_HOST :
00298             out << cookie.host();
00299             break;
00300          case CF_VALUE :
00301             out << cookie.value();
00302             break;
00303          case CF_EXPIRE :
00304             out << QString::number(cookie.expireDate());
00305             break;
00306          case CF_PROVER :
00307             out << QString::number(cookie.protocolVersion());
00308             break;
00309          case CF_SECURE :
00310             out << QString::number(cookie.isSecure() ? 1 : 0);
00311             break;
00312          default :
00313             out << QString();
00314         }
00315     }
00316 }
00317 
00318 bool KCookieServer::cookieMatches(const KHttpCookie& c,
00319                                   const QString &domain, const QString &fqdn,
00320                                   const QString &path, const QString &name)
00321 {
00322     const bool hasDomain = !domain.isEmpty();
00323     return (((hasDomain && c.domain() == domain) || fqdn == c.host()) &&
00324             (c.path() == path) && (c.name() == name) &&
00325             (!c.isExpired()));
00326 }
00327 
00328 
00329 // DBUS function
00330 QString KCookieServer::listCookies(const QString &url)
00331 {
00332     return findCookies(url, 0);
00333 }
00334 
00335 // DBUS function
00336 QString KCookieServer::findCookies(const QString &url, qlonglong windowId)
00337 {
00338    if (cookiesPending(url))
00339    {
00340       CookieRequest *request = new CookieRequest;
00341       message().setDelayedReply(true);
00342       request->reply = message();
00343       request->url = url;
00344       request->DOM = false;
00345       request->windowId = windowId;
00346       mRequestList->append( request );
00347       return QString(); // Talk to you later :-)
00348    }
00349 
00350    QString cookies = mCookieJar->findCookies(url, false, windowId);
00351    saveCookieJar();
00352    return cookies;
00353 }
00354 
00355 // DBUS function
00356 QStringList
00357 KCookieServer::findDomains()
00358 {
00359    QStringList result;
00360    Q_FOREACH(const QString& domain, mCookieJar->getDomainList())
00361    {
00362        // Ignore domains that have policy set for but contain
00363        // no cookies whatsoever...
00364        const KHttpCookieList* list =  mCookieJar->getCookieList(domain, "");
00365        if ( list && !list->isEmpty() )
00366           result << domain;
00367    }
00368    return result;
00369 }
00370 
00371 // DBUS function
00372 QStringList
00373 KCookieServer::findCookies(const QList<int> &fields,
00374                            const QString &_domain,
00375                            const QString &fqdn,
00376                            const QString &path,
00377                            const QString &name)
00378 {
00379     QStringList result;
00380     const bool allCookies = name.isEmpty();
00381     const QStringList domainList = _domain.split(QLatin1Char(' '));
00382     
00383     if (allCookies)
00384     {
00385         Q_FOREACH(const QString& domain, domainList)
00386         {
00387             const KHttpCookieList* list =  mCookieJar->getCookieList(domain, fqdn);
00388             if (!list) 
00389                 continue;
00390             Q_FOREACH(const KHttpCookie& cookie, *list)
00391             {
00392                 if (cookie.isExpired())
00393                     continue;
00394                 putCookie(result, cookie, fields);              
00395             }
00396         }
00397     }
00398     else
00399     {
00400         Q_FOREACH(const QString& domain, domainList)
00401         {
00402             const KHttpCookieList* list =  mCookieJar->getCookieList(domain, fqdn);
00403             if (!list) 
00404                 continue;
00405             Q_FOREACH(const KHttpCookie& cookie, *list)
00406             {
00407                 if (cookie.isExpired())
00408                     continue;
00409                 if (cookieMatches(cookie, domain, fqdn, path, name)) 
00410                 {
00411                     putCookie(result, cookie, fields);
00412                     break;
00413                 }
00414             }
00415         }
00416     }
00417     
00418     return result;
00419 }
00420 
00421 // DBUS function
00422 QString
00423 KCookieServer::findDOMCookies(const QString &url)
00424 {
00425    return findDOMCookies(url, 0);
00426 }
00427 
00428 // DBUS function
00429 QString
00430 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
00431 {
00432    // We don't wait for pending cookies because it locks up konqueror
00433    // which can cause a deadlock if it happens to have a popup-menu up.
00434    // Instead we just return pending cookies as if they had been accepted already.
00435    KHttpCookieList pendingCookies;
00436    cookiesPending(url, &pendingCookies);
00437 
00438    return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
00439 }
00440 
00441 // DBUS function
00442 void
00443 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
00444 {
00445    addCookies(arg1, arg2, arg3, false);
00446 }
00447 
00448 // DBUS function
00449 void
00450 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn,
00451                             const QString &path, const QString &name)
00452 {
00453     KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn );
00454     if (cookieList && !cookieList->isEmpty()) {
00455         KHttpCookieList::Iterator itEnd = cookieList->end();
00456         for (KHttpCookieList::Iterator it = cookieList->begin(); it != itEnd; ++it)
00457         {
00458             if (cookieMatches(*it, domain, fqdn, path, name)) {
00459                 mCookieJar->eatCookie(it);
00460                 saveCookieJar();
00461                 break;
00462             }
00463         }
00464     }
00465 }
00466 
00467 // DBUS function
00468 void
00469 KCookieServer::deleteCookiesFromDomain(const QString &domain)
00470 {
00471    mCookieJar->eatCookiesForDomain(domain);
00472    saveCookieJar();
00473 }
00474 
00475 
00476 // Qt function
00477 void
00478 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
00479 {
00480    deleteSessionCookies(windowId);
00481 }
00482 
00483 // DBUS function
00484 void
00485 KCookieServer::deleteSessionCookies( qlonglong windowId )
00486 {
00487   mCookieJar->eatSessionCookies( windowId );
00488   saveCookieJar();
00489 }
00490 
00491 void
00492 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId)
00493 {
00494   mCookieJar->eatSessionCookies( fqdn, windowId );
00495   saveCookieJar();
00496 }
00497 
00498 // DBUS function
00499 void
00500 KCookieServer::deleteAllCookies()
00501 {
00502    mCookieJar->eatAllCookies();
00503    saveCookieJar();
00504 }
00505 
00506 // DBUS function
00507 void
00508 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
00509 {
00510    addCookies(url, cookieHeader, windowId, true);
00511 }
00512 
00513 // DBUS function
00514 bool
00515 KCookieServer::setDomainAdvice(const QString &url, const QString &advice)
00516 {
00517    QString fqdn;
00518    QString dummy;
00519    if (KCookieJar::parseUrl(url, fqdn, dummy))
00520    {
00521       QStringList domains;
00522       mCookieJar->extractDomains(fqdn, domains);
00523 
00524       mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
00525                                   KCookieJar::strToAdvice(advice));
00526       // Save the cookie config if it has changed
00527       mCookieJar->saveConfig( mConfig );
00528       return true;
00529    }
00530    return false;
00531 }
00532 
00533 // DBUS function
00534 QString
00535 KCookieServer::getDomainAdvice(const QString &url)
00536 {
00537    KCookieAdvice advice = KCookieDunno;
00538    QString fqdn;
00539    QString dummy;
00540    if (KCookieJar::parseUrl(url, fqdn, dummy))
00541    {
00542       QStringList domains;
00543       mCookieJar->extractDomains(fqdn, domains);
00544 
00545       QStringListIterator it (domains);
00546       while ( (advice == KCookieDunno) && it.hasNext() )
00547       {
00548          // Always check advice in both ".domain" and "domain". Note
00549          // that we only want to check "domain" if it matches the
00550          // fqdn of the requested URL.
00551         const QString& domain = it.next();
00552          if ( domain.at(0) == '.' || domain == fqdn )
00553             advice = mCookieJar->getDomainAdvice(domain);
00554       }
00555       if (advice == KCookieDunno)
00556          advice = mCookieJar->getGlobalAdvice();
00557    }
00558    return KCookieJar::adviceToStr(advice);
00559 }
00560 
00561 // DBUS function
00562 void
00563 KCookieServer::reloadPolicy()
00564 {
00565    mCookieJar->loadConfig( mConfig, true );
00566 }
00567 
00568 // DBUS function
00569 void
00570 KCookieServer::shutdown()
00571 {
00572    deleteLater();
00573 }
00574 
00575 #include "kcookieserver.moc"
00576 

KIOSlave

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

kdelibs

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal