summaryrefslogtreecommitdiffstats
path: root/kioslave/http/kcookiejar/kcookieserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/http/kcookiejar/kcookieserver.cpp')
-rw-r--r--kioslave/http/kcookiejar/kcookieserver.cpp606
1 files changed, 606 insertions, 0 deletions
diff --git a/kioslave/http/kcookiejar/kcookieserver.cpp b/kioslave/http/kcookiejar/kcookieserver.cpp
new file mode 100644
index 000000000..365f15e79
--- /dev/null
+++ b/kioslave/http/kcookiejar/kcookieserver.cpp
@@ -0,0 +1,606 @@
+/*
+This file is part of KDE
+
+ Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+//----------------------------------------------------------------------------
+//
+// KDE Cookie Server
+// $Id$
+
+#define SAVE_DELAY 3 // Save after 3 minutes
+
+#include <unistd.h>
+
+#include <qtimer.h>
+#include <qptrlist.h>
+#include <qfile.h>
+
+#include <dcopclient.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kstandarddirs.h>
+
+#include "kcookiejar.h"
+#include "kcookiewin.h"
+#include "kcookieserver.h"
+
+extern "C" {
+ KDE_EXPORT KDEDModule *create_kcookiejar(const QCString &name)
+ {
+ return new KCookieServer(name);
+ }
+}
+
+
+// Cookie field indexes
+enum CookieDetails { CF_DOMAIN=0, CF_PATH, CF_NAME, CF_HOST,
+ CF_VALUE, CF_EXPIRE, CF_PROVER, CF_SECURE };
+
+
+class CookieRequest {
+public:
+ DCOPClient *client;
+ DCOPClientTransaction *transaction;
+ QString url;
+ bool DOM;
+ long windowId;
+};
+
+template class QPtrList<CookieRequest>;
+
+class RequestList : public QPtrList<CookieRequest>
+{
+public:
+ RequestList() : QPtrList<CookieRequest>() { }
+};
+
+KCookieServer::KCookieServer(const QCString &name)
+ :KDEDModule(name)
+{
+ mOldCookieServer = new DCOPClient(); // backwards compatibility.
+ mOldCookieServer->registerAs("kcookiejar", false);
+ mOldCookieServer->setDaemonMode( true );
+ mCookieJar = new KCookieJar;
+ mPendingCookies = new KHttpCookieList;
+ mPendingCookies->setAutoDelete(true);
+ mRequestList = new RequestList;
+ mAdvicePending = false;
+ mTimer = new QTimer();
+ connect( mTimer, SIGNAL( timeout()), SLOT( slotSave()));
+ mConfig = new KConfig("kcookiejarrc");
+ mCookieJar->loadConfig( mConfig );
+
+ QString filename = locateLocal("data", "kcookiejar/cookies");
+
+ // Stay backwards compatible!
+ QString filenameOld = locate("data", "kfm/cookies");
+ if (!filenameOld.isEmpty())
+ {
+ mCookieJar->loadCookies( filenameOld );
+ if (mCookieJar->saveCookies( filename))
+ {
+ unlink(QFile::encodeName(filenameOld)); // Remove old kfm cookie file
+ }
+ }
+ else
+ {
+ mCookieJar->loadCookies( filename);
+ }
+ connect(this, SIGNAL(windowUnregistered(long)),
+ this, SLOT(slotDeleteSessionCookies(long)));
+}
+
+KCookieServer::~KCookieServer()
+{
+ if (mCookieJar->changed())
+ slotSave();
+ delete mOldCookieServer;
+ delete mCookieJar;
+ delete mTimer;
+ delete mPendingCookies;
+ delete mConfig;
+}
+
+bool KCookieServer::cookiesPending( const QString &url, KHttpCookieList *cookieList )
+{
+ QString fqdn;
+ QStringList domains;
+ QString path;
+ // Check whether 'url' has cookies on the pending list
+ if (mPendingCookies->isEmpty())
+ return false;
+ if (!KCookieJar::parseURL(url, fqdn, path))
+ return false;
+
+ mCookieJar->extractDomains( fqdn, domains );
+ for( KHttpCookie *cookie = mPendingCookies->first();
+ cookie != 0L;
+ cookie = mPendingCookies->next())
+ {
+ if (cookie->match( fqdn, domains, path))
+ {
+ if (!cookieList)
+ return true;
+ cookieList->append(cookie);
+ }
+ }
+ if (!cookieList)
+ return false;
+ return cookieList->isEmpty();
+}
+
+void KCookieServer::addCookies( const QString &url, const QCString &cookieHeader,
+ long windowId, bool useDOMFormat )
+{
+ KHttpCookieList cookieList;
+ if (useDOMFormat)
+ cookieList = mCookieJar->makeDOMCookies(url, cookieHeader, windowId);
+ else
+ cookieList = mCookieJar->makeCookies(url, cookieHeader, windowId);
+
+ checkCookies(&cookieList);
+
+ for(KHttpCookiePtr cookie = cookieList.first(); cookie; cookie = cookieList.first())
+ mPendingCookies->append(cookieList.take());
+
+ if (!mAdvicePending)
+ {
+ mAdvicePending = true;
+ while (!mPendingCookies->isEmpty())
+ {
+ checkCookies(0);
+ }
+ mAdvicePending = false;
+ }
+}
+
+void KCookieServer::checkCookies( KHttpCookieList *cookieList)
+{
+ KHttpCookieList *list;
+
+ if (cookieList)
+ list = cookieList;
+ else
+ list = mPendingCookies;
+
+ KHttpCookiePtr cookie = list->first();
+ while (cookie)
+ {
+ kdDebug(7104) << "checkCookies: Asking cookie advice for " << cookie->host() << endl;
+ KCookieAdvice advice = mCookieJar->cookieAdvice(cookie);
+ switch(advice)
+ {
+ case KCookieAccept:
+ list->take();
+ mCookieJar->addCookie(cookie);
+ cookie = list->current();
+ break;
+
+ case KCookieReject:
+ list->take();
+ delete cookie;
+ cookie = list->current();
+ break;
+
+ default:
+ cookie = list->next();
+ break;
+ }
+ }
+
+ if (cookieList || list->isEmpty())
+ return;
+
+ KHttpCookiePtr currentCookie = mPendingCookies->first();
+
+ KHttpCookieList currentList;
+ currentList.append(currentCookie);
+ QString currentHost = currentCookie->host();
+
+ cookie = mPendingCookies->next();
+ while (cookie)
+ {
+ if (cookie->host() == currentHost)
+ {
+ currentList.append(cookie);
+ }
+ cookie = mPendingCookies->next();
+ }
+
+ KCookieWin *kw = new KCookieWin( 0L, currentList,
+ mCookieJar->preferredDefaultPolicy(),
+ mCookieJar->showCookieDetails() );
+ KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
+ delete kw;
+ // Save the cookie config if it has changed
+ mCookieJar->saveConfig( mConfig );
+
+ // Apply the user's choice to all cookies that are currently
+ // queued for this host.
+ cookie = mPendingCookies->first();
+ while (cookie)
+ {
+ if (cookie->host() == currentHost)
+ {
+ switch(userAdvice)
+ {
+ case KCookieAccept:
+ mPendingCookies->take();
+ mCookieJar->addCookie(cookie);
+ cookie = mPendingCookies->current();
+ break;
+
+ case KCookieReject:
+ mPendingCookies->take();
+ delete cookie;
+ cookie = mPendingCookies->current();
+ break;
+
+ default:
+ qWarning(__FILE__":%d Problem!", __LINE__);
+ cookie = mPendingCookies->next();
+ break;
+ }
+ }
+ else
+ {
+ cookie = mPendingCookies->next();
+ }
+ }
+
+
+ // Check if we can handle any request
+ for ( CookieRequest *request = mRequestList->first(); request;)
+ {
+ if (!cookiesPending( request->url ))
+ {
+ QCString replyType;
+ QByteArray replyData;
+ QString res = mCookieJar->findCookies( request->url, request->DOM, request->windowId );
+
+ QDataStream stream2(replyData, IO_WriteOnly);
+ stream2 << res;
+ replyType = "QString";
+ request->client->endTransaction( request->transaction,
+ replyType, replyData);
+ CookieRequest *tmp = request;
+ request = mRequestList->next();
+ mRequestList->removeRef( tmp );
+ delete tmp;
+ }
+ else
+ {
+ request = mRequestList->next();
+ }
+ }
+ if (mCookieJar->changed())
+ saveCookieJar();
+}
+
+void KCookieServer::slotSave()
+{
+ QString filename = locateLocal("data", "kcookiejar/cookies");
+ mCookieJar->saveCookies(filename);
+}
+
+void KCookieServer::saveCookieJar()
+{
+ if( mTimer->isActive() )
+ return;
+
+ mTimer->start( 1000*60*SAVE_DELAY, true );
+}
+
+void KCookieServer::putCookie( QStringList& out, KHttpCookie *cookie,
+ const QValueList<int>& fields )
+{
+ QValueList<int>::ConstIterator i = fields.begin();
+ for ( ; i != fields.end(); ++i )
+ {
+ switch(*i)
+ {
+ case CF_DOMAIN :
+ out << cookie->domain();
+ break;
+ case CF_NAME :
+ out << cookie->name();
+ break;
+ case CF_PATH :
+ out << cookie->path();
+ break;
+ case CF_HOST :
+ out << cookie->host();
+ break;
+ case CF_VALUE :
+ out << cookie->value();
+ break;
+ case CF_EXPIRE :
+ out << QString::number(cookie->expireDate());
+ break;
+ case CF_PROVER :
+ out << QString::number(cookie->protocolVersion());
+ break;
+ case CF_SECURE :
+ out << QString::number( cookie->isSecure() ? 1 : 0 );
+ break;
+ default :
+ out << QString::null;
+ }
+ }
+}
+
+bool KCookieServer::cookieMatches( KHttpCookiePtr c,
+ QString domain, QString fqdn,
+ QString path, QString name )
+{
+ if( c )
+ {
+ bool hasDomain = !domain.isEmpty();
+ return
+ ((hasDomain && c->domain() == domain) ||
+ fqdn == c->host()) &&
+ (c->path() == path) &&
+ (c->name() == name) &&
+ (!c->isExpired(time(0)));
+ }
+ return false;
+}
+
+// DCOP function
+QString
+KCookieServer::findCookies(QString url)
+{
+ return findCookies(url, 0);
+}
+
+// DCOP function
+QString
+KCookieServer::findCookies(QString url, long windowId)
+{
+ if (cookiesPending(url))
+ {
+ CookieRequest *request = new CookieRequest;
+ request->client = callingDcopClient();
+ request->transaction = request->client->beginTransaction();
+ request->url = url;
+ request->DOM = false;
+ request->windowId = windowId;
+ mRequestList->append( request );
+ return QString::null; // Talk to you later :-)
+ }
+
+ QString cookies = mCookieJar->findCookies(url, false, windowId);
+
+ if (mCookieJar->changed())
+ saveCookieJar();
+
+ return cookies;
+}
+
+// DCOP function
+QStringList
+KCookieServer::findDomains()
+{
+ QStringList result;
+ const QStringList domains = mCookieJar->getDomainList();
+ for ( QStringList::ConstIterator domIt = domains.begin();
+ domIt != domains.end(); ++domIt )
+ {
+ // Ignore domains that have policy set for but contain
+ // no cookies whatsoever...
+ const KHttpCookieList* list = mCookieJar->getCookieList(*domIt, "");
+ if ( list && !list->isEmpty() )
+ result << *domIt;
+ }
+ return result;
+}
+
+// DCOP function
+QStringList
+KCookieServer::findCookies(QValueList<int> fields,
+ QString domain,
+ QString fqdn,
+ QString path,
+ QString name)
+{
+ QStringList result;
+ bool allDomCookies = name.isEmpty();
+
+ const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
+ if ( list && !list->isEmpty() )
+ {
+ QPtrListIterator<KHttpCookie>it( *list );
+ for ( ; it.current(); ++it )
+ {
+ if ( !allDomCookies )
+ {
+ if ( cookieMatches(it.current(), domain, fqdn, path, name) )
+ {
+ putCookie(result, it.current(), fields);
+ break;
+ }
+ }
+ else
+ putCookie(result, it.current(), fields);
+ }
+ }
+ return result;
+}
+
+// DCOP function
+QString
+KCookieServer::findDOMCookies(QString url)
+{
+ return findDOMCookies(url, 0);
+}
+
+// DCOP function
+QString
+KCookieServer::findDOMCookies(QString url, long windowId)
+{
+ // We don't wait for pending cookies because it locks up konqueror
+ // which can cause a deadlock if it happens to have a popup-menu up.
+ // Instead we just return pending cookies as if they had been accepted already.
+ KHttpCookieList pendingCookies;
+ cookiesPending(url, &pendingCookies);
+
+ return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
+}
+
+// DCOP function
+void
+KCookieServer::addCookies(QString arg1, QCString arg2, long arg3)
+{
+ addCookies(arg1, arg2, arg3, false);
+}
+
+// DCOP function
+void
+KCookieServer::deleteCookie(QString domain, QString fqdn,
+ QString path, QString name)
+{
+ const KHttpCookieList* list = mCookieJar->getCookieList( domain, fqdn );
+ if ( list && !list->isEmpty() )
+ {
+ QPtrListIterator<KHttpCookie>it (*list);
+ for ( ; it.current(); ++it )
+ {
+ if( cookieMatches(it.current(), domain, fqdn, path, name) )
+ {
+ mCookieJar->eatCookie( it.current() );
+ saveCookieJar();
+ break;
+ }
+ }
+ }
+}
+
+// DCOP function
+void
+KCookieServer::deleteCookiesFromDomain(QString domain)
+{
+ mCookieJar->eatCookiesForDomain(domain);
+ saveCookieJar();
+}
+
+
+// Qt function
+void
+KCookieServer::slotDeleteSessionCookies( long windowId )
+{
+ deleteSessionCookies(windowId);
+}
+
+// DCOP function
+void
+KCookieServer::deleteSessionCookies( long windowId )
+{
+ mCookieJar->eatSessionCookies( windowId );
+ saveCookieJar();
+}
+
+void
+KCookieServer::deleteSessionCookiesFor(QString fqdn, long windowId)
+{
+ mCookieJar->eatSessionCookies( fqdn, windowId );
+ saveCookieJar();
+}
+
+// DCOP function
+void
+KCookieServer::deleteAllCookies()
+{
+ mCookieJar->eatAllCookies();
+ saveCookieJar();
+}
+
+// DCOP function
+void
+KCookieServer::addDOMCookies(QString arg1, QCString arg2, long arg3)
+{
+ addCookies(arg1, arg2, arg3, true);
+}
+
+// DCOP function
+void
+KCookieServer::setDomainAdvice(QString url, QString advice)
+{
+ QString fqdn;
+ QString dummy;
+ if (KCookieJar::parseURL(url, fqdn, dummy))
+ {
+ QStringList domains;
+ mCookieJar->extractDomains(fqdn, domains);
+
+ mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
+ KCookieJar::strToAdvice(advice));
+ // Save the cookie config if it has changed
+ mCookieJar->saveConfig( mConfig );
+ }
+}
+
+// DCOP function
+QString
+KCookieServer::getDomainAdvice(QString url)
+{
+ KCookieAdvice advice = KCookieDunno;
+ QString fqdn;
+ QString dummy;
+ if (KCookieJar::parseURL(url, fqdn, dummy))
+ {
+ QStringList domains;
+ mCookieJar->extractDomains(fqdn, domains);
+
+ QStringList::ConstIterator it = domains.begin();
+ while ( (advice == KCookieDunno) && (it != domains.end()) )
+ {
+ // Always check advice in both ".domain" and "domain". Note
+ // that we only want to check "domain" if it matches the
+ // fqdn of the requested URL.
+ if ( (*it)[0] == '.' || (*it) == fqdn )
+ advice = mCookieJar->getDomainAdvice(*it);
+ ++it;
+ }
+ if (advice == KCookieDunno)
+ advice = mCookieJar->getGlobalAdvice();
+ }
+ return KCookieJar::adviceToStr(advice);
+}
+
+// DCOP function
+void
+KCookieServer::reloadPolicy()
+{
+ mCookieJar->loadConfig( mConfig, true );
+}
+
+// DCOP function
+void
+KCookieServer::shutdown()
+{
+ deleteLater();
+}
+
+#include "kcookieserver.moc"
+