• Skip to content
  • Skip to link menu
KDE 4.6 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    QStringListIterator it (mCookieJar->getDomainList());
00361    while (it.hasNext())
00362    {
00363        // Ignore domains that have policy set for but contain
00364        // no cookies whatsoever...
00365        const QString domain = it.next();
00366        const KHttpCookieList* list =  mCookieJar->getCookieList(domain, "");
00367        if ( list && !list->isEmpty() )
00368           result << domain;
00369    }
00370    return result;
00371 }
00372 
00373 // DBUS function
00374 QStringList
00375 KCookieServer::findCookies(const QList<int> &fields,
00376                            const QString &_domain,
00377                            const QString &fqdn,
00378                            const QString &path,
00379                            const QString &name)
00380 {
00381     QStringList result;
00382     const bool allCookies = name.isEmpty();
00383     const QStringList domainList = _domain.split(QLatin1Char(' '));
00384     
00385     if (allCookies)
00386     {
00387         Q_FOREACH(const QString& domain, domainList)
00388         {
00389             const KHttpCookieList* list =  mCookieJar->getCookieList(domain, fqdn);
00390             if (!list) 
00391                 continue;
00392             Q_FOREACH(const KHttpCookie& cookie, *list)
00393             {
00394                 if (cookie.isExpired())
00395                     continue;
00396                 putCookie(result, cookie, fields);              
00397             }
00398         }
00399     }
00400     else
00401     {
00402         Q_FOREACH(const QString& domain, domainList)
00403         {
00404             const KHttpCookieList* list =  mCookieJar->getCookieList(domain, fqdn);
00405             if (!list) 
00406                 continue;
00407             Q_FOREACH(const KHttpCookie& cookie, *list)
00408             {
00409                 if (cookie.isExpired())
00410                     continue;
00411                 if (cookieMatches(cookie, domain, fqdn, path, name)) 
00412                 {
00413                     putCookie(result, cookie, fields);
00414                     break;
00415                 }
00416             }
00417         }
00418     }
00419     
00420     return result;
00421 }
00422 
00423 // DBUS function
00424 QString
00425 KCookieServer::findDOMCookies(const QString &url)
00426 {
00427    return findDOMCookies(url, 0);
00428 }
00429 
00430 // DBUS function
00431 QString
00432 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
00433 {
00434    // We don't wait for pending cookies because it locks up konqueror
00435    // which can cause a deadlock if it happens to have a popup-menu up.
00436    // Instead we just return pending cookies as if they had been accepted already.
00437    KHttpCookieList pendingCookies;
00438    cookiesPending(url, &pendingCookies);
00439 
00440    return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
00441 }
00442 
00443 // DBUS function
00444 void
00445 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
00446 {
00447    addCookies(arg1, arg2, arg3, false);
00448 }
00449 
00450 // DBUS function
00451 void
00452 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn,
00453                             const QString &path, const QString &name)
00454 {
00455     KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn );
00456     if (cookieList && !cookieList->isEmpty()) {
00457         KHttpCookieList::Iterator itEnd = cookieList->end();
00458         for (KHttpCookieList::Iterator it = cookieList->begin(); it != itEnd; ++it)
00459         {
00460             if (cookieMatches(*it, domain, fqdn, path, name)) {
00461                 mCookieJar->eatCookie(it);
00462                 saveCookieJar();
00463                 break;
00464             }
00465         }
00466     }
00467 }
00468 
00469 // DBUS function
00470 void
00471 KCookieServer::deleteCookiesFromDomain(const QString &domain)
00472 {
00473    mCookieJar->eatCookiesForDomain(domain);
00474    saveCookieJar();
00475 }
00476 
00477 
00478 // Qt function
00479 void
00480 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
00481 {
00482    deleteSessionCookies(windowId);
00483 }
00484 
00485 // DBUS function
00486 void
00487 KCookieServer::deleteSessionCookies( qlonglong windowId )
00488 {
00489   mCookieJar->eatSessionCookies( windowId );
00490   saveCookieJar();
00491 }
00492 
00493 void
00494 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId)
00495 {
00496   mCookieJar->eatSessionCookies( fqdn, windowId );
00497   saveCookieJar();
00498 }
00499 
00500 // DBUS function
00501 void
00502 KCookieServer::deleteAllCookies()
00503 {
00504    mCookieJar->eatAllCookies();
00505    saveCookieJar();
00506 }
00507 
00508 // DBUS function
00509 void
00510 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
00511 {
00512    addCookies(url, cookieHeader, windowId, true);
00513 }
00514 
00515 // DBUS function
00516 bool
00517 KCookieServer::setDomainAdvice(const QString &url, const QString &advice)
00518 {
00519    QString fqdn;
00520    QString dummy;
00521    if (KCookieJar::parseUrl(url, fqdn, dummy))
00522    {
00523       QStringList domains;
00524       mCookieJar->extractDomains(fqdn, domains);
00525 
00526       mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
00527                                   KCookieJar::strToAdvice(advice));
00528       // Save the cookie config if it has changed
00529       mCookieJar->saveConfig( mConfig );
00530       return true;
00531    }
00532    return false;
00533 }
00534 
00535 // DBUS function
00536 QString
00537 KCookieServer::getDomainAdvice(const QString &url)
00538 {
00539    KCookieAdvice advice = KCookieDunno;
00540    QString fqdn;
00541    QString dummy;
00542    if (KCookieJar::parseUrl(url, fqdn, dummy))
00543    {
00544       QStringList domains;
00545       mCookieJar->extractDomains(fqdn, domains);
00546 
00547       QStringListIterator it (domains);
00548       while ( (advice == KCookieDunno) && it.hasNext() )
00549       {
00550          // Always check advice in both ".domain" and "domain". Note
00551          // that we only want to check "domain" if it matches the
00552          // fqdn of the requested URL.
00553         const QString& domain = it.next();
00554          if ( domain.at(0) == '.' || domain == fqdn )
00555             advice = mCookieJar->getDomainAdvice(domain);
00556       }
00557       if (advice == KCookieDunno)
00558          advice = mCookieJar->getGlobalAdvice();
00559    }
00560    return KCookieJar::adviceToStr(advice);
00561 }
00562 
00563 // DBUS function
00564 void
00565 KCookieServer::reloadPolicy()
00566 {
00567    mCookieJar->loadConfig( mConfig, true );
00568 }
00569 
00570 // DBUS function
00571 void
00572 KCookieServer::shutdown()
00573 {
00574    deleteLater();
00575 }
00576 
00577 #include "kcookieserver.moc"
00578 

KIOSlave

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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