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

KIOSlave

  • kioslave
  • http
  • kcookiejar
kcookieserver.cpp
Go to the documentation of this file.
1 /*
2 This file is part of KDE
3 
4  Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 //----------------------------------------------------------------------------
24 //
25 // KDE Cookie Server
26 
27 #include "kcookieserver.h"
28 
29 #define SAVE_DELAY 3 // Save after 3 minutes
30 
31 #include <QtCore/QTimer>
32 #include <QtCore/QFile>
33 #include <QtDBus/QtDBus>
34 
35 #include <kconfig.h>
36 #include <kdebug.h>
37 #include <kcmdlineargs.h>
38 #include <kstandarddirs.h>
39 #include <kpluginfactory.h>
40 #include <kpluginloader.h>
41 #include <kwindowsystem.h>
42 
43 #include "kcookiejar.h"
44 #include "kcookiewin.h"
45 #include "kcookieserveradaptor.h"
46 
47 #define QL1S(x) QLatin1String(x)
48 #define QL1C(x) QLatin1Char(x)
49 
50 K_PLUGIN_FACTORY(KdedCookieServerFactory,
51  registerPlugin<KCookieServer>();
52  )
53 K_EXPORT_PLUGIN(KdedCookieServerFactory("kcookiejar"))
54 
55 // Cookie field indexes
56 enum CookieDetails { CF_DOMAIN=0, CF_PATH, CF_NAME, CF_HOST,
57  CF_VALUE, CF_EXPIRE, CF_PROVER, CF_SECURE };
58 
59 
60 class CookieRequest {
61 public:
62  QDBusMessage reply;
63  QString url;
64  bool DOM;
65  qlonglong windowId;
66 };
67 
68 template class QList<CookieRequest*>;
69 
70 class RequestList : public QList<CookieRequest*>
71 {
72 public:
73  RequestList() : QList<CookieRequest*>() { }
74 };
75 
76 KCookieServer::KCookieServer(QObject* parent, const QList<QVariant>&)
77  : KDEDModule(parent)
78 {
79  (void)new KCookieServerAdaptor(this);
80  mCookieJar = new KCookieJar;
81  mPendingCookies = new KHttpCookieList;
82  mRequestList = new RequestList;
83  mAdvicePending = false;
84  mTimer = new QTimer();
85  mTimer->setSingleShot(true);
86  connect(mTimer, SIGNAL(timeout()), SLOT(slotSave()));
87  mConfig = new KConfig("kcookiejarrc");
88  mCookieJar->loadConfig( mConfig );
89 
90  const QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies");
91 
92  // Stay backwards compatible!
93  const QString filenameOld = KStandardDirs::locate("data", "kfm/cookies");
94  if (!filenameOld.isEmpty())
95  {
96  mCookieJar->loadCookies( filenameOld );
97  if (mCookieJar->saveCookies( filename))
98  {
99  QFile::remove(filenameOld); // Remove old kfm cookie file
100  }
101  }
102  else
103  {
104  mCookieJar->loadCookies( filename);
105  }
106  connect(this, SIGNAL(windowUnregistered(qlonglong)),
107  this, SLOT(slotDeleteSessionCookies(qlonglong)));
108 }
109 
110 KCookieServer::~KCookieServer()
111 {
112  slotSave();
113  delete mCookieJar;
114  delete mTimer;
115  delete mPendingCookies;
116  delete mConfig;
117 }
118 
119 bool KCookieServer::cookiesPending( const QString &url, KHttpCookieList *cookieList )
120 {
121  QString fqdn;
122  QString path;
123  // Check whether 'url' has cookies on the pending list
124  if (mPendingCookies->isEmpty())
125  return false;
126  if (!KCookieJar::parseUrl(url, fqdn, path))
127  return false;
128 
129  QStringList domains;
130  mCookieJar->extractDomains(fqdn, domains);
131  Q_FOREACH(const KHttpCookie& cookie, *mPendingCookies) {
132  if (cookie.match( fqdn, domains, path)) {
133  if (!cookieList)
134  return true;
135  cookieList->append(cookie);
136  }
137  }
138  if (!cookieList)
139  return false;
140  return cookieList->isEmpty();
141 }
142 
143 void KCookieServer::addCookies( const QString &url, const QByteArray &cookieHeader,
144  qlonglong windowId, bool useDOMFormat )
145 {
146  KHttpCookieList cookieList;
147  if (useDOMFormat)
148  cookieList = mCookieJar->makeDOMCookies(url, cookieHeader, windowId);
149  else
150  cookieList = mCookieJar->makeCookies(url, cookieHeader, windowId);
151 
152  checkCookies(&cookieList, windowId);
153 
154  *mPendingCookies += cookieList;
155 
156  if (!mAdvicePending)
157  {
158  mAdvicePending = true;
159  while (!mPendingCookies->isEmpty())
160  {
161  checkCookies(0, windowId);
162  }
163  mAdvicePending = false;
164  }
165 }
166 
167 void KCookieServer::checkCookies(KHttpCookieList *cookieList)
168 {
169  checkCookies(cookieList, 0);
170 }
171 
172 void KCookieServer::checkCookies(KHttpCookieList *cookieList, qlonglong windowId)
173 {
174  KHttpCookieList *list;
175 
176  if (cookieList)
177  list = cookieList;
178  else
179  list = mPendingCookies;
180 
181  QMutableListIterator<KHttpCookie> cookieIterator(*list);
182  while (cookieIterator.hasNext()) {
183  KHttpCookie& cookie = cookieIterator.next();
184  const KCookieAdvice advice = mCookieJar->cookieAdvice(cookie);
185  switch(advice) {
186  case KCookieAccept:
187  mCookieJar->addCookie(cookie);
188  cookieIterator.remove();
189  break;
190  case KCookieReject:
191  cookieIterator.remove();
192  break;
193  default:
194  break;
195  }
196  }
197 
198  if (cookieList || list->isEmpty())
199  return;
200 
201  // Collect all pending cookies with the same host as the first pending cookie
202  const KHttpCookie& currentCookie = mPendingCookies->first();
203  KHttpCookieList currentList;
204  currentList.append(currentCookie);
205  const QString currentHost = currentCookie.host();
206  QList<int> shownCookies; shownCookies << 0;
207  for (int i = 1 /*first already done*/; i < mPendingCookies->count(); ++i) {
208  const KHttpCookie& cookie = (*mPendingCookies)[i];
209  if (cookie.host() == currentHost) {
210  currentList.append(cookie);
211  shownCookies << i;
212  }
213  }
214  //kDebug() << shownCookies;
215 
216  KCookieWin *kw = new KCookieWin( 0L, currentList,
217  mCookieJar->preferredDefaultPolicy(),
218  mCookieJar->showCookieDetails() );
219  if (windowId > 0) {
220 #ifndef Q_WS_WIN
221  KWindowSystem::setMainWindow(kw, static_cast<WId>(windowId));
222 #else
223  KWindowSystem::setMainWindow(kw, (HWND)(long)windowId);
224 #endif
225  }
226 
227  KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
228  delete kw;
229  // Save the cookie config if it has changed
230  mCookieJar->saveConfig( mConfig );
231 
232  // Apply the user's choice to all cookies that are currently
233  // queued for this host (or just the first one, if the user asks for that).
234  QMutableListIterator<KHttpCookie> cookieIterator2(*mPendingCookies);
235  int pendingCookieIndex = -1;
236  while (cookieIterator2.hasNext()) {
237  ++pendingCookieIndex;
238  KHttpCookie& cookie = cookieIterator2.next();
239  if (cookie.host() != currentHost)
240  continue;
241  if (mCookieJar->preferredDefaultPolicy() == KCookieJar::ApplyToShownCookiesOnly
242  && !shownCookies.contains(pendingCookieIndex)) {
243  // User chose "only those cookies", and this one was added while the dialog was up -> skip
244  break;
245  }
246  switch(userAdvice) {
247  case KCookieAccept:
248  mCookieJar->addCookie(cookie);
249  cookieIterator2.remove();
250  break;
251 
252  case KCookieReject:
253  cookieIterator2.remove();
254  break;
255 
256  default:
257  kWarning() << "userAdvice not accept or reject, this should never happen!";
258  break;
259  }
260  }
261 
262  // Check if we can handle any request
263  QMutableListIterator<CookieRequest *> requestIterator(*mRequestList);
264  while (requestIterator.hasNext()) {
265  CookieRequest *request = requestIterator.next();
266  if (!cookiesPending(request->url)) {
267  const QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId);
268 
269  QDBusConnection::sessionBus().send(request->reply.createReply(res));
270  delete request;
271  requestIterator.remove();
272  }
273  }
274 
275  saveCookieJar();
276 }
277 
278 void KCookieServer::slotSave()
279 {
280  if (mCookieJar->changed())
281  {
282  QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies");
283  mCookieJar->saveCookies(filename);
284  }
285 }
286 
287 void KCookieServer::saveCookieJar()
288 {
289  if( mTimer->isActive() )
290  return;
291 
292  mTimer->start( 1000*60*SAVE_DELAY );
293 }
294 
295 void KCookieServer::putCookie( QStringList& out, const KHttpCookie& cookie,
296  const QList<int>& fields )
297 {
298  foreach ( int i, fields ) {
299  switch(i)
300  {
301  case CF_DOMAIN :
302  out << cookie.domain();
303  break;
304  case CF_NAME :
305  out << cookie.name();
306  break;
307  case CF_PATH :
308  out << cookie.path();
309  break;
310  case CF_HOST :
311  out << cookie.host();
312  break;
313  case CF_VALUE :
314  out << cookie.value();
315  break;
316  case CF_EXPIRE :
317  out << QString::number(cookie.expireDate());
318  break;
319  case CF_PROVER :
320  out << QString::number(cookie.protocolVersion());
321  break;
322  case CF_SECURE :
323  out << QString::number(cookie.isSecure() ? 1 : 0);
324  break;
325  default :
326  out << QString();
327  }
328  }
329 }
330 
331 bool KCookieServer::cookieMatches(const KHttpCookie& c,
332  const QString &domain, const QString &fqdn,
333  const QString &path, const QString &name)
334 {
335  const bool hasDomain = !domain.isEmpty();
336  return (((hasDomain && c.domain() == domain) || fqdn == c.host()) &&
337  (c.path() == path) && (c.name() == name) &&
338  (!c.isExpired()));
339 }
340 
341 
342 // DBUS function
343 QString KCookieServer::listCookies(const QString &url)
344 {
345  return findCookies(url, 0);
346 }
347 
348 // DBUS function
349 QString KCookieServer::findCookies(const QString &url, qlonglong windowId)
350 {
351  if (cookiesPending(url))
352  {
353  CookieRequest *request = new CookieRequest;
354  message().setDelayedReply(true);
355  request->reply = message();
356  request->url = url;
357  request->DOM = false;
358  request->windowId = windowId;
359  mRequestList->append( request );
360  return QString(); // Talk to you later :-)
361  }
362 
363  QString cookies = mCookieJar->findCookies(url, false, windowId);
364  saveCookieJar();
365  return cookies;
366 }
367 
368 // DBUS function
369 QStringList
370 KCookieServer::findDomains()
371 {
372  QStringList result;
373  Q_FOREACH(const QString& domain, mCookieJar->getDomainList())
374  {
375  // Ignore domains that have policy set for but contain
376  // no cookies whatsoever...
377  const KHttpCookieList* list = mCookieJar->getCookieList(domain, "");
378  if ( list && !list->isEmpty() )
379  result << domain;
380  }
381  return result;
382 }
383 
384 // DBUS function
385 QStringList
386 KCookieServer::findCookies(const QList<int> &fields,
387  const QString &_domain,
388  const QString &fqdn,
389  const QString &path,
390  const QString &name)
391 {
392  QStringList result;
393  const bool allCookies = name.isEmpty();
394  const QStringList domainList = _domain.split(QLatin1Char(' '));
395 
396  if (allCookies)
397  {
398  Q_FOREACH(const QString& domain, domainList)
399  {
400  const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
401  if (!list)
402  continue;
403  Q_FOREACH(const KHttpCookie& cookie, *list)
404  {
405  if (cookie.isExpired())
406  continue;
407  putCookie(result, cookie, fields);
408  }
409  }
410  }
411  else
412  {
413  Q_FOREACH(const QString& domain, domainList)
414  {
415  const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
416  if (!list)
417  continue;
418  Q_FOREACH(const KHttpCookie& cookie, *list)
419  {
420  if (cookie.isExpired())
421  continue;
422  if (cookieMatches(cookie, domain, fqdn, path, name))
423  {
424  putCookie(result, cookie, fields);
425  break;
426  }
427  }
428  }
429  }
430 
431  return result;
432 }
433 
434 // DBUS function
435 QString
436 KCookieServer::findDOMCookies(const QString &url)
437 {
438  return findDOMCookies(url, 0);
439 }
440 
441 // DBUS function
442 QString
443 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
444 {
445  // We don't wait for pending cookies because it locks up konqueror
446  // which can cause a deadlock if it happens to have a popup-menu up.
447  // Instead we just return pending cookies as if they had been accepted already.
448  KHttpCookieList pendingCookies;
449  cookiesPending(url, &pendingCookies);
450 
451  return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
452 }
453 
454 // DBUS function
455 void
456 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
457 {
458  addCookies(arg1, arg2, arg3, false);
459 }
460 
461 // DBUS function
462 void
463 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn,
464  const QString &path, const QString &name)
465 {
466  KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn );
467  if (cookieList && !cookieList->isEmpty()) {
468  KHttpCookieList::Iterator itEnd = cookieList->end();
469  for (KHttpCookieList::Iterator it = cookieList->begin(); it != itEnd; ++it)
470  {
471  if (cookieMatches(*it, domain, fqdn, path, name)) {
472  mCookieJar->eatCookie(it);
473  saveCookieJar();
474  break;
475  }
476  }
477  }
478 }
479 
480 // DBUS function
481 void
482 KCookieServer::deleteCookiesFromDomain(const QString &domain)
483 {
484  mCookieJar->eatCookiesForDomain(domain);
485  saveCookieJar();
486 }
487 
488 
489 // Qt function
490 void
491 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
492 {
493  deleteSessionCookies(windowId);
494 }
495 
496 // DBUS function
497 void
498 KCookieServer::deleteSessionCookies( qlonglong windowId )
499 {
500  mCookieJar->eatSessionCookies( windowId );
501  saveCookieJar();
502 }
503 
504 void
505 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId)
506 {
507  mCookieJar->eatSessionCookies( fqdn, windowId );
508  saveCookieJar();
509 }
510 
511 // DBUS function
512 void
513 KCookieServer::deleteAllCookies()
514 {
515  mCookieJar->eatAllCookies();
516  saveCookieJar();
517 }
518 
519 // DBUS function
520 void
521 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
522 {
523  addCookies(url, cookieHeader, windowId, true);
524 }
525 
526 // DBUS function
527 bool
528 KCookieServer::setDomainAdvice(const QString &url, const QString &advice)
529 {
530  QString fqdn;
531  QString dummy;
532  if (KCookieJar::parseUrl(url, fqdn, dummy))
533  {
534  QStringList domains;
535  mCookieJar->extractDomains(fqdn, domains);
536 
537  mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
538  KCookieJar::strToAdvice(advice));
539  // Save the cookie config if it has changed
540  mCookieJar->saveConfig( mConfig );
541  return true;
542  }
543  return false;
544 }
545 
546 // DBUS function
547 QString
548 KCookieServer::getDomainAdvice(const QString &url)
549 {
550  KCookieAdvice advice = KCookieDunno;
551  QString fqdn;
552  QString dummy;
553  if (KCookieJar::parseUrl(url, fqdn, dummy))
554  {
555  QStringList domains;
556  mCookieJar->extractDomains(fqdn, domains);
557 
558  QStringListIterator it (domains);
559  while ( (advice == KCookieDunno) && it.hasNext() )
560  {
561  // Always check advice in both ".domain" and "domain". Note
562  // that we only want to check "domain" if it matches the
563  // fqdn of the requested URL.
564  const QString& domain = it.next();
565  if ( domain.at(0) == '.' || domain == fqdn )
566  advice = mCookieJar->getDomainAdvice(domain);
567  }
568  if (advice == KCookieDunno)
569  advice = mCookieJar->getGlobalAdvice();
570  }
571  return KCookieJar::adviceToStr(advice);
572 }
573 
574 // DBUS function
575 void
576 KCookieServer::reloadPolicy()
577 {
578  mCookieJar->loadConfig( mConfig, true );
579 }
580 
581 // DBUS function
582 void
583 KCookieServer::shutdown()
584 {
585  deleteLater();
586 }
587 
588 #include "kcookieserver.moc"
589 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Thu Feb 21 2013 11:13:57 by doxygen 1.8.1 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.5 API Reference

Skip menu "kdelibs-4.8.5 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