• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.11.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  case KCookieAcceptForSession:
188  mCookieJar->addCookie(cookie);
189  cookieIterator.remove();
190  break;
191  case KCookieReject:
192  cookieIterator.remove();
193  break;
194  default:
195  break;
196  }
197  }
198 
199  if (cookieList || list->isEmpty())
200  return;
201 
202  // Collect all pending cookies with the same host as the first pending cookie
203  const KHttpCookie& currentCookie = mPendingCookies->first();
204  KHttpCookieList currentList;
205  currentList.append(currentCookie);
206  const QString currentHost = currentCookie.host();
207  QList<int> shownCookies; shownCookies << 0;
208  for (int i = 1 /*first already done*/; i < mPendingCookies->count(); ++i) {
209  const KHttpCookie& cookie = (*mPendingCookies)[i];
210  if (cookie.host() == currentHost) {
211  currentList.append(cookie);
212  shownCookies << i;
213  }
214  }
215  //kDebug() << shownCookies;
216 
217  KCookieWin *kw = new KCookieWin( 0L, currentList,
218  mCookieJar->preferredDefaultPolicy(),
219  mCookieJar->showCookieDetails() );
220  if (windowId > 0) {
221 #ifndef Q_WS_WIN
222  KWindowSystem::setMainWindow(kw, static_cast<WId>(windowId));
223 #else
224  KWindowSystem::setMainWindow(kw, (HWND)(long)windowId);
225 #endif
226  }
227 
228  KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
229  delete kw;
230  // Save the cookie config if it has changed
231  mCookieJar->saveConfig( mConfig );
232 
233  // Apply the user's choice to all cookies that are currently
234  // queued for this host (or just the first one, if the user asks for that).
235  QMutableListIterator<KHttpCookie> cookieIterator2(*mPendingCookies);
236  int pendingCookieIndex = -1;
237  while (cookieIterator2.hasNext()) {
238  ++pendingCookieIndex;
239  KHttpCookie& cookie = cookieIterator2.next();
240  if (cookie.host() != currentHost)
241  continue;
242  if (mCookieJar->preferredDefaultPolicy() == KCookieJar::ApplyToShownCookiesOnly
243  && !shownCookies.contains(pendingCookieIndex)) {
244  // User chose "only those cookies", and this one was added while the dialog was up -> skip
245  break;
246  }
247  switch(userAdvice) {
248  case KCookieAccept:
249  case KCookieAcceptForSession:
250  // Store the user's choice for the cookie.
251  // This is only used to check later if the cookie should expire
252  // at the end of the session. The choice is not saved on disk.
253  cookie.setUserSelectedAdvice(userAdvice);
254  mCookieJar->addCookie(cookie);
255  cookieIterator2.remove();
256  break;
257 
258  case KCookieReject:
259  cookieIterator2.remove();
260  break;
261 
262  default:
263  kWarning() << "userAdvice not accept or reject, this should never happen!";
264  break;
265  }
266  }
267 
268  // Check if we can handle any request
269  QMutableListIterator<CookieRequest *> requestIterator(*mRequestList);
270  while (requestIterator.hasNext()) {
271  CookieRequest *request = requestIterator.next();
272  if (!cookiesPending(request->url)) {
273  const QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId);
274 
275  QDBusConnection::sessionBus().send(request->reply.createReply(res));
276  delete request;
277  requestIterator.remove();
278  }
279  }
280 
281  saveCookieJar();
282 }
283 
284 void KCookieServer::slotSave()
285 {
286  if (mCookieJar->changed())
287  {
288  QString filename = KStandardDirs::locateLocal("data", "kcookiejar/cookies");
289  mCookieJar->saveCookies(filename);
290  }
291 }
292 
293 void KCookieServer::saveCookieJar()
294 {
295  if( mTimer->isActive() )
296  return;
297 
298  mTimer->start( 1000*60*SAVE_DELAY );
299 }
300 
301 void KCookieServer::putCookie( QStringList& out, const KHttpCookie& cookie,
302  const QList<int>& fields )
303 {
304  foreach ( int i, fields ) {
305  switch(i)
306  {
307  case CF_DOMAIN :
308  out << cookie.domain();
309  break;
310  case CF_NAME :
311  out << cookie.name();
312  break;
313  case CF_PATH :
314  out << cookie.path();
315  break;
316  case CF_HOST :
317  out << cookie.host();
318  break;
319  case CF_VALUE :
320  out << cookie.value();
321  break;
322  case CF_EXPIRE :
323  out << QString::number(cookie.expireDate());
324  break;
325  case CF_PROVER :
326  out << QString::number(cookie.protocolVersion());
327  break;
328  case CF_SECURE :
329  out << QString::number(cookie.isSecure() ? 1 : 0);
330  break;
331  default :
332  out << QString();
333  }
334  }
335 }
336 
337 bool KCookieServer::cookieMatches(const KHttpCookie& c,
338  const QString &domain, const QString &fqdn,
339  const QString &path, const QString &name)
340 {
341  const bool hasDomain = !domain.isEmpty();
342  return (((hasDomain && c.domain() == domain) || fqdn == c.host()) &&
343  (c.path() == path) && (c.name() == name) &&
344  (!c.isExpired()));
345 }
346 
347 
348 // DBUS function
349 QString KCookieServer::listCookies(const QString &url)
350 {
351  return findCookies(url, 0);
352 }
353 
354 // DBUS function
355 QString KCookieServer::findCookies(const QString &url, qlonglong windowId)
356 {
357  if (cookiesPending(url))
358  {
359  CookieRequest *request = new CookieRequest;
360  message().setDelayedReply(true);
361  request->reply = message();
362  request->url = url;
363  request->DOM = false;
364  request->windowId = windowId;
365  mRequestList->append( request );
366  return QString(); // Talk to you later :-)
367  }
368 
369  QString cookies = mCookieJar->findCookies(url, false, windowId);
370  saveCookieJar();
371  return cookies;
372 }
373 
374 // DBUS function
375 QStringList
376 KCookieServer::findDomains()
377 {
378  QStringList result;
379  Q_FOREACH(const QString& domain, mCookieJar->getDomainList())
380  {
381  // Ignore domains that have policy set for but contain
382  // no cookies whatsoever...
383  const KHttpCookieList* list = mCookieJar->getCookieList(domain, "");
384  if ( list && !list->isEmpty() )
385  result << domain;
386  }
387  return result;
388 }
389 
390 // DBUS function
391 QStringList
392 KCookieServer::findCookies(const QList<int> &fields,
393  const QString &_domain,
394  const QString &fqdn,
395  const QString &path,
396  const QString &name)
397 {
398  QStringList result;
399  const bool allCookies = name.isEmpty();
400  const QStringList domainList = _domain.split(QLatin1Char(' '));
401 
402  if (allCookies)
403  {
404  Q_FOREACH(const QString& domain, domainList)
405  {
406  const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
407  if (!list)
408  continue;
409  Q_FOREACH(const KHttpCookie& cookie, *list)
410  {
411  if (cookie.isExpired())
412  continue;
413  putCookie(result, cookie, fields);
414  }
415  }
416  }
417  else
418  {
419  Q_FOREACH(const QString& domain, domainList)
420  {
421  const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
422  if (!list)
423  continue;
424  Q_FOREACH(const KHttpCookie& cookie, *list)
425  {
426  if (cookie.isExpired())
427  continue;
428  if (cookieMatches(cookie, domain, fqdn, path, name))
429  {
430  putCookie(result, cookie, fields);
431  break;
432  }
433  }
434  }
435  }
436 
437  return result;
438 }
439 
440 // DBUS function
441 QString
442 KCookieServer::findDOMCookies(const QString &url)
443 {
444  return findDOMCookies(url, 0);
445 }
446 
447 // DBUS function
448 QString
449 KCookieServer::findDOMCookies(const QString &url, qlonglong windowId)
450 {
451  // We don't wait for pending cookies because it locks up konqueror
452  // which can cause a deadlock if it happens to have a popup-menu up.
453  // Instead we just return pending cookies as if they had been accepted already.
454  KHttpCookieList pendingCookies;
455  cookiesPending(url, &pendingCookies);
456 
457  return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
458 }
459 
460 // DBUS function
461 void
462 KCookieServer::addCookies(const QString &arg1, const QByteArray &arg2, qlonglong arg3)
463 {
464  addCookies(arg1, arg2, arg3, false);
465 }
466 
467 // DBUS function
468 void
469 KCookieServer::deleteCookie(const QString &domain, const QString &fqdn,
470  const QString &path, const QString &name)
471 {
472  KHttpCookieList* cookieList = mCookieJar->getCookieList( domain, fqdn );
473  if (cookieList && !cookieList->isEmpty()) {
474  KHttpCookieList::Iterator itEnd = cookieList->end();
475  for (KHttpCookieList::Iterator it = cookieList->begin(); it != itEnd; ++it)
476  {
477  if (cookieMatches(*it, domain, fqdn, path, name)) {
478  mCookieJar->eatCookie(it);
479  saveCookieJar();
480  break;
481  }
482  }
483  }
484 }
485 
486 // DBUS function
487 void
488 KCookieServer::deleteCookiesFromDomain(const QString &domain)
489 {
490  mCookieJar->eatCookiesForDomain(domain);
491  saveCookieJar();
492 }
493 
494 
495 // Qt function
496 void
497 KCookieServer::slotDeleteSessionCookies( qlonglong windowId )
498 {
499  deleteSessionCookies(windowId);
500 }
501 
502 // DBUS function
503 void
504 KCookieServer::deleteSessionCookies( qlonglong windowId )
505 {
506  mCookieJar->eatSessionCookies( windowId );
507  saveCookieJar();
508 }
509 
510 void
511 KCookieServer::deleteSessionCookiesFor(const QString &fqdn, qlonglong windowId)
512 {
513  mCookieJar->eatSessionCookies( fqdn, windowId );
514  saveCookieJar();
515 }
516 
517 // DBUS function
518 void
519 KCookieServer::deleteAllCookies()
520 {
521  mCookieJar->eatAllCookies();
522  saveCookieJar();
523 }
524 
525 // DBUS function
526 void
527 KCookieServer::addDOMCookies(const QString &url, const QByteArray &cookieHeader, qlonglong windowId)
528 {
529  addCookies(url, cookieHeader, windowId, true);
530 }
531 
532 // DBUS function
533 bool
534 KCookieServer::setDomainAdvice(const QString &url, const QString &advice)
535 {
536  QString fqdn;
537  QString dummy;
538  if (KCookieJar::parseUrl(url, fqdn, dummy))
539  {
540  QStringList domains;
541  mCookieJar->extractDomains(fqdn, domains);
542 
543  mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
544  KCookieJar::strToAdvice(advice));
545  // Save the cookie config if it has changed
546  mCookieJar->saveConfig( mConfig );
547  return true;
548  }
549  return false;
550 }
551 
552 // DBUS function
553 QString
554 KCookieServer::getDomainAdvice(const QString &url)
555 {
556  KCookieAdvice advice = KCookieDunno;
557  QString fqdn;
558  QString dummy;
559  if (KCookieJar::parseUrl(url, fqdn, dummy))
560  {
561  QStringList domains;
562  mCookieJar->extractDomains(fqdn, domains);
563 
564  QStringListIterator it (domains);
565  while ( (advice == KCookieDunno) && it.hasNext() )
566  {
567  // Always check advice in both ".domain" and "domain". Note
568  // that we only want to check "domain" if it matches the
569  // fqdn of the requested URL.
570  const QString& domain = it.next();
571  if ( domain.at(0) == '.' || domain == fqdn )
572  advice = mCookieJar->getDomainAdvice(domain);
573  }
574  if (advice == KCookieDunno)
575  advice = mCookieJar->getGlobalAdvice();
576  }
577  return KCookieJar::adviceToStr(advice);
578 }
579 
580 // DBUS function
581 void
582 KCookieServer::reloadPolicy()
583 {
584  mCookieJar->loadConfig( mConfig, true );
585 }
586 
587 // DBUS function
588 void
589 KCookieServer::shutdown()
590 {
591  deleteLater();
592 }
593 
594 #include "kcookieserver.moc"
595 
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Mon May 5 2014 18:17:22 by doxygen 1.8.3.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.11.5 API Reference

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