• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 <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 // Cookie field indexes
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    // Stay backwards compatible!
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)); // Remove old kfm cookie file
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     // Check whether 'url' has cookies on the pending list
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     // Collect all pending cookies with the same host as the first pending cookie
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 /*first already done*/; 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     // Save the cookie config if it has changed
00218     mCookieJar->saveConfig( mConfig );
00219 
00220     // Apply the user's choice to all cookies that are currently
00221     // queued for this host (or just the first one, if the user asks for that).
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             // User chose "only those cookies", and this one was added while the dialog was up -> skip
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     // Check if we can handle any request
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 // DBUS function
00334 QString KCookieServer::listCookies(const QString &url)
00335 {
00336     return findCookies(url, 0);
00337 }
00338 
00339 // DBUS function
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(); // Talk to you later :-)
00352    }
00353 
00354    QString cookies = mCookieJar->findCookies(url, false, windowId);
00355    saveCookieJar();
00356    return cookies;
00357 }
00358 
00359 // DBUS function
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        // Ignore domains that have policy set for but contain
00369        // no cookies whatsoever...
00370        const KHttpCookieList* list =  mCookieJar->getCookieList(*domIt, "");
00371        if ( list && !list->isEmpty() )
00372           result << *domIt;
00373    }
00374    return result;
00375 }
00376 
00377 // DBUS function
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 // DBUS function
00405 QString
00406 KCookieServer::findDOMCookies(const QString &url)
00407 {
00408    return findDOMCookies(url, 0);
00409 }
00410 
00411 // DBUS function
00412 QString
00413 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
00414 {
00415    // We don't wait for pending cookies because it locks up konqueror
00416    // which can cause a deadlock if it happens to have a popup-menu up.
00417    // Instead we just return pending cookies as if they had been accepted already.
00418    KHttpCookieList pendingCookies;
00419    cookiesPending(url, &pendingCookies);
00420 
00421    return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
00422 }
00423 
00424 // DBUS function
00425 void
00426 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
00427 {
00428    addCookies(arg1, arg2, arg3, false);
00429 }
00430 
00431 // DBUS function
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 // DBUS function
00452 void
00453 KCookieServer::deleteCookiesFromDomain(const QString &domain)
00454 {
00455    mCookieJar->eatCookiesForDomain(domain);
00456    saveCookieJar();
00457 }
00458 
00459 
00460 // Qt function
00461 void
00462 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
00463 {
00464    deleteSessionCookies(windowId);
00465 }
00466 
00467 // DBUS function
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 // DBUS function
00483 void
00484 KCookieServer::deleteAllCookies()
00485 {
00486    mCookieJar->eatAllCookies();
00487    saveCookieJar();
00488 }
00489 
00490 // DBUS function
00491 void
00492 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
00493 {
00494    addCookies(url, cookieHeader, windowId, true);
00495 }
00496 
00497 // DBUS function
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       // Save the cookie config if it has changed
00511       mCookieJar->saveConfig( mConfig );
00512       return true;
00513    }
00514    return false;
00515 }
00516 
00517 // DBUS function
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          // Always check advice in both ".domain" and "domain". Note
00533          // that we only want to check "domain" if it matches the
00534          // fqdn of the requested URL.
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 // DBUS function
00546 void
00547 KCookieServer::reloadPolicy()
00548 {
00549    mCookieJar->loadConfig( mConfig, true );
00550 }
00551 
00552 // DBUS function
00553 void
00554 KCookieServer::shutdown()
00555 {
00556    deleteLater();
00557 }
00558 
00559 #include "kcookieserver.moc"
00560 

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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